Java EE Enterprise Application: perform some action on deploy/startup [duplicate] - java

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.

Related

How to initialize some class, which is not a Servlet on glassfish4? [duplicate]

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 have web application in Java code, which uses servlets. My question is how to initialize some java class, which is not servlet. I understand that if the client connects - the servlet then prints the output. But only "if client connects".
Is it possible to run some threads before any connections are made?
EDIT:
Thanks to answers, right now I'm trying to do it this way:
the class:
package com.xsistema.filemanager.application;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
*
* #author Ernestas Gruodis
*/
public class ServerInit implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("Initialized");
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("Destroyed");
}
}
And the glassfish-web.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
<context-root>/file-manager</context-root>
<class-loader delegate="true"/>
<jsp-config>
<property name="keepgenerated" value="true">
<description>Keep a copy of the generated servlet class' java code.</description>
</property>
</jsp-config>
<listener>
<listener-class>
com.xsistema.filemanager.application.ServerInit
</listener-class>
</listener>
</glassfish-web-app>
And I getting this error while deploying the application:
Warning: Unsupported deployment descriptors element listener-class
value com.xsistema.filemanager.application.ServerInit.
What's wrong here?
EDIT2:
Can not delete this question, appeared to be duplicate (it has the answers already). But I found the solution:
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.servlet.ServletContextEvent;
#Startup
#Singleton
public class Config {
#PostConstruct
public void init() {
// Do stuff during webapp's startup.
}
#PreDestroy
public void destroy() {
// Do stuff during webapp's shutdown.
}
}
Very nice and easy, and working :)
The preferred way to do this is to install a ServletContextListener.
These get a chance to run code when the container starts up and shuts down.
If the code affects only a single servlet (or needs to initialize something private to that servlet object), you could also do the work in the init method of the servlet and make sure that the servlet is loaded even before a request is made (via the load-on-startup parameter).
You may run your code that initializes the other classes in the init() method of one of your servlets.

Executing task after deployment of Java EE application

I have a Java EE application which should start a synchronization process with an external system once after its deployment.
How could I implement this requirement?
Below are listed a couple of popular methods for getting lifecycle callbacks in JavaEE apps.
Create a javax.servlet.ServletContextListener implementation
If you have a web component to your .ear file (embedded .war) or your deployment is a .war by itself you can add a ServletContextListener to your web.xml and get a callback when the server starts or is shutting down.
Example:
package com.stackoverflow.question
import javax.servlet.ServletContextListener;
import javax.servlet.ServletContextEvent;
public class MyServletContextListener implements ServletContextListener{
#Override
public void contextInitialized(ServletContextEvent contextEvent) {
/* Do Startup stuff. */
}
#Override
public void contextDestroyed(ServletContextEvent contextEvent) {
/* Do Shutdown stuff. */
}
}
and then add this configuration to your web.xml deployment descriptor.
$WAR_ROOT/WEB-INF/web.xml.
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee">
<listener>
<listener-class>com.stackoverflow.question.MyServletContextListener</listener-class>
</listener>
</web-app>
Create an EJB 3.1 #Startup Bean
This method uses an EJB 3.1 singleton to get a startup and shutdown callback from the server.
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Startup;
import javax.ejb.Singleton;
#Singleton
#Startup
public class LifecycleBean {
#PostConstruct
public void init() {
/* Startup stuff here. */
}
#PreDestroy
public void destroy() {
/* Shutdown stuff here */
}
}
I tested the suggested solution which uses the #Startup and #PostConstruct annotations. It turned out that Glassfish does not complete the deployment of an application until all methods annotated with #PostConstruct have finished. So in my case the deployment would take from several minutes up to an hour.
But I figured out a different way to achive what I want. The best solution seems to be a timer callback method which cancels its timer after its execution.
#Stateless
public class SynchronisationService {
#Schedule(hour = "*", minute = "*", persistent = false)
protected void init(Timer timer)
{
doTheSync();
timer.cancel();
}
}
Using a non-persistent timer allows the timer to be re-created if the application server is restarted.
You can use the #Startup and #PostConstruct annotations to perform tasks on application startup.
Using a ServletContextListener, or a servlet that is initialized at startup, for example. Of course, this becomes much harder if you have multiple deployments of the application in a cluster, and only want this process to be run once.

Call method on Apache CXF initialiaze

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.

How to bridge Spring Application Context events to an other context

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.

Where is the main() method In a JSP/Servlet application? [duplicate]

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.

Categories

Resources