I'm trying to understand how to control dependency injection in OSGi (specifically Apache Felix as used in Adobe Experience Manager (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
@Property(name = "service.ranking", intValue = 1000)
public class DocumentSigningProviderDocuSignImpl implements DocumentSigningProvider {
If I write a second implementation, I can control which one is injected via the service.ranking
value -- highest number wins. If no ranking is declared on any of the implementations, the oldest wins.
So far, so good -- except that to change the values I need to recompile and redeploy. I need to control this at runtime, or via a configuration file that's tied to the environment or "runmode". I can't see how to do that.
Since the @Component
declares metatype=true
, @Property
annotations within the class generate a control in the OSGi console's GUI. I can use that GUI to change values at runtime. But the service.ranking
is declared in an @Property
on the class itself, and it doesn't appear to generate a control in the GUI.
In addition, configuration files named after the class provide default values at runtime, and I can have a different config file for each environment or "runmode". This would work for me too; in one environment I can configure a mock implementation, and use a "real" implementation in another environment. But again, these config files seem to work for @Property
declarations inside the class, but not on the class.
I've read a number of threads here about this subject but none touch on exposing service.ranking
in the OSGi GUI or in config files.
Is there any way to control which class is injected without modifying, re-compiling and re-deploying source code?