When I use a reference in DS I can specify a target that will allow me to narrow down which service instance I want. The problem is that all the examples show static queries that must be done at code time. Is there a way to do a dynamic query (maybe pull in a property from Configuration Admin)?
If DS does not support this is there another OSGi dependency injection framework (blueprint, iPojo, etc) that will support this?
You can always use the target attribute of the reference to peform a first level filter. The if your bind method has the signature
void <method-name>(<parameter-type>, Map);
Then you can run any dynamic filter over the Map which contains the services properties. If the filter does not match, you can ignore that component (for the time being.)
In the alternate, since the component's configuration can contain the reference's target filter, you can modify the component's configuration to alter the target filter.
I use the following trick. If you specify a "target" attribute on the service reference but leave its value as the empty string, then a component property with the same name but a ".target" suffix will be used at runtime.
In the example below, I select my JDBC source dynamically via a .cfg file in my Karaf container. The "datasourcefactory.target" property is injected automatically into the "target" attribute of the "datasourcefactory" reference.
Caveat: I don't actually know if this trick is officially supported or just a Felix SCR feature. I've been meaning to look this up in the spec to see if it's mentioned... +1 to any comment that clarifies its legality!
@Component(
name = "...",
specVersion = "1.1",
policy = ConfigurationPolicy.REQUIRE,
metatype = true
)
@Property(name = "dataSourceFactory.target",
value = "",
label = "dataSourceFactory target",
description = "An OSGi service filter to select the data source provider. "+
"For example: '(&(osgi.jdbc.driver.name=derby)(objectClass=org.osgi.service.jdbc.DataSourceFactory))' where 'derby' is the important bit and the rest is boilerplate. "+
"See DataSourceFactory.OSGI_JDBC_DRIVER_(NAME,CLASS,VERSION)."
)
@Reference(
name = "dataSourceFactory",
referenceInterface = org.osgi.service.jdbc.DataSourceFactory.class,
cardinality = ReferenceCardinality.MANDATORY_UNARY,
target = "", // must be overwritten by configuration property named "dataSourceFactory.target"
bind = "bindDataSourceFactory",
unbind = "unbindDataSourceFactory"
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With