I have a simple web project which changes a line of text with another at the click of a button. What I want is a core Java method which will recognise when the .war file is deployed on the Tomcat server.
I want to output the exact time when the deployment happens. I have the code ready for that, and I want it to be in core Java.
Is there any such method that will allow me to perform some activity when the deployment happens?
You can use a ServletContextListener.
Add a <listener> tag in your web.xml file as follows:
<listener>
<listener-class>classes.MyListener</listener-class>
</listener>
And make a Java class implement the ServletContextListener interface. Overriding the contextInitialized() method and writing your code in it will do the trick.
For example:
package classes;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.joda.time.DateTime;
public class MyListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("Project deployed: " + new DateTime());
//or any other form of output
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("Project undeployed: " + new DateTime());
//or any other form of output
}
}
Hope this helps!
Look to see if the WAR file has been unzipped (exploded) in the webapps directory. This itself can be done two different ways, by looking to see if the exploded directory is there. Or by looking at the access time of the WAR file. Please note to see the access time of a file in *nix you have to use the -u option in the ls command.
But this has a flaw in the you cannot tell when the webservice has finished initializing. For that you can create a keepAlive service that you can poll in your webservice. That way when your application is done initializing you will get a response from the keepAlive. You can set a high loadnumber on this service to allow all the other Servlets to load first.
curl "http:localhost:8080/MyWebService/keepAlive"
Furthermore, I know specifically with Tomcat you can query its JMX monitor. I do not know if it has a JMX query to list out loaded Servlets, but it might and it is extensible so you can add your own queries for finding that out.
EDIT: You can also setup your Servlet to log when it is done initializing. Then just grep "your services' log msg" in a loop till it exits with exit code 0.
Related
I am working on a servlet (containing a Jersey REST server) which I ship in the war format. I wrote extensive unit tests to thoroughly test the code base. However, I often have the problem that the war does not start correctly.
This is mostly due to me making some kind of mistake in the web.xml file. For example, I rename some class mentioned in the xml without changing the corresponding line in the xml itself. The problem is that in my tests I create a debug Application so the xml is never considered. More to the point, lets say I have the following (Jersey) ResourceConfig:
import org.glassfish.jersey.server.ResourceConfig;
public class MyConfig extends ResourceConfig {
public MyConfig() {
register(...);
}
}
Now suppose I have an error in the web.xml:
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>MyMisspelledConfig</param-value>
</init-param>
My unit tests look like this:
public class ServerTest extends JerseyTest {
#Override
protected Application configure() {
return new MyConfig();
}
#Test
public void test() {
//...
}
}
The tests pass but the deployed servlet won't even start...
Is there a way to automatically test the default deployment (including the web.xml)?
The only way I know for testing the deployment descriptor web.xml is to deploy the war on a local server on the developper machine (tomcat or jetty are good candidates). Netbeans or Eclipse offer nice integration for that, opening a browser window to the root of the web application.
You can then manually view some pages, or if you prefere automated tests, you can use the excellent Selenium that plays some recorded scenarii controlling portions of the received pages.
We're migrating an existing application to Spring Boot. The application in question (Genie) acts as a distributed, scalable client for data processing clusters like Hadoop or Presto. As such we need to output results of queries to disk and allow users access to their data. In the past we've done this by enabling directory listing in Tomcat where we would deploy our war and allowing users to browse and access their files using the DefaultServlet.
I tried exporting the directory using resource handlers like so:
#SpringBootApplication
public class GenieWeb extends WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter {
// Other configuration
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
final String myExternalFilePath = "file:///path/to/dir/";
registry
.addResourceHandler("/urlPath/*")
.setCachePeriod(0)
.addResourceLocations(myExternalFilePath);
}
}
This works fine when the URI of the resource is known but any request for a directory returns a 404. Ideally this would behave the same way the DefaultServlet in standalone Tomcat behaves when listings is set to true as an init parameter.
I've tried various ways to access the Tomcat configuration and the DefaultServlet in particular but have had no luck enabling directory listing via the typical "listing" property.
Excessive searching didn't turn up any results so I was curious if anyone knew if this was possible before I resign myself to going back to a WAR build or fronting with Apache. The main reason I don't want to do this is to make deploying our application as painless as possible and having everything self contained in one jar file has a lot of appeal.
Thanks in advance!
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'm trying to run a java web service on Glassfish. There is some initialization code that sets a few variables and retrieves some information from the Glassfish environment itself.
I have that code in a static initializer inside the #WebService class, however this code appears to be called too early, it gets run as soon as the WebService endpoint is deployed, whereas I need it to run once the whole web service is successfully deployed.
I tried moving the code into the constructor of the WebService class, however then that code was only run when I went into the Tester web page and sent some data to make the web methods run.
Is there any way to set up some initialization code to be run as soon as the whole web service deployment is completed?
Option 1: In Glassfish you have the Lifecycle modules
Option 2:
You also have the ability to code a ServletContextListener to be triggered when the context is loaded:
public class MyServlet implements ServletContextListener {
public void contextInitialized(ServletContextEvent e) {
// implementation code
}
public void contextDestroyed(ServletContextEvent e) {
// implementation code
}
}
Reference:
About Life Cycle Modules
Example of ServletContextListener
Yes #Jaynathan Leung, with soapUI can you deployment the web services and testing your programming with input and output data. I hope help you. :)
In most of the Java projects using Spring, I find this entry in web.xml which is executed at server start-up:
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
What is the purpose of Log4jConfigListener?
In my legacy project I can also see this setting. However when i dive into the code I do not find anything special done in this class or further classes called internally by this class. I am sure there must be some good purpose behind putting above code snippet and I am missing it.
In every class which putting the logs in file here is the entry
private static final Log log = LogFactory.getLog(PoolManagerImpl.class);
log.debug("Number of connection pools to create = ["
+ connection.size() + "]");
Even if I comment out my web.xml entry, logging works fine. So what is it's purpose?
The Log4jConfigListener initialises the Log4j "subsystem" as soon the webapplication starts up, as opposed to "lazily configuring" it as soon as it is needed.
In my opinion, the main advantage of explicitly initializing log4j via the Log4JConfigListener is that it allows you to configure the location of the log4j configuration file through using servlet context parameters; depending on how the application is deployed, this may make it possible for the configuration to be changed at runtime by some kind of admin user without having to dig around inside the exploded WAR directory .
See the javadoc for Log4jConfigListener, and more importantly Log4jWebConfigurer, as it does the real work.
I have a java application that up until now was run as a stand alone java application (i.e. executable jar). I now need to deploy it in Tomcat as a servlet. It doesn't need to actually process any HTTP requests though, but it needs to be started using tomcat.
What are the steps required to convert the project so that it can be deployed in Tomcat? I'm using maven as a build tool and Java 1.5.
I understand that you want to run this app on server's startup. The best way would be implementing ServletContextListener and run the app in the contextInitialized() method. E.g.
public class Config implements ServletContextListener {
private YourApp yourApp;
public void contextInitialized(ServletContextEvent event) {
yourApp = new YourApp();
yourApp.start();
}
public void contextDestroyed(ServletContextEvent event) {
yourApp.shutdown();
}
}
Register this in web.xml as follows:
<listener>
<listener-class>com.example.Config</listener-class>
</listener>
That's it. No need to wrap it in flavor of a HttpServlet as you aren't going to fire HTTP requests on it.
You however need to ensure that it runs in its own thread, otherwise it would block the startup. If it doesn't, then wrap it in a Runnable and execute it using ExecutorService.
I'm assuming that your app is continuously running and you have an app/web server already (e.g. Tomcat/Jetty), such that it's making your life easy to deploy into it. Given that, you need to:
extend an AbstractHttpServlet class and in particular the init() method. This would start your app.
build a web.xml that references this and sets the load-on-startup attribute to 1 (or at least non-zero)
build a .war from this and deploy it
Step 2 ensures that the init() method is called upon deployment/server reboot, and so you don't have to respond to HTTP requests (a normal startup trigger for a servlet).
It may be simpler and more appropriate to use something like javaservicewrapper, and wrap it up to be a Windows service or similar.