View Full Version : How to Access Spring Application Context from within Bundle
Dukes
Jun 20th, 2008, 11:07 AM
Hi,
According to my understanding of Spring Dynamic Modules, the extender bundle will instantiate a Spring application context for my "Spring-powered bundle". This I have working.
I have seen several examples of how to export beans as OSGi services to make them available to clients in other bundles.
But what is the proper way to get a reference to the Spring application context for accessing beans WITHIN the same bundle?
Going through the OSGi Service Registry in this case seems expensive and wasteful, since there is no inter-bundle interaction required (just trying to access beans within the same bundle through the Spring application context that the extender has already created for me).
Any sample code would be greatly appreciated.
Thanks for your help.
Dukes
Jun 20th, 2008, 05:24 PM
Martin Lippert was kind enough to provide an answer to my question. I will post his answer here in case it helps others with the same question:
"There are several possible ways, I think:
- If you need a reference to a bean within the application context (for
injecting it into another bean) you can use it just the Spring way. This
is the simple case.
- If you need a reference to a bean from the application context within
a class of your bundle that is not controlled by the application context
you have two choices, I think:
a) Export the bean as an OSGi service and import this service using a
service tracker from your class within your bundle.
b) Write a class that implements "ApplicationContextAware" and define
this class inside your application context. If the application context
is created it creates an object of this class and calls
"setApplicationContext" on this object (this is the method that is
defined by the ApplicationContextAware interface). You can now implement
this method by keeping the reference to the app context within a static
member or by setting the reference to your application context to
another statically accessible part of your bundle (the bundle activator
object, for example). Having the reference to your application context
you can call getBean on it to get a reference to a bean that is defined
within the app context.
Best regards,
-Martin"
oleg.zhurakousky
Jun 23rd, 2008, 06:54 PM
Yes all these ways will work, but outside of the fact that generally it is not recommended to access ApplicationContext directly (assuming all the wiring happened for Spring managed services/beans and for non-Spring managed services/beans such services were exported as OSGi services), there is cleaner and more elegant/proper way of accessing ApplicationContext.
ApplicationContext is itself published as OSGi service and can be accessed as such (see chapter 4.2.2. Application Context Service Publication of ref-manual), since it is ". . .published
under the interface org.springframework.context.ApplicationContext. . ." and can be accessed via simple OSGi lookup.
Also, considering that you might have several ApplicationContexts published (more then one Spring-powered bundle) you might want to use filtering mechanism to get the right one since they will all have different value for the following property: org.springframework.context.service.name
So, here is he sample code:
In this example I am accessing the ApplicationContext published by my web-bundle:
ServiceReference webContext = context.getAllServiceReferences("org.springframework.context.ApplicationContext", "(org.springframework.context.service.name=org.spri ngframework.osgi.websimple)")[0];
ApplicationContext ac = (ApplicationContext)context.getService(webContext) ;
Also, read 5.1. Bundle format and Manifest headers, since there are ways of disabling default behavior for publishing the ApplicationContext via app-deploy:headers. This way ApplicationContext will not be available as OSGi service.
Hope it helps
Dukes
Jun 24th, 2008, 05:08 PM
Thank you Oleg, this works very nicely and I agree is a very clean and elegant way to access the ApplicationContext that Spring DM automatically exports to the OSGi Service Registry.
It would be helpful if the Spring DM Reference Documentation included a sample and description similar to the one you provided.
One question I have though: Why is it generally not recommended to access the ApplicationContext directly in the case of non-Spring managed objects that need to access Spring managed objects within a bundle?
I am new to OSGi, but I thought that the OSGi Service Registry is really for inter-bundle communication, and that for intra-bundle communication it is more appropriate to use traditional Spring access mechanisms (i.e., ApplicationContext/BeanFactory). But it sounds like I am missing something here?
Thank you for your help.
Regards.
oleg.zhurakousky
Jun 24th, 2008, 05:29 PM
It is not recommended to follow general architectural patterns promoted by Spring and OSGi
For example:
Spring-managed components in a "proper" architecture will be wired together within ApplicationContext they defined in and will have no need to access the ApplicationContext. That is what dependency injection (DI) is all about.
In the case of OSGi we publish components as OSGi services and access them as such. So if you need a bean which is not published as OSGi service i could argue that it might not be intended for usage outside of defining ApplicationContext.
However I will also say that the keyword here is "not recommended", which means that you can and should be able to do it if you have compelling reason :-)
After all it is all about quality code
Cheers
Powered by vBulletin® Version 4.2.1 Copyright © 2013 vBulletin Solutions, Inc. All rights reserved.