Spring 4: run some initialization code before application context refresh - java

I am using Spring 4 (not Spring Boot) in the web application. I need to run some initialization code before any of the beans in the application context would be created. I tried to create implementation of org.springframework.context.ApplicationContextInitializer and register it in spring.factories but was not picked up for some reason. How can I do it?

As it turned out implementing of org.springframework.context.ApplicationContextInitializer was a right way. Because in my project I do not use Spring MVC implementation of this initializer should be registered in web.xml instead of spring.factories. Here is an example:
<context-param>
<param-name>contextInitializerClasses</param-name>
<param-value>my.company.MyContextInitializer</param-value>
</context-param>

This should work. If not, please post your code.
#Component
public class SampleBootstrap implements ApplicationListener<ContextRefreshedEvent> {
....
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
Do Something();
}
}

Related

HttpSessionEventPublisher not working in java config

I have a mature java web application that uses spring security (4.2.3, java8, tomcat8), and includes a view that allows a user to query the session registry to see who else is logged in. This depends on HttpSessionEventPublisher to notify the session registry when a user logs out.
The original implementation used web.xml config, but I have mostly reimplemented that using java config now. The last thing I refactored was the HttpSessionEventPublisher.
When I moved it from a web.xml declaration into my WebSecurityConfigurerAdapter it stopped working. Specifically, logged-out sessions are no longer being removed from the registry.
I know the bean is being instantiated (the factory method is being called).
This is the java config suggested in the reference docs:
#Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
Is there some trick needed to get this to work in java config?
HttpSessionEventPublisher should be registered as a standard listener not as spring bean. check the documentation.
So, I think you need to register it using WebApplicationInitializer as follows:
public final class MyWebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(final ServletContext ctx) {
ctx.addListener(new HttpSessionEventPublisher());
}
}

Make ServletContextListener spring aware

I am plugging in Spring to existing Java EE web Application. I have following lines in my web.xml:
<listener>
<listener-class>com.MyContextListener</listener-class>
</listener>
And Following MyContextListener class?
public class MyContextListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
//...
}
}
What should I do to make MyContextListener be managed by Spring?
Edited:
My assumption is: Spring should create all servlets and all web app infrastructure so everything happened in contextInitialized method of MyContextListener should be somehow handled by Spring. How can I achieve, by implementing some interface I suppose. Correct me if I am wrong. Thanks!
Well,
We had a similar scenario of configuring an exiting Jersey web services app to use Spring for dependency injection. Our Jersey webapp had extended ContextLoaderListener as follow
public class XServletContextListener extends ContextLoaderListener {
...
#Override
public void contextInitialized(ServletContextEvent arg0) {
super.contextInitialized(arg0);
....
}
#Override
public void contextDestroyed(ServletContextEvent arg0) {
super.contextDestroyed(arg0);
....
}
}
where ContextLoaderListener is
import org.springframework.web.context.ContextLoaderListener;
We included the jersey-spring bridge with all spring dependencies including applicationContext.xml as follow
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.xxx.*" />
....
....
</beans>
And obviously needed to make sure that XServletContextListener is included in the web.xml as follow
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>com.xxx.**.XServletContextListener</listener-class>
</listener>
Followed by servlet and its init-param values and servlet mapping. You can obviously adopt annotation config in place of xml confib in which case you would need to use WebListener annotation.
We use a variety of annotations such as
#Component for objects
#Service for services
#Repository for DAOs
#Controller for controllers/resources
#ContextConfiguration for tests
Everything is loaded and autowired by Spring framework.
What should I do to make MyContextListener be managed by Spring?
It depends on which configuration way you are using. Anyway, you should tell directly Spring to use the class you have declared. That could be done by the following way:
#WebListener
public class MyContextListener implements ServletContextListener { ... }
A class marked with this annotation (the Servlet 3.0 specification, 8.1.4) must implement one of these interfaces
HttpSessionAttributeListener
HttpSessionListener
ServletContextAttributeListener
ServletContextListener (+)
ServletRequestAttributeListener
ServletRequestListener
HttpSessionIdListener
that it actually does.
Personally, I prefer a meta-annotation based approach which makes my configuration shorter and more concise.
Spring should create all servlets and all web app infrastructure so everything happened in contextInitialized method of MyContextListener should be somehow handled by Spring.
Yes, Spring will do it for you if you provide some information which could help it to register / configure / create / manage an instance.
The information may be either meta-information (a template that tells how to create an instance, like BeanDefinitions) or a completed instance itself (usually, it gets passed programmatically that, in turn, leads to writing a huge amount of code).
How can I achieve, by implementing some interface I suppose.
You are implementing an interface to make your listener a listener (a class that describes specific methods which will be called at some points of time). Spring, itself, is responsible for guaranteeing such calls at those points of time, placing an object in the existing web infrastructure before.
Either annotate the class with #WebListener or the method with #Bean
Annotate where you create a new instance of MyContextListener with #Bean if using Java Configs with Spring Boot.

Listener for server starup and all spring bean loaded completely

In my web application, I want to create Listener which will get notified when my server get started and all bean get loaded.
In that Listener, I want to call a service method.
I used ServletContextListener.
it has contextInitialized method but it does not work in my case. it get involked when server get started but before spring bean creation.
so I get instance of service class as null.
Is there other way to create Listener.
I would go for registering an instance of ApplicationListener in the Spring context configuration, that listens for the ContextRefreshedEvent, which is signalled when the application context has finished initializing or being refreshed. After this moment you could call your service.
Below you will find the ApplicationListener implementation (which depends on the service) and the Spring configuration (both Java and XML)that you need to achieve this. You need to choose the configuration specific to your app:
Java-based configuration
#Configuration
public class JavaConfig {
#Bean
public ApplicationListener<ContextRefreshedEvent> contextInitFinishListener() {
return new ContextInitFinishListener(myService());
}
#Bean
public MyService myService() {
return new MyService();
}
}
XML
<bean class="com.package.ContextInitFinishListener">
<constructor-arg>
<bean class="com.package.MyService"/>
</constructor-arg>
</bean>
This is the code for the ContextInitFinishListener class:
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
public class ContextInitFinishListener implements ApplicationListener<ContextRefreshedEvent> {
private MyService myService;
public ContextInitFinishListener(MyService myService) {
this.myService = myService;
}
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
//call myService
}
}
You can use Spring's event handling. The event that you are looking for is probably ContextRefreshedEvent
Yes you need to add ContextLoaderListener in web.xml, only if you want to load other Spring context xml files as well while loading the app and you can specify them as
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-security.xml
</param-value>
</context-param>
for more u can visit this link might helpful to you.
Click Here

With Spring how can I execute code after HIbernate is initialized but before the application starts?

I want to insert some data into the database using the application API if the application has started up with some empty database tables. How do I go about this?
I'm using Spring 3.1, Hibernate 4.1.1.
[edit]
Thanks to AlexR the answer is to sublcass ContextLoaderListener, call super in contextInitialized and then do whatever it is you need to do:
public class MyContextLoaderListener extends ContextLoaderListener {
public void contextInitialized(final ServletContextEvent event) {
super.contextInitialized(event);
// ... doStuff();
}
}
You may also need to wire this up in web.xml instead of the Spring one:
<listener>
<listener-class>com.example.MyContextLoaderListener</listener-class>
</listener>
You can use spring context listener.
Take a look on: http://fusesource.com/docs/framework/2.2/deploy_guide/CXFServletDeploySpring.html
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/context/ContextLoaderListener.html
http://forum.springsource.org/showthread.php?88896-Spring-MVC-3-is-ContextLoaderListener-needed

Does spring have a way to load up things when the application first loads? At a global level

Is there any spring specific way in the framework to perform initialization when MVC loads up?
Say I need to create global objects based on configuration files, is there a place to do this or do I just create my own servlet and do this in oninit?
What about standard #PostConstruct?
#Service
class AnySpringBean {
#PostConstruct
public void init() {
//run when bean is created
}
}
Works on #Controllers as well.
UPDATE: The more global place would be to subclass ContextLoaderListener) and override contextInitialized() and use it in web.xml (see user1076371 answer). I don't like this approach much, but at least the initialization is not tied to any Spring bean.
There is an ApplicationListener interface you can implement to hook into the startup completion event. I use this in my app to do things after I know Spring has finished starting up. I have a few different classes that I want to kick off background threads after the system is "up" and each implements this interface to do their particular post startup stuff.
It's sent after the app as a whole is done, but it's each listening spring bean that gets an event, so you'd could hook it into some existing bean or to create something like a PostStartupBean that exists only to implement this one method.
public void onApplicationEvent( ApplicationEvent applicationEvent )
{
if ( applicationEvent instanceof ContextRefreshedEvent )
{
..do stuff here..
}
}
Best thing would be to leave it to Spring. Add your global object beans (which could be singletons etc..) to your application context. Make sure Spring is initialized when the application is loaded by adding ContextLoaderListener to the web.xml.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4">
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>
You can access your global objects from the WebApplicationContext anywhere in the application.

Categories