Your achievements

Level 1

0% to

Level 2

Tip /
Sign in

Sign in to Community

to gain points, level up, and earn exciting badges like the new
Bedrock Mission!

Learn more

View all

Sign in to view all badges

Call a servlet (GET request) from Sling model

dopamine7
Level 2
Level 2

All,

 

I have a deployed servlet in AEM that returns JSON result from external endpoint.

My use case is to call this servlet deployed in AEM with a GET request from a sling model (same AEM instance) to get this json result.

The issue is that its working in localhost but in Azure environements AEM instances i am getting a timeout on calling the servlet.

I tried changing the lib for requesting the servlet (HttpConnection, HttpClient, Jsoup, ...) but still i am getting a timeout.

When calling directly the path of the servlet without passing in the different environmnt i am getting correctly the JSON response.

My thoughts that AEM instance in (dev, stage) environments is blocking the internal call to the servlet (/bin/tests/test).

 

PS:

- i have tried using directly publish ip adress to avoid the dispatcher but i get the same issue.

- an OSGI Service istead of the servlet is working but i still need the use of servlet for caching the query and result easily.

 

Any idea of the cause and a possible solution ?

 

Best regards,

 

10 Replies
lukaszm
Level 8
Level 8

Hi @dopamine7, in my opinion you should not call servlet from your sling model - I think this is not a good practice. Instead if you need to run some operation from servlet and sling model you can extract your logic into separate class i.e. OSGi service and use it in all other classes. This should eliminate situation when you're calling servlet from sling model directly. If I good understand what you need is data from external service that are currently exposed by your servlet. You can try to refactor you code like below.

 

@Component(name = "OSGi service with your logic", service = MyService.class)
public class YourService {

    // place for your service methods that will run business logic
    public void doSomething(String param1, String param2) {
        // ...
    }

    //...
}
@Component(service = Servlet.class, property = {
        "sling.servlet.methods=GET", "sling.servlet.paths=/bin/path/to/your/servlet"})
public class YourServlet extends SlingSafeMethodsServlet {

    @Reference
    private transient YourService yourService;

    @Override
    protected void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response) {
        yourService.doSomething(param1, param2);
        // ...
    }

    // ...
}
@Model(adaptables = Resource.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class YourSlingModel {

    @OSGiService
    private YourService yourService;

    // ...
}

 

As you can see above approach assure separation between business logic and classes where you need to access results provided by business logic class.

dopamine7
Level 2
Level 2

i need to use only the servlet from the sling model, they are no needs to request it seperately. The need from the use of the servlet is for caching the query and response easily.

I already tried passing by an OSGI Service and it works already but i have to implement a specific cache service to handle it which it complicate it for my use case.

It would be appreciable staying with the servlet call from the sling model to facilitate the caching

lukaszm
Level 8
Level 8

So just be clear - by cache you mean cache on dispatcher, right? How you are using data on sling model, and sling model itself. Did you consider instead of using servlet accessible by path to correlate it with specific resource type i.e. the same as sling model and add some selector? This potentially could eliminate need of calling servlet from sling model, and in the same time to use servlet in general and dispatcher cache.

dopamine7
Level 2
Level 2

yes i mean dispatcher cache, to be clear :

Assuming that servlet path is : /bin/tests/test

SlingModel gets contribution from component (City : madrid) -> sends a  GET Request to sling servlet (/bin/tests/test.madrid.json) -> The servlet call an endpoint and receive a json response -> SlingModel uses that response 

lukaszm
Level 8
Level 8

So the city value is manually configured by author, right? And you including this as a selector in your servlet request.

 

I am going into direction that if in the end the content on the page is static, maybe as alternative you can cache the page with results of your component, this will also allow you to easily invalidate the cache. This will allow you to use osgi service reference instead of servlet call, and you still can benefit from using dispatcher cache.

dopamine7
Level 2
Level 2

Yes, the city is contribuated via a content fragment inside the component.

The issue of that is that we have to cache the entire page because it contains other dynamic components that we don't need to cache.

Thank u again for ur responses and time 🙂

milind_bachani
Level 5
Level 5

@dopamine7 I agree to what @lukaszm says and its not a good practice to call a servlet from a model.
The approach mentioned using service makes more sense and however, you can achieve the same functionality by using the service. Calling a servlet inside a model is a dirty implementation to me.

Morpheus_1729
Level 2
Level 2

The timeout could be due to the performance of the query you are using to warm up your cache in the Azure Environments.

Morpheus_1729
Level 2
Level 2

Please check the Query Performance/Easy Query in Operations Cosole.