Spring service publishing to wrong reference arbitrarily [message #676371] |
Fri, 03 June 2011 20:02  |
Eclipse User |
|
|
|
I'm seeing published services being injected into fields they aren't "@Qualified" for. And it changes as I start and stop those services. I might get the Authentication bean in the Policy field, stop and restart and I might get the Policy bean in the Authentication field, etc.
I have three beans that all have the same interface, from three different bundles. Each bundle publishes their service by "id" and interface, and the "id" values are all different via Spring "<osgi:service ref='...' interface='some.common.interface' />". Each bean uses @Component("someId") to explicitly set the ID used in the ref/id of the OSGI tags. They share a common interface for specific reasons.
I then have a service that consumes those published services via three Spring "<osgi:reference id='...' interface='some.common.interface' />" tags. The service consuming these references uses @Autowried and @Qualifier annotations to specify the specific bean ID to inject into specific fields.
I thought by specifying the bean's Component ID in the reference, id, and @Qualifier fields, it'd explicitly limit the published service by the bean ID and not just go off of the interface.
I could add a marker interface, but that kind of defeats the purpose. Is the interface the only marker for the inbound service reference? I don't see any other options on the <osgi:reference> tag that allows me to restrict by the service ID.
|
|
|
Re: Spring service publishing to wrong reference arbitrarily [message #676454 is a reply to message #676371] |
Sat, 04 June 2011 10:18   |
Eclipse User |
|
|
|
If I understand properly what you're trying to do, you want to have @Qualifier values "cross over" the OSGi boundary between Spring contexts. To my knowledge, there's nothing to directly support that. The Spring DM reference (either 1.x or 2.x) doesn't even mention qualifiers, and in my testing, I've seen no evidence that a bean's qualifier value is added to the exported service in any way, though that seems like it would be convenient. Maybe you should file a feature request on Spring DM for that?
You're seeing seemingly indeterminate service importing behavior in your <osgi:reference> tags because the only constraint you're giving it is the interface that the service needs to implement. The id attribute of osgi:reference has no role in determining which service to select. It's just the id of the bean that the service is exported as. Therefore you're asking the OSGi container for the first service it finds that satisfies the given interface, where "first" would be governed by OSGi's service selection algorithm. Specifically:
"If multiple such service objects exist, the service object with the highest SERVICE_RANKING is returned. If there is a tie in ranking, the service object with the lowest SERVICE_ID (the service object that was registered first) is returned." --OSGi Service Platform Release 4, Version 4.3, Section 5.2.8.
In the meantime, I think you could get what you want by using the bean-name attribute of osgi:reference. That restricts the imported service by the name of the Spring bean that was exported. The bean name *is* a property of the exported service, stored in the service property "org.springframework.osgi.bean.name". Personally, I'd try not to use it, as it's basically by-name bean wiring, where I always find by-type + qualifier to be a much better model, and OSGi itself is very by-type-oriented.
The only other option I can think of would be to add custom service properties when you export the service using the <service-properties> element of <osgi:service> and then use a filter expression on your <osgi:reference>.
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.03970 seconds