Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.
SOLVED

How to access sling request object in OSGI Service

Avatar

Level 5

Hello,

 

Could you please suggest how I can access request object in an OSGI Service ?

 

I tried @reference SlingHttpServletRequest request but it is giving null.

 

Thanks,

Ravi Joshi

1 Accepted Solution

Avatar

Correct answer by
Level 6

@ravi_joshi 

You can try method overloading. Just create a version of the method with an extra parameter to take this field value(which you are injecting in the model). That way it won't affect the existing classes which are using the same method.

View solution in original post

11 Replies

Avatar

Community Advisor

Hi @ravi_joshi , I think that the easiest option will be to pass request object as part of method parameter which rely on request i.e

@Component(service = MyService.class)
public class MyServiceImpl implements MyService {

    public void processRequest(SlingHttpServletRequest request) {
     // place for your logic that will use request object
    }
}

By default OSGi services are not request aware, with some exception like filters or servlets that works in request context and have direct access to request object. What kind of data would you like to retrieve from request - maybe you can get them in other way?

Avatar

Level 5

Hi @lukasz-m ,

 

Thank you for such a quick response . And The answer was very insightful. And my apologies that I forgot to mention that we cannot change method signature to pass request parameter.

 

Situation is, that I have sling model with a dialog field injected to it and I want to use that field value in a OSGi service method when it is getting called. But as I said I cannot change method signature that is out of scope.

So I thought of using that field as an request attribute by setting it in model and use it in the service as needed.

But as you said OSGI services are not request aware so that solution will not work. 

Could you please provide your suggestions on the similer approach ?

One more thing that we have resource resolver available.

 

Thanks,

Ravi Joshi

Avatar

Community Advisor

Hi @ravi_joshi, thanks for sharing wider context. If you can't change method signature, then I would suggest following approach. Try add additional method in your OSGi service that will allow to transfer request object to your service. This will eliminate need of changing signature of existing methods. It is not the ideal solution but should give you what you need. Below you can find some quasi code, that illustrates what I am proposing. You can also consider to create setter for value you would like to pass to your OSGi service, instead of adding it as an request attribute and pass request object - but the concept will be the same.

 

Code of Sling model

@Model(...)
public class MyModel {

   @Self   
   private SlingHttpServletRequest request;

// your existing OSGi service @OSGiService private MyService myService; public void method() {
// new method tho set request object myService.setRequest(request);

// existing method
myService.methodA(); } }

Code of OSGi service

@Component(service = MyService.class)
public class MyServiceImpl implements MyService {

    // variable that will store request object
    private SlingHttpServletRequest request;

    // existing method
    public void methodA() {
       // place for your logic that will use request object
    
       if (request != null) {
          // some request related logic
       }
    }

    // new method to set request object
    public void setRequest(SlingHttpServletRequest request) {
       this.request = request;   
    }
}

Avatar

Level 6

You can pass the request object from the servlet from where you are calling the service.

Avatar

Level 5

Hi @ibishika ,

 

Thank you for such a quick response. As I mentioned in the above reply  changing method signature is out of scope.

 

Could you please provide your suggestions on the same approach ?

 

Like how I can transfer a value from model to OSGI service without changing method signature.

 

We have only resource resolver available and we cannot change method signature.

 

Thanks,

Ravi Joshi

Avatar

Community Advisor

@ravi_joshi,

I would like to understand how you're trying to invoke your OSGI service?

Is it from component HTML or Sling model or Servlet or scheduler or any other area?    1. If it is from Sling model then you can access 

         @Self
          private SlingHttpServletRequest request;

    2. If it is from servlet then you can invoke servlet by resourceType or Path and then access request object 

@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
response.getWriter().println(this.slingSettingsService.getRunModes().contains("publish"));
}

3. If it is from HTML, then you have to call your service using  as shown below then access resourceresolver object and you can get the resource object.

          <sly data-sly-use.info="com.test.utils.TestPojoComp">

           ${info.details}

          </sly>

Implement Details method in your service and get the resource path using resource resolver factory.

 

Let me know if you have any questions.

Thanks,

Aruna

 

 

 

Avatar

Level 5

Hi @Aruna_surukunta_  ,

 

The above answer was very insightful. And sorry I forgot to mention that we cannot change method signature.

 

Situation is, that I have a sling model with a dialog field injected to it and I want to use that field value in an OSGi service method when that method is is getting called in the service. But as I said I cannot change method signature.

 

So I thought of using that field as an request attribute by setting it in the request object inside the model and use it in the service whenever needed.

 

Could you please your suggestions on the similer approach ?

 

One more thing that we have resource resolver available.

 

Thanks,

Ravi Joshi

Avatar

Level 6

@ravi_joshi  I need answer to two questions in order to understand the scenario better.

1. How the service is being triggered? Is it happening from some other source?

2. Are you planning to use the component only once in each page?

Avatar

Level 5

 Hi @ibishika 

 

1. No, we are Injecting the service in model using @OSGIService and then we calling a method of that service in model itself. The reason we are not changing signature is that the perticular service  has a lot of references in the code. So we are tring to avoid that much change impact.

 

2. No, component can be used multiple times on the page. 

 

Thanks,

Ravi Joshi

Avatar

Correct answer by
Level 6

@ravi_joshi 

You can try method overloading. Just create a version of the method with an extra parameter to take this field value(which you are injecting in the model). That way it won't affect the existing classes which are using the same method.

Avatar

Level 5

Hi @ibishika ,

 

Amazing. Thank you. I think overloading will be useful in this scenerio.

 

Thank you,

Ravi Joshi