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?