How to control OSGi dependency injection in AEM? | Community
Skip to main content
Level 3
November 9, 2017

How to control OSGi dependency injection in AEM?

  • November 9, 2017
  • 2 replies
  • 11669 views

I'm trying to understand how dependency injection works in OSGi (specifically Apache Felix as used in AEM). I have a servlet with an `@Reference` annotation on a field that references an interface -- in my case, it represents a secure document signing provider. I have an implementation class that implements the interface, and it's automatically injected into the servlet.

In the servlet:

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)

    private DocumentSigningProvider signingProvider;

    ...

    URL redirectUrl = signingProvider.Sign(...);

and my implementation class:

    @Component(metatype=true)

    @Service

    public class DocumentSigningDocuSignImpl implements DocumentSigningProvider {

    ...

    @Override

    public URL Sign(...) {...}

  

As you can see, in my servlet I code against the interface, not the implementation, which is never mentioned in the servlet.

Question: When I write a 2nd implementation class for the same interface, how do I control which implementation is injected into the servlet?

I'd like to control this via configuration so I can use a different impl class in different run modes. Secondarily, it might be useful to be able to select the impl dynamically at runtime, e.g if I need to select among implementations based on some request parameter.

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.

2 replies

Level 3
November 9, 2017

I think we can achieve this using a mechanism called "Service Ranking".  By default, which ever implementation got a highest rank that implementation class will be selected. Developer can control which implementation needs to be selected by using OSGI property called SERVICE_RANKING.

refer to this article... i followed this one when i had this question in my previous project....

cq5 - Multiple Interface Implementations - AEM/CQ - OSGi - Stack Overflow

For detailed explanation you can refer to the following helpx article

Adobe Experience Manager Help | Getting Started with Adobe Experience Manager and OSGi bundles

Let me know if you are still running into issues

valcohenAuthor
Level 3
November 9, 2017

Thanks, this looks like the right direction: on each implementation class, add

@Property(name="service.ranking", intValue=<some integer>)

However, to change the order, I need to change code, rebuild and redeploy. When I add the @Property on the class, I don't see this the service.ranking property in the Felix console. is there any way to see and edit that value in configuration, so I can simply change it in the console, inactivate and reactivate the components or bundle, and have the new value take effect, rather than re-deploy?

joerghoh
Adobe Employee
Adobe Employee
November 9, 2017

If you want to do it yourself, you can use an OSGI service tracker to manage all implementations and then select the implementation you are interested in (by whatever means).

Instead of the "raw" servicetracker SCR offers some nice abstractions for it, mostly the ReferenceCardinality. A nice blog entry for it is Multiple Cardinality OSGI @References Using SCR Annotations | Architect's Log Stardate Today

Jörg

valcohenAuthor
Level 3
November 9, 2017

Jorg, thanks, that's interesting -- but in my case, at least for now, I only want a single implementation at a time. I now understand how the impl is selected -- service.ranking if it exists, or a filter, or if none specified, the oldest impl -- but I'm now trying to see how I can change the service.ranking via configuration so I can change it at runtime or based on runmode. I'd really like not to have to recompile and redeploy to change the resolution order.

joerghoh
Adobe Employee
Adobe Employee
November 9, 2017

If you want to make it runmode based, I would advise to set the ConfigurationPolicy to REQUIRED; then you can set a proper configuration for a special impl only for the runmode you want it. Or you can make the service ranking a property which you can change via OSGI configuration.

Jörg