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.
Related
Annotated spring beans in my spring-cloud application are being created twice. I assume this is because they get constructed into the bootstrap context and then into a child application context.
For me this is undesirable because some are annotated with #Scheduled to perform periodic refreshes of the data that they provide from a backend data source and this is happening twice in quick succession once for each context.
If it's not otherwise harmful then can I disable all of the application beans from being created in the bootstrap context? If not then can I detect in code when I'm running in the bootstrap context? I use entirely annotation-based beans with component scanning enabled on the Camden SR4 release.
OK I solved this myself. It was down to two different issues in the code and nothing to do with multiple contexts.
Firstly my long held assumption that an #PostConstruct method is only ever called once was false. Moving my one-off bean initialisation code to an implementation of ApplicationListener<ApplicationReadyEvent> solved that one.
Secondly I got bit by multiple initialisation of a bean with an #Scheduled annotation causes the scheduler to run multiple times. To be fair, this behaviour is noted in the documentation. This was easily solved by moving the scheduled task creation to a regular java ScheduledExecutorService set up in the ApplicationReadyEvent implementation.
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.
}
We have some logic in an HttpSessionListener that we'd like to test. We're using Spring MVC and the associated testing framework, with MockMvc and so on. Unfortunately, we haven't found a way to get the listener initialized so that when a session is created or destroyed the appropriate listener methods are called.
I have tried to add the listener programmatically rather than using web.xml (as described in this question) and this works fine when running in a Servlet 3.0 container. But when running with Spring Test it all goes wrong, as the MockServletContext does not support the addListener method, and so throws an exception.
Is there any way to test such listeners without using integration testing?
The Servlet container decides when to dispatch events to the HttpSessionListener. This is not necessarily right after a session created or destroyed. Because this depends on the container implementation, you can't depend on the unit test. Integration testing is the way to go.
You can always unit test those HttpSessionListener implementations
HttpSessionListener listener = new MyHttpSessionListener();
listener.sessionCreated(mockEvent);
listener.sessionDestroyed(mockEvent);
outside the context of your application.
I have a pure JAX-RS application both in Glassfish and in jetty-servlet. I'm trying to inject some beans into Quartz job.
I've annotated Job fields with #javax.inject.Inject, but I also believe I need to make Job factory available to container, or vice versa - I'm somewhat lost here what end to start with.
How do I accomplish it?
Hi Victor without some more detail regarding your application I am going to assume you're running in a servlet container. There is no way to do it using a "pure" JAX-RS application.
However I would recommend you use CDI (Weld or OpenWebBeans). You can then use Deltaspike to enable the request context inside your Quartz job get a reference to a request scoped bean.
Enabling Weld in your servlet container is quite simple
A guide on enabling the request context outside of an HTTP request is available here
By default you cannot inject #RequestScoped beans into your quartz job (there is no HTTP request hence no request context). To work around this you can either enable the request context by following the link above OR (and probably my approach) inject #Dependent scoped beans (which do the work) into your JAX RS beans (essentially wrappers), you can then easily get references to the #Dependent scoped beans inside your quartz job.
Here is my web.xml and pom.xml for running Weld and Jersey inside jetty, you will need jetty-plus, jetty-jndi and Weld dependencies.
Here is some info about getting JNDI setup within jetty, however I do not use this method as I start jetty as an embedded container within a SE application, here is a code snippet of what I do:
String[] configurationClasses =
{
"org.eclipse.jetty.webapp.WebInfConfiguration",
"org.eclipse.jetty.webapp.WebXmlConfiguration",
"org.eclipse.jetty.webapp.MetaInfConfiguration",
"org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.plus.webapp.EnvConfiguration",
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration"
};
WebAppContext webapp = new WebAppContext();
webapp.setConfigurationClasses(configurationClasses);
webapp.setDescriptor("/path/to/webapp/WEB-INF/web.xml");
webapp.setContextPath("/");
webapp.setResourceBase("/path/to/webapp");
webapp.setClassLoader(Thread.currentThread().getContextClassLoader());
I have a Spring Web application with an applicationContext.xml loaded through a ContextLoaderListener in an XmlWebApplicationContext. The application context has a Quartz scheduler (defined with a SchedulerFactoryBean like here) but has no trigger nor job details.
During loading of this main application context, I load some "plug-in" JARs containing their own pluginApplicationContext.xml file.
Each pluginApplicationContext.xml is loaded in a GenericXmlApplicationContext as a child of the main XmlWebApplicationContext.
Those plug-ins may contain Quartz jobs (QuartzJobBean) which are scheduled within the scheduler discussed above. Scheduling have to be done programmatically through the Quartz API but this is fine for me. When the job is triggered, it is well instanciated by Quartz and, because it extends the QuartzJobBean, I'm able to get the current ApplicationContext through setApplicationContext.
The problem here is that I get the XmlWebApplicationContext instead of the GenericXmlApplicationContext from which the job have been scheduled. Thus, I cannot call getBean to retrieve the beans defined within the plugin.
I well understand why all of this happen. But I cannot find a clean and reusable solution to handle it. I've already had a look at OSGi but we're implementing this plug-in system on an existing application, not creating a new one from scratch and migrating the whole application to OSGi would be too much work to do. Do you know how OSGi and other plug-in frameworks deal with this kind of situation?
Thanks a lot for your help
I am not sure I get all those spring problems but I've done these things with OSGi.
What people often do not realize is that you can embed OSGi in your existing application without making any changes to the existing code. Richard Hall describes it here http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html (the API is 100% standardized).
Having a framework, you can then run your plugins in the framework. You will have to make sure the framework exports all the application packages (see the org.osgi.framework.system.packages.extra launch property). Plugins and application can then communicate through services.
I've never used Quartz but I've some experience with scheduling. I register a Runnable service with cron like properties:
#Component(properties="cron=1 * * * *")
public void SomeImpl implements Runnable {
public void run() {
...
}
}
You will then need to make a bundle that calls that service according to its cron specification).
I agree osgi is a good approach, but maybe you can simply crate one huge application context (to rule them all)? Instead of manually starting new child application context based on pluginApplicationContext.xml file simply add:
<import resource="classpath:/pluginApplicationContext.xml"/>
And this will find all plugins and merge their beans into a single application context. From architecture point of view this is a worse approach, but it will work if you discover all plugins at startup time.