The easiest way to configure dependencies is with the '.target' property. This requires that the implementations register with an identifying property, lets say impl=1
. and impl=2
.
@Component(property="impl=1")
public class MyServiceImpl1 implements MyService {
}
@Component(property="impl=2")
public class MyServiceImpl2 implements MyService {
}
The component then could look like:
@Component
public class MyComponent {
@Reference(target="(impl=1)")
volatile MyService myService;
}
In this case you won't be able to use 1 or 2 as flag but you would have to modify the configuration property for MyComponent
with the name myService.target
with another filter. (This is shown with OSGi standardized annotations.)
If you insist on a property that is 1 or 2 (let's call it select
) for MyComponent
then it is more elaborate. First we have the problem of being satisfied. Should MyComponent be satisfied when it needs according to the select property impl 1 but only 2 is available? If that is ok then the following much more complicated solution should work
@Designate( ocd=Config.class )
@Component( property = "select=1" )
public class MyComponent {
static Class<?> types [] = {
MyServiceImpl1.class,
MyServiceImpl2.class,
};
@interface Config {
int select() default 1;
}
@Reference(target="(|(impl=1)(impl=2))")
volatile List<MyService> candidates;
volatile MyService selected;
@Activate
@Modify
void changed( Config config ) {
Class<?> type = types[config.select()];
Optional<MyService> service = candidates.
stream().
filter( type::isInstance ).
findFirst();
this.service = service.isPresent() ? service.get() : null;
}
}
As you can see it is generally a bad idea for a component to start to handle its own dependencies. I am therefore curious to your real world scenario.
I find it always very awkward and hard to maintain designs where components are picky about who they reference. It is sometimes inevitable but in general solutions where MyServiceImpl2
and MyServiceImpl1
decide to register or not based on some condition reflect reality better.
So the big question I have what does the 1 or 2 property reflect in the real world? Can this not be modeled as a service dependency?
(disclaimer: code not tested and no error handling in it)