This question already has an answer here:
Using special auto start servlet to initialize on startup and share application data
(1 answer)
Closed 7 years ago.
The reason I'm asking this is that I want to write code that initializes the application once it starts and cleans up later on.
I dont want to use a servlet init() method since it is per servlet.
There is no main() method in Servlet.
If
The reason I'm asking this is that I want to write code that initializes the application once it starts and cleans up later on.
You can use ServletContextListener implemented
public class MyServletContext implements ServletContextListener{
ServletContext context;
public void contextInitialized(ServletContextEvent contextEvent) {
System.out.println("Context Created");
}
public void contextDestroyed(ServletContextEvent contextEvent) {
System.out.println("Context Destroyed");
}
}
web.xml
<listener>
<listener-class>
com.yourpackage.MyServletContext
</listener-class>
</listener>
There is no main() method, because the components are managed and the container invokes other methods - like the init() on servlets and filters. The container itself is started through a main method, but even that's hidden from you.
For per-application and initialization you can use a ServletContextListener
You have to map it in web.xml using <listener><listener-class>...</listener-class></listener>. In contextInitialized(..) and contextDestroyed(..) you can do initialization and cleanup respectively.
Related
I have a singleton spring bean named gameContext, my spring bean definition;
<bean name="gameContext" scope="singleton"
class="tr.com.hevi.game.numblock.core.context.GameContext"/>
I also use this class for session listening, here is my web.xml
<listener>
<listener-class>
tr.com.hevi.game.numblock.core.context.GameContext
</listener-class>
</listener>
The problem is that gameContext is being created twice. one; at the very beginning before the spring context is being loaded, and the second; within the spring context.
I am sure that I do not component-scan more than once.
I understand the reason behind but don't know how to tackle the problem. One possible solution should be adding the listener within the spring context not web.xml, or there might be a proxy object solution.
In your problem, there are 2 objects for spring because you are configuring the listener twice
The first is in the web.xml (outside the spring context)
Within the spring context as a bean.
The easiest way to have only 1 instance is if you are using the Servlet 3.0 specification. Here the ServletContext has a addListener() method make use of the same. Do something like the below:
#Component
public class MyCustomListener implements javax.servlet.http.HttpSessionListener, ApplicationContextAware {
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (applicationContext instanceof WebApplicationContext) {
((WebApplicationContext) applicationContext).getServletContext().addListener(this);
} else {
//Either throw an exception or fail gracefully, up to you
throw new RuntimeException("Must be inside a web application context");
}
}
}
The above approach will cause you to create only 1 object of the listener, and have the same object registered as a Servlet listener and spring bean.
I've seen many answers on this topic but still can't find a clean solution.
public class ProcessScheduler {
static {
Timer timer=new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
LogProcessorServiceImpl.processPageRequestsLogs();
}
}, 0, 120);
}
}
How do I make this execute and be happy with quality solution? My application is based on Spring (unfortunately) and I know I can reference this class in one of my controllers and it'd probably work. But that's silly. There just must be a better way. I'm on Tomcat with no EJB support, so timer annotation will not work for me. Also, I don't want to do CRON. I want to schedule all my maintenance tasks within this scheduler class.
Servlet classes can be loaded via web.xml (1). Can we do something similar on non-servlet classes?
Instead of writing this in a static block, I would prefer to
write an event listener that extends javax.servlet.ServletContextListener
move that piece of code into the contextInitialized method
define the contextDestroyed method to cancel the timer
configure the class as <listener> in web.xml file for my application.
<listener>
<listener-class>
com.vikdor.webapps.ProcessSchedulerListener
</listener-class>
</listener>
I'm in the "how-to" phase with Apache CXF and would like to know if there's a way to call a method when the server is started.
It would be similar to a JSF web application, when I use a #ApplicationScoped managed bean with eager=true: when the container is started, the annotated class is instantiated and I can call whatever I want from its constructor.
Any help?
So, If you are using CXF Servlet to serve Web Service request, then you can create ServletContextListener and contextInitialized method will be called on deployment or on server start up if the application is already deployed.
To do that create class which will implement ServletContextListener:
public class YourContextListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent sce) {
//This method is called by the container on start up
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
Then define that listener in your web.xml:
<listener>
<listener-class>your.package.YourContextListener</listener-class>
</listener>
In the contextInitialized method you can get servlet context by using:
ServletContext context = sce.getServletContext();
And you can set as many attributes as you want to be available into whole application scope.
I have a Spring web application with two contexts: one (applicationContext) built by ContextLoaderListener and a second (webContext) built by DispatcherServlet.
Within the applicationContext is a bean (org.springframework.security.authentication.DefaultAuthenticationEventPublisher) that fires spring context events.
But the receiver for the event is defined in the webContext. And that receiver did not get the event. (If put the receiver for test purpose in the applicationContext then it get the event, but I can not do this, because I need the webContexts for its functionality.)
So my question is, how to bridges the events from the applicationContext to webContext?
I had the same problem, solved mine by moving the beans creating the event to web-context. However you can solve your problem by manually wiring your event listener, something like this (this code is not compiled therefore it is untested):
#Component
public class BeanInWebContext implements ApplicationListener<SomeEvent> {
#Autowired
private ApplicationContext webContext;
#PostConstruct
public void registerAsListener() {
// get parent context
AbstractApplicationContext appContext = (AbstractApplicationContext) webContext.getParent();
// register self as a listener, this method is in AbstractApplicationContext
appContext.addApplicationListener(this);
}
#Override
public void onApplicationEvent(SomeEvent event) {
}
}
I think the actual answer is that you may want to configure your app differently (so that you only have one context)
I think in your web.xml you need to do something like this :
<servlet>
<servlet-name>example</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/META-INF/applicationSpringConfig.xml
</param-value>
</init-param>
</servlet>
But to answer the deeper question. Someone else points out that you can use includes in your spring file (indeed in the above you can have more than one springconfig specified in your dispatcher servlet).
But when you include other context files you do not share instances of beans, only definitions.
Modularising Spring applications has been the only real downside of spring in comparison with EJB etc. That led spring into using OSGi.
And the answer to your underlying question of how to share spring context, officially you share spring bean instances between contexts using OSGi (spring dm)
Try moving the event publisher to the web context file, where it should have visibility over the whole application context. A similar issue occurs when configuring method security in the parent application context. The parent application context (loaded by ContextLoaderListener) isn't aware of the child (web) context.
You can also use a single application context for the entire application if you don't really need the parent-child relationship between the two. Often it just gets in the way and it is easier if all beans were defined in the same space.
As stated in documentation for the spring framework the simple ApplicationEvent mechanism is only designed to be used within the same application context, I am not aware that it is possible to propagate events to child contexts.
If you need a more advanced solution you might look into using a more enhanced solution like Java Message Service or Spring Integration.
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-functionality-events
We can use the import tag to import/bridge the 2 different contexts created in a way the visibility of the events/beans are available and shared.
<import resource="applicationContext_name.xml"/>
In this import the context xml which is configured to be created from ContextLoaderListener in the context xml of the DispatcherServlet.
This question already has an answer here:
Using special auto start servlet to initialize on startup and share application data
(1 answer)
Closed 7 years ago.
I would like to perform some action as soon as my application (Enterprise Application with Business Logic, EJB, and a Client, Web) is deployed.
For example I would like to make some entity in a persistent state, or otherwise create a file.
How can I do that?
Thanks.
Configure SerlvetContextListener and override contextInitilized()
in your web application description , web.xml
<web-app ...>
<listener>
<listener-class>com.someCompany.AppNameServletContextListener</listener-class>
</listener>
</web-app
package com.someCompany;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class AppNameServletContextListener implements ServletContextListener{
#Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("ServletContextListener destroyed");
}
#Override
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("ServletContextListener started");
// do the things here
}
}
The "default" way is to have a servlet with an init() method. Then in the servlet-descriptor you mark this servlet as load-on-startup 1:
Example:
<servlet-name>Seam Resource Servlet</servlet-name>
<servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
As soon as the servlet is deployed (which happens after the EJBs are deployed), that init() method is called and you can execute the task you want.
With present web application in your ear, the easiest and simplest would be to use ServletContextListener, otherwise in EJB 3.1 you could use automatic timers or startup singleton session beans.