0

I am working in Sling framework with OSGi DS annotations.

Background: I am working with micro services. When we send calls between them, we pass around and log a "transaction ID" (which is just a UUID). That way we can easily trace calls between all the different services. This means each web request has a different UUID. We typically use Spring Boot, but in this case I am in AEM using Sling.

Problem: I can't seem to create my own "web request scoped" osgi component. I have tried setting it up as a Prototype service scope, but it just isn't working. Below is an example of what I think should be working, but it isn't because in my "service" class, I get a different instance of the RequestInfo class than from when I get the instance in the Filter class.

Request scoped object:

@Component(service = RequestInfo.class, scope = ServiceScope.PROTOTYPE)
public class RequestInfo {
     private String transactionId;
     ...
}

Filter:

@Component(service = Filter.class, immediate = true, property = { sling.filter.scope=REQUEST })
@ServiceRanking(0)
public class RequestInfoFilter implements Filter {
     @Reference(scope = ReferenceScope.PROTOTYPE_REQUIRED)
     private RequestInfo requestInfo;

     @Override
     public void doFilter(ServletRequest baseRequest, ServletResponse baseResponse, FilterChain filterChain) {
          HttpServletRequest request = (HttpServletRequest) baseRequest;
          HttpServletResponse response = (HttpServletResponse) baseResponse;
          requestInfo.setTransactionId(...);
          filterChain.doFilter(request, response);
     }
     ...
}

Service class:

@Component(service = MyService.class, immediate = true)
public class MyService {
     @Reference(scope = ReferenceScope.PROTOTYPE_REQUIRED)
     private RequestInfo requestInfo; <--- Does not pick up same instance of RequestInfo that filter had!!! Why??? It's still in the context of the same request!!!

     public String callAnotherService {
          String transactionID = requestInfo.getTransactionId();
          ... add ID as header and call another service with httpclient ...
     }
 }

Other attempted solutions:

  • I tried to reference the SlingHttpServletRequest object inside a Component but it just did not work unless I'm extending SlingAllMethodsServlet, which is not appropriate for a Service class.
  • I tried setting up a SlingModel which holds info from the request, but then I can't figure out how to pull in the instance of that SlingModel into an OSGI Component.

My fallback solution which I do not like:
I could just pull the transaction ID out in my Servlet and pass between all the various classes/methods until I reach the Service class, but that's kind of crap.

Can anyone help please?

Shea
  • 47
  • 1
  • 4

1 Answers1

0

Maybe this will help you http://blog.vogella.com/2017/02/13/control-osgi-ds-component-instances/

Setting the scope of the service component to PROTOTYPE does not mean that every consumer gets a distinct service instance automatically. By default the result will be the same as with using the BUNDLE scope. So if you start the application with the updated Hitman service, you will get the same result as before. The reason for this is the reference scope that was also introduced with DS 1.3. It is configured on the consumer side via @Reference and specifies how the service reference should be resolved. There are three possible values:

BUNDLE All component instances in a bundle will use the same service object. (default) PROTOTYPE Every component instance in a bundle may use a distinct service object. PROTOTYPE_REQUIRED Every component instance in a bundle must use a distinct service object.

mkovacek
  • 310
  • 2
  • 15