How do I use a Spring bean inside an OSGi bundle? - java

I have an application where I have to use Spring to load a bean based on some business conditions inside an OSGi bundle. This bean is not meant for export and is used for calculation inisde my bundle. Basically I have an actual service component, which is exported, and it has to use this Spring bean internally. But...
When I use Spring DM the extender loads the application context in a seperate thread. How to access the context file inside my bundle?
How to make sure extender thread finshes loading application context so that i can use it in my bundle?
I don't want to export the application context as services as Spring DM does, as it's only used inside my bundle for internal purposes.
Is there any way to do this?

You don't need Spring DM for what you are trying to accomplish.
It sounds like what you want to do is actually provide access to your context inside of your bundle and have some class do lookups via ctx.getBean(). If this is the case, just create the context in your bundle manually like you would if you were not in OSGi and make the calls. No Spring DM involved at all.
The one issue here is that you have to extend ClassPathXmlApplicationContext to provide the bundles classloader, as it will use the thread context classloader otherwise.
ApplicationContext ctx = new ClassPathXmlApplicationContext(myCtxPath)
{
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader)
{
super.initBeanDefinitionReader(reader);
reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
reader.setBeanClassLoader(getClassLoader());
}
}

Related

Pluggable Spring context files

What would be the best way to handle a situation, where new Spring context is introduced to application during a runtime, and server restart is not an option?
I have an application where some beans are registered to other bean called "manager" when context is created. Now, should there be new functionality needed later, I have a Spring configuration file defining beans for the new functionality, and these beans should register them selves to "manager", which is already created. This works fine if the new file is added to classpath and server is restarted, but how to achieve it without restarting?
I guess I should make Application container somehow notice new context files and process them like during startup. But is that possible?
Have you considered combining spring with a framework like Apache Felix?
http://felix.apache.org/

Spring NON MVC project configuration - Best Practices

I am going to work on a Java project and want to use Spring IOC for bean management.
This is not a web project but just a simple java project that will give me a jar file at the end.
My questions is that, in my application i want to use Spring IoC to get instances of classes to call their respective methods. For the purpose i need to get the spring context using
CalenderDao calenderDao = (CalenderDao) ApplicationContextUtils
.getApplicationContext().getBean("calenderDao");
calenderDao.getCalenderUpdate();
Now if i need this bean in some other class too , i will copy and paste the same thing there as well like.
CalenderDao calenderDao = (CalenderDao) ApplicationContextUtils
.getApplicationContext().getBean("calenderDao");
calenderDao.getCalenderUpdate();
My question here is that, do i need to create a ApplicationContext in each file to get a bean throughout the application. Or is there any alternate and best thing to perform. And if i am doing the thing like this way how can use setter injection or constructor injection in application.
In web apps this is quit simple we loads the context one time and everything works fine, but how to do this in non web where we don't have web.xml file to instantiate the context.
Please help how beans are managed in non web project using spring.
Spring is not just designed for web apps.
Just because it's not a web application you dont need to fall back to "provider style". You do not need a web.xml to initialize an application context.
Use your main method to create an application context and work with your beans as you would do for a webapp. You can use autowiring and all the gadgets of spring.
Once the context is initialized call your main class to start your application, for example with the help of the refresh event. From there on you have (almost) no need to use getBean.
Obviously you dont have session and request scope, but singleton and prototype are available.
Just take a look at the spring docs.
Wherever you require ApplicationContext in your application, implement that class with ApplicationContextAware interface.
Say here
public class CalenderService implements ApplicationContextAware{
private ApplicationContext context;//declare this so you can use it
}
As it is interface you need to overide its method
public void setApplicationContext(ApplicationContext context){
this.context=context; // here ApplicationContext gets injected.
}

Accessing osgi bundle classess from servlet

I have two projects.
An osgi bundle (eclipse plugin project).
A simple web application (deployable in tomcat).
I have started the felix container from tomcat with no problem by following the link below
http://felix.apache.org/documentation/subprojects/apache-felix-http-service.html#using-the-servlet-bridge
Now I am stuck how to call the classes of the bundle (already installed in the felix container) from a servlet. It is throwing class not found error as the bundle project is not in the classpath but in the following location
/WEB-IN/bundles.(I have to use this location for the bundles). So how it could be achieved?
The BundleContext of the framework bundle is put into the servlet context in ProvisionActivator:
servletContext.setAttribute(BundleContext.class.getName(), context);
This means that you can access the BundleContext via the servletContext (that is available in all of your ordinary servlets) like this:
BundleContext context = servletContext.getAttribute(BundleContext.class.getName());
You can access the classes inside the embedded OSGi container by:
Asking for the bundle that contains the class via the bundleContext
Getting the class with the bundle.loadClass("myClass") method. You will be able to use that class only if you cast to the interface available from the ordinary WAR or with reflection
This is the way to do it, however you should not use this method :). Design your solution in the way that in your bundles you register OSGi services that implement interface(s) coming from the WAR classpath. After that you should use the bundleContext object to retrieve the OSGi service objects.
Other good solution is if you implement the logic you need within bundles instead of classes coming from the WAR.

how to load spring without a web container

I have a RESTful service using Jersey/Spring/Tomcat. My question is - is it possible to access the classes within my war from command line (without the web interface)?
The problem is the JDBC connections and some other beans are managed by spring. So how do I load all these beans without the web container?
You can easily initialize application context and load all the classes manually. Here is an example:
ConfigurableApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml");
YourBean yourBean = applicationContext.getBean("yourBean", YourBean.class);
applicationContext.close();
Classes in a WAR archive are tricky, because you'll have to tell the ClassLoader to look inside WEB-INF/classes and WEB-INF/lib/*.jar . Sounds non-trivial to me...

Implementing servlet lifecycle methods in a Spring web application?

I am implementing a web application using Spring. I am using Spring's ContextLoaderListener, to load up my application contexts, and Spring's DispatcherServlet, to load the relevant beans from {name}-servlet.xml, which refer to the beans in the main application context. I want to be able to integration test these Spring configurations outside of the container to validate everything is wired up correctly before I deploy to Tomcat. However my application requires some scheduled background processing when running in the container. In a regular HttpServlet I would simply implement init() and destroy(). All the suggestions I have read suggest using an InitializingBean for that kind of initialization.
However, if I use an InitializingBean, afterPropertiesSet() gets called whether I am inside the container or in integration tests - and outside the container, I don't have access to the resources that background task needs. Is there a better way to perform the tasks I would normally perform in init() and destroy() so that they will only run when deployed as a webapp?
Have you considered using a test spring config file that overrides the bean implementing your background process?
This way everything else in the spring configuration would work normally except for the one overridden bean.

Categories