Showing the right "Running" status in tomcat manager - java

I'm running a servlet in a tomcat container.
All is working correct, tomcat calls the init method of my Servlet and it starts correctly.
When I look at the Tomcat Web Application Manager - List Applications I see the running status is "true".
In the init function I want to check some important settings.
If a check fails, I throw a new ServletException. Now I thought that the running status would change to "false" but it didn't.
So my question is how to stop the servlet from a check in the init function.
Or maybe I just do it the wrong way.
Would like to get some help, thanks in advance

The Manager does not show the status of individual servlets but of the web application. Individual servlets can fail to start but that doesn't stop the web application from starting.
If you have some checks you want to perform that need to stop the web application starting then put those checks in the contextInitialized method of a ServletContextListener and throw a RuntimeException (or a subclass of it) if the checks fail.

Related

Stop the deployment if any error in the servlet context listener [duplicate]

I have a ServletContextListener which performs some database management functions when my Java EE application starts. This runs in my application before JPA and other pieces of the application are started/loaded. If the database maintenance fails I am logging the errors. If the database maintenance fails the application will not function properly and I would like to halt the application.
How can I gracefully and correctly stop the application from ServletContextListener.contextInitialized?
Solution given by Viven below is close but not quite. When I throw a RuntimeException Glassfish is left in an inconsistent state where its admin console is not accessible but some process is still running and keeping port 3700 (IIOP?) open which then prevents a restart.
In your listener, catch any exceptions and use servlet context attributes to store flags or other useful information about the error. You should probably also log something to indicate that the app is non-functional.
At this point, your options may be dictated by the architecture of your app. If all requests are handled by a single controller/dispatcher servlet, it might make sense to have its init method check the context attributes and throw an UnavailableException. Just be aware that the exception only applies to the specific servlet throwing it. This makes the approach less manageable if your app contains many servlets or allows direct access to other resources.
Another option would be to create a filter that intercepts every request, checks the context attributes and then throws an exception. Other variations are certainly possible.
If your ServletContextListener throws an exception, the webapp won't load correctly and the application server may block all subsequent request (and respond with a 500 error).
It isn't exactly preventing the application to start, nor stopping the application, but it prevents any further usage of the app and could be useful in your case.
After proper verification in the spec, this behaviour isn't mandatory in the specification. The server may (not must) return 500 errors. This solution has to be used carefully, therefore.
See this Answer for a quote from the Servlet spec.

How to find the entry point in a java web application to debug?

I am trying to debug a java web application. I have configured tomcat in eclipse, added my application to tomcat and started the tomcat in debugging mode.
Now, when the user performs any action on the web page, the request hits the server, goes through some java/tomcat classes and finally reaches our application code.
If I know which of the application classes/methods will be executed, I can set a breakpoint and start debugging from there. But if I don't know which code will be executed, how can I set breakpoint?
Basically I am trying to figure out which application class/method is executed when user performs an action on the page.
I know I can set a breakpoint in the Servlet doGet/doPost method. But we are using struts and we have many more general servlets also. So it is difficult to set breakpoint in all of them.
Please help.
Check your Tomcat logs (or console). You should see which part of code is executed when you are doing something on your web page then set breakpoints. When you finally catch the program somewhere try to find a better place according to stacktrace in your debugger.
Look in your struts-config.xml file and find the action that matches your URL. Most Struts implementations use the *.do pattern to match Struts actions. The path part of the URL without the .do will match an action configuration in your struts-config.xml file. Find the action class that is called and put your breakpoint in the execute() method.

Clean up after servlet if init() failed

I have an Initializer class that implements the ServletContextListener interface. In its contextInitialized() method, I initialize some global classes that have to be destroyed, otherwise the servlet cannot be unloaded.
However, when the servlet's init() method throws a ServletException, the contextDestroyed() method never gets called --> resources are not release --> servlet does not get unloaded by Tomcat (it remains in "running" state even though its init method never finished).
My question is this - how do I cleanup the resources in this case?
Bonus: why does the servlet even get to "running" state? I understand from the documentation that it's not supposed to be running unless the init() method finishes successfully.
Edit - I think this is because each status line displayed in Tomcat Manager represents an entire war, and not a servlet. A war may contain several servlets, with some succeeding to start and others not. The Initializer is called when the container starts, and its destroy is called only when the entire container is dropped. This leads to a related question - is there a similar built-in way to monitor the state of individual servlets?
(I'm aware I can write custom code to monitor the servlet, either via JMX, or not, but that's out of the scope of
this question).
As far as I can tell there's absolutely no way to do so without an external request. ServletContextListener gives you the correct signal (when all servlets have been initialized - successfully or not), but you can't enumerate all servlets in the context to test their status because the relevant ServletContext methods were deprecated and now return an empty enumerator.
In short, the only way to do this is via a nonstandard API; in particular, it's almost trivial to do this with Tomcat's JMX API, which is the course I'd recommend.
In real world the init() should never fail. If it fails, then it is a programming error which the developer is supposed to fix. The appserver webcontainer has nothing to do with it. The servlet will simply be kept unavailable.
What container are you running?
Tomcat for example does support JMX. You can always write your own JMX-beans.

Start / stop a web application from itself?

I've made a web application using Java, Struts and running over Apache Server and Tomcat. It would be very useful to be able to restart the application from the web. I don't want to restart Tomcat, only this webapp, the same way as Tomcat Manager does it.
Do you know how can I do it? If not, any way to simulate that behaviour (reload config.properties, make Hibernate init process, etc)?
Thank you a lot.
I took a quick look at the source code for the Tomcat Manager. It looks like there's a class that's part of the Tomcat source called "Container Servlet". From the javadocs:
A ContainerServlet is a servlet
that has access to Catalina internal
functionality, and is loaded from the
Catalina class loader instead of the
web application class loader.
A ContainerServlet automatically gets passed a wrapper that can be used to get the Context and Deployer -- and the Deployer has helpful methods such as start(String contextPath) and stop(String contextPath) that will do what you want.
So, what I think you would need to do is write your own servlet that inherits from ContainerServlet, and configure Tomcat to load your servlet using the Catalina class loader (look at how the Manager is configured to see how). Note that this is probably not going to be an option for you in a hosted environment.
Then your servlet could have, say, a button you press to reload the application. I recommend putting password-protection of some kind in front of that. :)
Just hit the URLs
http://<username>:<password>#<hostname>:<port>/manager/stop?path=/<context path>
to stop and
http://<username>:<password>#<hostname>:<port>/manager/start?path=/<context path>
to start. That simulates you using the manager application.
Tomcat Manager offers an http interface to start/stop an application and other tasks. There are Ant tasks that you can use to easily access these operations.

Eclipse Servlets take a long time to update

I'm testing running a simple Servlet from within Eclipse. When I click 'Run', the console says it is starting TomCat, and then an internal browser launches within Eclipse which shows my code.
However, if I make any changes in the servlet and click 'Refresh' in the browser, the changes don't show. Then, a few seconds later if i hit refresh, the changes begin to show randomly. So I'm guessing there's a cache setting somewhere that controls this.
How can I turn that cache setting off or otherwise make the Eclipse internal browser update instantly as soon as I hit refresh?
This is caused by the way servlet developing works. When modifying your servlert, it needs to be submitted to the servlet container after compiling it. The servlet container itself needs to reload the servlet, the servlet must be instantiated (servlet lifecycle). Thats a lot of things to do, which may cause you waiing for an update visible in the browser some seconds.

Categories