How do I make Tomcat stop caching my servlet responses? - java

I'm learning Servlets programming, using Apache Tomcat 6 on a Ubuntu 8.10 machine, and I'm running with a very annoying issue -- apparently, related to caching.
This is what I'm doing: I write a servlet, put it in a nice directory structure and deploy it using the Tomcat Web Application Manager. It works as expected. Then I edit the servlet, recompile and try to access it again, but Tomcat keeps returning the same old version. Reloading the Application or even restarting the server does not work. The only thing that works is "Undeploying" the Application, then deploying it all over again.
I have to do this every single time I make any small change on my code. It sucks.
I'm sure there is a way around this, but I couldn't find the answer anywhere on the web (and I did search a lot). I would really appreciate any help. Thanks!

The advice from Adeel Ansari is flawed: you should never modify CATALINA_HOME/conf/context.xml with webapp-specific configuration. That's what your-webapp/META-INF/context.xml is for.
You should also never specify the "docBase" attribute of <Context>.
You should also never specify the "path" attribute of <Context>.
The OP has several options:
Use the manager to reload the web app (undeploy/redeploy should not be necessary: a simple reload should work)
( http://tomcat.apache.org/tomcat-6.0-doc/manager-howto.html#Reload_An_Existing_Application )
Set the element in META-INF/context.xml to have reloadable="true"
( http://tomcat.apache.org/tomcat-6.0-doc/config/context.html )
With all due respect to SO, if you need help with Tomcat, join the users' mailing list and get some real answers.

I have encountered similar problems with Tomcat 5.5. I never figured out the root cause but I worked around it by deleting the folder corresponding to the webapp from %CATALINA_HOME%/work/Catalina/localhost. Its not a great solution but it avoids you having to undeploy/redeploy your whole application.

Under your TOMCAT_HOME/conf/, you will find a file named Context.xml. The content would look like below,
<Context>
<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>WEB-INF/classes</WatchedResource>
</Context>
Both lines are uncommented here, you should uncomment both too. Its likely that you will have the 2nd one commented or might not have it at all. Try uncomment it, or add it in latter case. I am assuming you are deploying your app under TOMCAT_HOME/webapps.
[Edited]
Try using docBase, and path attribure under your Context element. Below is the example
<Context docBase="path-to-WEB-INF" path="/your-app">
NOTE: Don't include WEB_INF
[Edited]
May be I am missing something. Check this out. Its the same, but much more clear and descriptive including few other options.

You don't say if you are using the ubuntu tomcat or a separate download from tomcat.apache.org. If you are using the ubuntu one, try to make it simpler with using a separate download. The standard download is very easy to administer and rather geared to working out of the box. It might be (I don't know) that the ubuntu one might be configured more towards production use, e.g. it might be somewhat hardened.
The recommended production setting for tomcat is just what you describe (e.g. no auto-deploy etc). The development setting is way easier to use.

If you use Netbeans then it automatically recompiles the class and injects it into the running webapp when you save the file. There are no additional steps involved, just hit save.

Related

Intellij IDEA + JBoss doesn't update LESS files on runtime compilation

unfortunately googling didn't help :(
I have deployed a simple project on JBoss5.x integrated in my Intellij IDEA.
I use some mvc frameworks with JSP pages.
So I run my project, works with it and when I edit any JSP I can just click "Run" >> "Update JBoss" >> "Update resources" and all my changes to JSPs will be applied without redeploying the server.
But this doesn't work with LESS files (LESS is for dynamic css). I cannot figured out why? Any hints?
PS: less file is mentioned on JSP correctly, so it is applied normally, but changes to it cannot be applied without redeploying.
Try deploying the files directly, not through IDEA, to see if it's a problem of your IDE configuration or a server-side issue.
If it's a server-side problem (the files don't get deployed even with the direct deploy), then try checking stuff like permissions on files, if the deployer works and if it's listening for new files, etc.. Also some files cannot be "hot-deployed" without actual redeploying of the whole module of your application.
If it's a problem with your IDE then try checking your configuration. Here are some links which should help you get started:
http://www.jetbrains.com/idea/training/demos/JBoss_server.html
https://community.jboss.org/thread/202446?start=0&tstart=0
How does Intellij deploy to JBoss?
If you have any further questions, please ask in the comments. Cheers!
Edit: I am not an expert on hot deployment, nor can I specify exactly which files can or cannot be hot-deployed, but AFAIK you can hot-deploy changes to your classes which do not change the structure of your class. This most of the time means that you can change the body of a method and hotdeploy it without any problems, however if you rename it or add new methods completely you won't be able to hot-swap them. Another thing is file discovery - files which are discovered during the startup phase of the server cannot be hotdeployed without a restart or some other way which tells the server to reload them. This might be your case.. I hope that someone will specify these hot-deploying limits better.

Methods to see result fo a code change faster

This question came to me when developing using Eclipse.
I use JBoss Application Server and use hot code replacement. But this option requires that the 'build automatically' option to be enabled. This makes Eclipse build the workspace automatically (periodically or when a file is saved?) and for a large code base this takes too much time and processing which makes the machine freeze for a while. Also sometimes an error message is shown saying that hot code replacement failed.
The question that I have is: is there a better way to see the result of a code change?
Currently I have the following two suggestions:
Have unit tests - this will allow to run a single test and see the result of a code change. ( But for a JavaEE application that uses EJBs is it easy to setup unit tests?)
Use OSGi - which allows to add jars to the running system without bringing down the JVM.
Any ideas on above suggestions or any other suggestion or a framework that allows to do this is welcome.
Did you take a look at http://zeroturnaround.com/jrebel/?
I tell you how I work. I hope it is useful. First of all, I disable "Build Automatically". Maybe it is better if you do a simple ANT script to compile and see errors/exceptions. Also, I make jar file with the same script. Afterwards, I use OSGi to check the application. Yo do not need to stop server, only you need to change versions in deployed bundles. Intead of JBoss Server I use Equinox which includes Jetty Web Server.
May you have a nice day!
With JRebel, you wouldn't have to build your project (skip the build totally). Plus, only the changed resources will be reloaded so the update happens instantly. Plus, session is preserved so you do not have re-login to the application after the update was performed.
Even though the question I asked was quite specific to Java, I thought that mentioning using an interpreted programming language that avoids the compilation step is anther way of seeing result of a code change faster.

Get current EAR path with WebLogic

In my source code, I'd like to get programmatically, the last modified date of the current EAR from which my code is deployed.
I'm using Oracle WebLogic.
How could I do that?
Thx for your answers
I'd suggest stepping back and looking at the problem you're trying to solve, Eric.
Do you want to know when the application was built or the particular version of the application you've got deployed? If that's the case, you're probably best served by incorporating something into the build process to set this. Ideally a manifest of the specific component versions used to package up your application.
If you want to know when the application was first deployed by an administrator, or most recently deployed that gets more tricky. Relying on the filesystem to solve this problem is a bad idea because you're at the mercy of whatever WebLogic Server is doing, which is admittedly more than a bit opaque.
If you absolutely need to do this, WebLogic Server's standard staging behaviour puts a version of the file in a particular subdirectory on each server instance, then very quickly pulls it apart. (it's the 'servers//stage' subdirectory underneath the root directory of the domain ($DOMAIN_HOME) $DOMAIN_HOME is the current directory for all server processes at runtime, so the relative path should work fine.
That should give you the time that file was deployed across the network, but you'd definitely want to test the observed behaviour from rebooting your server instance.
The problem with that is that it doesn't give you anything you couldn't determine more elegantly via either the build process, or WLST scripting around the deployment process.
If it's the last time the application itself was deployed (regardless of the version) then application lifecycle event listeners are definitely the best way to go. Unfortunately there's no MBean that gives you the uptime of an individual application.
There's a great reference on lifecycle listeners here:
http://download.oracle.com/docs/cd/E17904_01/web.1111/e13712/app_events.htm#i178290
You could either check the file properties or see inside the MANIFEST.MF present inside the EAR.

Create navigation menu dynamicly based on deployed jars

I am just investigating the idea of this so have no example code. I've been digging around on the web but I'm not really sure what I should actually be looking for so I'm not finding much. So I thought I'd ask and see if anyone knew if a) This is possible. b) How I should do it. (Or at least what I should be looking to learn about to do it.)
I'm building a web app using JSP pages on the client with a JBoss server running J2EE, in the middle there is a tomcat web server.
Basically the app contains different sections that will be rolled out over time as they're developed and also customers may be using different combinations of sections. The tidiest way of deploying this I can think of is to build each section into it's own jar. Then depending on the combination of sections that are relevant for the customer, install only the required jars on the JBoss server for deployment.
To support this I'd like the client navigation menu to only show the available sections based on what is deployed on the JBoss server. Is it possible for my servlet to find out what is deployed on the server? I'd like the solution to be as 'dumb' as possible, i.e. I don't want to tell it what to look for, (other than a prefix to identify our jars), as I don't know yet everything we might build.
My current solution is to have a table in the database to hold a list of the installed sections. But this is going to require update scripts etc during install and I'm sure we should be able to do this by just deploying jars on the server.
Thanks in advance.
You could add this information to the MANIFEST.MF file and then enumerate all files in your webapp (see this answer for how to list all manifests) when you start.
I do something similar by configuring a "Plugin Directory" setting for my application. It then scans that directory regularly for Jars. It looks for specific metadata in the manifest to determine whether the Jar is actually a valid plugin, and what class to load from it (the static initializer of that class registers the plugin with the application).
Then all you need to do is place a new Jar into that directory to add its functionality.

How to compile single/multiple java files without server restart? Is there any Eclipse plugin for the same?

I want to compile multiple java files in my Application without restarting Weblogic and Tomcat. Otherwise, this takes a lot of time. For this I got one Hotswap plugin in Eclipse, but this is not working in all the cases. It says it works for single file compile. Even if I use that it is not working in all the cases.
Is there any other way that I can do this or is there any other plugin/script/software which can help me in this?
If there are some open source ones, it will be very helpful.
Thanks in Advance.
One thing is compiling the classes, but you also need the JAVA VM to reload the classes and use them, which is called hot-swapping. For the best available hot-swapping of classes you'll need something like javarebel. It allows you to hot-reload a lot more types of code-changes than the regular SUN JVM. If you run your deployment in exploded-mode you're home free, and can test any code change in a second or so. We're fairly test-driven, so I only use javarebel in that short phase when I assemble the whole application, but it works really well.
The Java HotSpot VM does this automatically, but not in all cases...
First, you must be running a "debug" session, not a "run" session.
Next, some changes will force a restart. The basic idea is that if the interface to the class change (the method sigs, not an actual Java interface), the VM can't replace the class contents inline.
You shouldn't need a plugin for this, just a recent-ish VM.
This happens under several circumstances like
adding methods
removing methods
changing method signatures
changing the class hierarchy (superclasses, implemented interfaces)
It can also happen if you introduce an error into the class. (For errors like mismatched curly braces)
When you save a Java file, eclipse compiles it. If there is an error, eclipse inserts an exception throw to indicate that there is an unresolved compilation error. (It does this so when you run you don't just see the last successful compilation, making it obvious you have a compiler error)
I don't know Eclipse, but I do use Netbeans. Netbeans does this pretty well. The latest version even has an option to automatically recompile when you save a java file.
I know this doesn't exactly answer your question. You can probably use both Netbeans and Eclipse depending on what part of the project you're working on.
EDIT:
With Tomcat you can reload the web app. This is really only useful if Tomcat is looking at the new class. If your project is compiled to a build directory first and a WAR is then created from this you can go into Tomcat and install the web app and instead of pointing at a WAR point at the build directory.
In Tomcat you may have to put a site config file under tomcat/conf/Catalina/localhost. The contents of this file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="C:/Projects/MyWebApp/build/web" path="/MyWebApp"/>
Instructions for reloading here:
http://www.cs.ucl.ac.uk/teaching/java/tomcatfaq.html#changeservlet
If you do this a few times though Tomcat will run out of memory. This is because of something called PermGenSpace. Read up about it if you want to know more. The solution is to increase the JVM memory, the PermGenSize (with -XX:MaxPermSize) and finally restarting Tomcat occasionally.
EDIT2:
If reloading the app causes you to be logged out you may be able to easily get the container to serialize your session data to disk by adding 'implements Serializable' to some of your classes. Then you should not need to login after reloading the app.
I agree that it is very tedious to redeploy all the time when developing.
I would suggest you look into MyEclipse which has a very good hotdeploy mechanism which works well with Tomcat, and which is quite affordable and has a 30 day trial.
The stock Java EE mechanism in Eclipse for redeploying to servers is nowhere as fast.
I guess I don't really see where the problem is. Here is what I do and the changes load almost instantaneously. I have an Ant script that compiles the .java and .jsp files for me, puts them in the appropriate directories under webapps and changes the web.xml file if necessary (or at least touches it to notify tomcat of the changes). If you need help on doing any of that with Ant, I'd be happy to help. Btw I do not use WAR files for deployment on my testing machine. That would be a lot slower I guess.
very easily done if you read this page:
See http://blog.redfin.com/devblog/2009/09/how_to_set_up_hot_code_replacement_with_tomcat_and_eclipse.html
Thank you Dan Fabulich

Categories