Calling a Spring #Service on web application initialization - spring

I have a web application that needs some static variables initialization as soon as I thrown the .war in the Tomcat webapp folder. This initialization needs to call a #Service to retrieve the initial set up.
I realized that the #Autowire injection only works when my GUI is calling the service
What is the best way to initialize my Spring web application after throwing the .war in the app container? I need this initialization to be executed once only.

If you need to do something after servletContext is initialized, in spring, we use ApplicationListener to do this.
public class SpringListener implements ApplicationListener<ContextRefreshedEvent>{
// this should work if other setting is right
#Autowired
XXX xxx;
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent ) {
// do things here
}
}
in application.xml
<bean id="eventListenerBean" class="package.name.SpringListener " />
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-functionality-events
On the otherhand, just FYI, the traditional way is to do it using ServletContextListener.
http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html

Related

How to register JSF ExceptionHandlerFactory programmatically in Spring Boot

I'm using Joinfaces to build a JSF + Spring Boot application and Omnifaces is packed with it.
When the View expires and I navigate I get the ViewExpiredException. When I execute Ajax, the page does nothing and the error shows in the console.
Is it possible to register the org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory programatically with Spring, without having to add a .xml (web, faces-config) to my project?
Use the following to set up a custom exception handler sans web.xml:
FactoryFinder.setFactory(FactoryFinder.EXCEPTION_HANDLER_FACTORY,"org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory");
The trick here is to make sure this line is executed as early in the startup as possible; once FactoryFinder.getFactory() has been called by the JSF runtime, it's too late to change the configured handler.
The good thing is that I actually can't find anywhere in the Mojarra codebase where the exception handler factory is being set by default, so you probably could execute this maybe in the constructor (not the #PostConstructor) of any #ApplicationScoped bean. You could also do it in a static initializer of the ame bean.
Additionally, you could do it in a FacesInitializer. So asssuming you're running Mojarra, you'll need to setup the handler very early on in the startup process of the servlet context
public class YourWebAppInitializer extends FacesInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext ctxt) throws ServletException {
AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
root.register(YourSpringConfigClass.class);
ctxt.addListener(new ContextLoaderListener(root));
FactoryFinder.setFactory(FactoryFinder.EXCEPTION_HANDLER_FACTORY,"org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory");
}
}
The WebApplicationInitializer is a standard interface supported by Spring for bootstrapping a web application and I'm assuming you already have that in place because you don't have a web.xml - feel free to replace the contents of the onStartup method with whatever you have in your actual implementation. The key thing here is to make sure you set the factory there, which is pretty early in the startup of the application.
Also note that you can hand set the actual ExceptionHandler on any given instance of FacesContext (although I haven't tested this to see how it'll behave or whether it'll perform well)

Is there some way to get access to Spring bean from Spock extension?

There is an example what I want to do.
The service client is a Spring bean, which is retrieving from external configuration class and should be called from Spock extension.
class ServiceCleintExtension implements IGlobalExtension {
#Autowired
ServiceCLient client
#Override
void start() {
client.execute()
}
...
}
UPD:
I've found a solution by using Spring TestExecutionListener and custom static "container" for SpecInfo/FeatureInfo.
No that is not possible, IGlobalExtension are initialized and manged by Spock. Furthermore, they are singletons which doesn't mesh well with multiple possible Spring contexts.
If you just want to call a method on an injected bean during setup, then I'd suggest to use an annotation based extension. Look at the builtin AutoCleanup extension for reference.

Spring, Run task once when application started

My application is based on spring boot.
I want to create a task which should be run only once after application has been started.
Currently, I am looking into two solutions:
Using #Scheduled and boolean property which should determine whether the logic shold be run or not.
#Scheduled
public void method(){
if(method_run_propery){
//do something;
}
}
Using Quartz. But I have not used before.
Please, tell me what is the best approach to use in this case.
Spring has a #PostConstruct annotation to do exactly that. Runs once the bean has been initialized and all dependencies added.
If it has to be run once immediately after application is initialized, I would simply start it from the init method of a singleton bean. Spring ensures that at be time it will be run all dependant beans will have been initialized.
For example, assuming a Java annotation Spring configuration you could use something like:
#Bean(init_method="init")
class TaskLauncher {
#Autowired DependantBeanClass dependant Bean;
...
public void init() {
// execute or start the task, eventually using the autowired dependant beans
...
}
}
When the context is refreshed, Spring autowire everything, initializes the dependant beans and then will call once the init method of the TaskLauncher bean.
No need for #Scheduler nor Quartz if you only need to start something at Spring initialization time
One of the ways is to implement ApplicationListener
Once spring context is initialized, Your class which implements ApplicationListener
which will then have onApplicationEvent method will be invoked, your logic can go in this method.

How can I instantiate an injected class (using Spring) before logback configuration

I am using spring to inject a class into my PropertyDefiner implementation which will be used to help set up some properties within the logback.xml file (through dynamic property loading).
I'd love to get this class loaded and instantiated before logback is configured. Any thoughts on how to do this?
If you're using annotations in Spring, it's convenient to do this by marking the class (i.e. the dependency) you'll be injecting as #Component and then using #Autowired in your PropertyDefiner implementation. This ensures that the first class will be instantiated first. http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch04s12.html
Any other initialization you require could be achieved using instance initializer blocks http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
I do not know if this can be done elegantly at present time (2012-07). However, support for injection has been requested in LOGBACK-719.
If your bean factory implements AutowireCapableBeanFactory, given the Spring Applicaton context, you could invoke autowireBean(Object existingBean) to autowire the bean. Here is a tentative implementation:
class Your.PropertyDefiner implements PropertyDefiner, LifeCycle {
#Autowired
#Qualifier("myKey")
String myKey;
public void start() {
ApplicationContext appContext = ... somehow get the spring app context
AutowireCapableBeanFactory factory = appContext.getAutowireCapableBeanFactory();
factory.autowireBean(this); // declare victory
}
}
The start() method will be invoked only if your PropertyDefiner implements the LifeCycle interface. Moreover, you need logback version 1.0.7 or later. Earlier versions do not invoke start().
My solution resulted in not implementing a PropertyDefiner. The original question became an issue of not having the application context from spring to set the dynamic properties. I'm not sure why, but code in a later listener (after the Spring listeners) would get called (invoking the LoggerFactory call) before the application context was available. I tried a number of things, until I starting looking at a different approach.
Instead of using dynamic properties I created a listener (called on server startup) which then programmatically sets up my appender with the properties I want (through the createAdminNotifyAppender).
#Override
public void contextInitialized(ServletContextEvent arg0)
{
//Set up the property reader to pull the correct properties
ServletContext context = arg0.getServletContext();
ApplicationContext appContext = WebApplicationContextUtils.getWebApplicationContext(context);
propReader = (AppConfigPropertiesReader)appContext.getBean("propertySourcesPlaceholder");
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
createAdminNotifyAppender(lc, propReader);
}
The createAdminNotify method simply sets up an appender and adds it to the logging context. (if you're really interested, you can see that method's implementation on this thread).
Now I have a separate and modular listener that I can add to other apps that are using logback, but possibly with different properties. The properties are pulled from a database and can also vary by environment.

Spring bean initialized on web app starts up

This is probably due to my ignorance of the Spring framewok but i am building a JSF+Facelets+Spring web app, i have a bean that whose init method i want to get called at the time the application is started. My problem is getting the bean initialized. I can reference the bean on a page, and when I go to the page, the bean is initialized, and works as directed; what I would like instead is for the bean to be initialized when the application is started
What is the way to get a Spring bean initialized on web app starts up
Your question is more Spring-targeted than JSF-targeted. I know the solution for JSF, but I don't think that this suits a Spring bean. I googled a second and found this topic at the Spring forum which may be of use for you. It describes/links several different approaches: http://forum.springsource.org/archive/index.php/t-21982.html
All the code that you want to handle immediately after an webapp is initialized can be done in a class that implements ServletContextListener as
#WebListener
public class ApplicationListener implements ServletContextListener {...}
and you can create spring application context like
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[] {"applicationContext.xml", "applicationContext-part2.xml"});
// of course, an ApplicationContext is just a BeanFactory
BeanFactory factory = context;
and get the bean you are interested in and go on.

Resources