How to properly manage Tomcat web apps inside Eclipse? - java

I used to run Tomcat separately on my machine. I had an Ant script that would rebuild my project, deploy it locally, and restart Tomcat. That all worked ok, but I wasn't able to debug the web app inside Eclipse.
So I learned how to setup Tomcat inside Eclipse and got my web app running. Now the problem is that I don't understand fully how to manage it this way. Eclipse is set to automatically build my project on changes, but those changes don't seem to always be reflected in the web app. Sometimes I have to manually build the project and manually "clean" the server for the changes to be reflected.
Are there rules somewhere about how to manage this setup? For instance, if I only change a JSP then will it automatically be synchronized? If I change a servlet class, then I need to manually rebuild the project? Are these rules consistent, or should I just manually rebuild and clean every time?
I would really appreciate it if someone could give me the best practice rules or point me to a good resource to learn how to manage this environment.
PS. I am using Eclipse 3.4.1 Java EE package and Tomcat v5.5

You can use Eclipse and Tomcat in the way you mention. First the basics of how to set it up:
In the Servers view setup a new Tomcat server pointing to your TOMCAT_HOME
Make sure your project is an Eclipse "web project". You may need to create a dummy one and copy over some of the files in .settings (look at the wst files).
Deploy your project to Tomcat by right clicking on the server in the Servers view and "Add and Remove Projects..." to add your project to the server.
You can run your server and test it out just like you were running Tomcat outside of Eclipse. If you run the server in Debug mode you can set breakpoints and step through the code.
As for when you will need to restart the server Eclipse is usually pretty good about auto-deploying the changes. You will pretty much never need to restart for changes to jsp pages. If you change a class it will auto-deploy the change (usually) if you change the body of a method. If you change the signature of a class (add or remove a method or change args for it) you will almost always need to restart. Any changes to configuration files (web.xml or similar) will also almost always require a restart.
To restart just click on the "Debug" or "Run" button in the Server view. All your changes will be redeployed into Tomcat.
One thing to watch out for is that in the default configuration your "webapp" directory in TOMCAT_HOME will not be used. Instead it will use a folder under your Eclipse workspace directory (WORKSPACE/.metadata/.plugins/org.eclipse.wst.server.core/tmp0).

Normally you should republish the application to get latest changes, don't forget to synchronize with file system first in case your files modified extrernally.
You can specify that your application is automatically reloaded when modified, look for Auto-reload attribute in server.xml of your server configuration project. When set to true, tomcat will automatically reload your application. It's not always a good idea by the way.
Modified JSP's should work automatically, no need to restart the applciation.

If you change the structure of a class that has already been loaded and used (add/remove members, change method signature etc.) your code changes will not be reflected. This is not an eclipse issue but a JVM issue. If you make simple code changes, like logic changes inside an existing method, your changes will take effect after the class is compiled and re-deployed.
Regardless of that, if you change a public constant, you have to rebuild your project(s).

I found two things important to understand:
Eclipse does not automatically realize if files were changed outside of Eclipse. clicking Refresh on a project does that, so does F5. You can also change a setting to refresh automatically, which, however, does not detect changes instantly (my gut feeling says up to 10 secs delay)
Working with servers has the concept of "Publishing" files to Tomcat. This normally happens automatically within a second after any change. Changing many classes can cause many server reloads, which can be a drag if a context reload takes some time (as complex Spring apps certainly do). So I changed a setting to not publish automatically (double-click Server instance)

Related

Is it possible in Tomcat/Java EE server to deploy app in RAM memory, to speed up development?

Even if we enable "deploy on save" with our IDE, we still need to wait some time to propagate changes. This can be annoying espacially when we deploy small changes.
So, is it possible to run some servlet container in-memory with IDE-compatible deployment to speed up deployment and development time? Or even run whole container in-memory with server dependencies (JSP compilator etc.).
(I know that I can install Tomcat on RAMDisk, but looking for "more native" solution)
According from their site
JRebel is a JVM-plugin that makes it possible for Java developers to instantly see any code change made to an app without redeploying. JRebel lets you see code changes instantly, versioning classes and resources individually and updating one at a time instead of as a lump application redeploy. When developers make a change to any class or resource in their IDE, the change is immediately reflected in the deployed application, skipping the build and redeploy phases and preventing an average of 5.25 work weeks per year in redeploys!
http://zeroturnaround.com/software/jrebel/
The first thing you can do is to set the deployment path to your webapps directory. This way you deploy the application "exploded" without copying the whole app to another deployment directory. Make sure to let the classes be compiled into the WEB-INF/classes directory.
A second, more problematic thing is, the class loader. When the JVM runs in debug mode, some code changes made within methods will be recognized by the class loader and you would see the changes immediately. But some changes, like method signature and structural class changes will not be detected, so a restart of the JVM will be necessary. You can provide a self brewed class loader which will be able to reload anything when the underlying class files changes.
The tomcat container is loaded in memory when you start it. And tomcat loads all the applications available in webapps directory. Later as and when application classes are required are loaded. And application may load some other resources as required.
If you open the task manager on windows or similar thing on other OS, you can see that tomcat java process is always runnning once started. You may also check its current memory footprint . So it is not unloaded and re-loaded on demand.

Java class reloading

I'm using jboss server and having all my classes inside a jar file.
Now if I change any of the java files, I need to replace the class file in the jar and have to restart the server.
Is there any way to dynamically load the newly created class file without the server restart?
Thanks in advance.
I've had great success with JRebel (http://www.zeroturnaround.com/jrebel/). This is a very good product that enables seamless class reloading for the vast majority of modifications you can make to a Java class. There is no restarting of the app sever or even the application required, classes simply reload behind the scenes.
It comes with a free 30 day trial so you can see if it works for you.
(Disclaimer: I'm in no way connected to Zero Turnaround)
It appears that you have to trick the server into reloading your application by modifying web.xml -- meaning you can open web.xml in an editor enter a space then delete and save the file or change the modification date on the file with a utility.
JBoss doesn't seem to have a handy feature like Tomcat's reloadable="true" flag in Tomcat's Server.xml file.
there are a number of solutions, none of them particularly clean or easy.
As stated, changing the web.xml will cause the context to reload and hence refresh the source code and this can be done without restarting the server. This works because "WEB-INF/web.xml" is configured as WatchedResource in the TOMCAT/conf/Context.xml file. That is every context inherits this setting and automatically watches this file. You can remove this behaviour but you can also provide WatchedResource values in your own web.xml to watch additional files. While I don't recommend it, you could add all of your class files to this and the context would reload when you change one file.
A better solution relies on the fact that a Class can be reloaded when you discard the ClassLoader that loaded the Class. Therefore if you manage your hot swappable code in your own ClassLoader then you can refresh your code without restarting the context if you refresh the ClassLoader. Easier said than done, unfortunately but it may get you started.

RAD won't deploy class files to running websphere server (local development0

Environment: WinXP.
RAD: Version: 7.5.3 (Eclipse 3.4.2)
Websphere 6.1
I have two web projects on my local RAD environment and 4 or 5 sub jar projects. When I change classes in debug and regular start mode, the files don't get copied to the server for runtime.
So, normally I have to restart the server completely or add/remove the project all together.
I may make a change to Servlet.java
When I do "publish", the ear/application seems to restart, but my changes are not there. So I normally restart the server. This is a productivity killer.
Additional settings:
* Publish automatically turned off.
* Minimize resources. Use workspace.
What can I do to make sure that the classes get copied over.
My theories:
I have parent_first/application for the class loader/war settings. Is that an issue?
Maybe I should remove the ear and add it back to websphere
I did a clean on the server?
Delete your application from the server.
Restart the server
Go to the admin console and ensure the application is not listed in the list of applications, if it is then delete it.
Restart the server
Deploy/publish again.
Unfortunatelly, RAD with WebSphere are very unstable environment.
From my experience, debug mode is causing a lot of problems. It's mainly what you describe, changes not being seen after republish, additionally very quick memory depletion. I'm using debug mode as last report.
In normal mode everything should (read: in most cases) work correctly. You add/change some classes and make 'republish'. Sometimes it's necessary to do clean on project before republishing it.
But when the Websphere is running longer together with RAD, I observe that often something get stuck. You have there clean option on the server, with is expected to clean the cache (which included also compiled classes). You should also observe memory usage. If it's nearing the limits of JVM (memory leaks are heavy) Websphere stops to function correctly, and you must restart it.
However, I sometimes get serious issues where the clean isn't helping, and then it's necessary to remove all applications, stop the websphere (close all projects and open then again) and then start Websphere and add all applications, restarting RAD in the meanwhile. But it's not everyday, maybe every month or so...
If you are really unlucky, RAD can break your workspace, which will force you to delete all project, delete project files (or do a fresh checkout) and import everything once again, or even start a new workspace (happens also with 'normal' Eclipse, ~1-2 years).
You are using the latest RAD so do I... here is my guide for solving this issue:
Enable the error log to see if you get intuitive info on internal RAD errors, in 7.5 it is available on "Show views"
If your changes are not deployed Clean project
If your changes are not deployed yet Rebuild project
If your changes are not deployed yet Redeploy project
If your changes are not deployed yet Clean server
If your changes are not deployed yet Restart server
Or:
- Use ant or maven to make deployments straighforward and ignore the pain due to websphere and eclipse having internal bugs (which you may see in the error log if it is fully enabled).
Regards.
Are your JSPs copied correctly? That is, when you make a change in one JSP, can you see change immediately upon browser refresh? If this works, then I see no reason why classes aren't also published. JSP auto refresh should work in normal and debug modes.
Now, is "build automatically" enabled? If no, your classes won't get compiled and transferred. Parent_first/application for class loading shouldn't be an issue.
Is the local app. server running in development mode? If not, it should be.
While developing, use debug mode. Hot deploy will assure changes to your methods are seen immediately. Changes in classes won't be seen (i.e. adding a method will require application restart).
Is your app. server using global security? I have it turned off and auto redeploy works without problems.
Class reloading has always been a problem while developing Java EE applications. Try do erase that ear file from your WAS and redeploy it again.
If all else fails, try JRebel.

java web application best practices

I'm trying to figure out the optimum way to develop and release a fairly simple web application, and I'm running into several problems. I'll outline the decisions I've made, because somewhere I've clearly gone off the rails.. Hugely grateful for any help!
I have what I think is a fairly simple web application. It contains a couple of jsps that reference a couple of java beans, and the usual static html, js, css and images.
Decision 1) I wanted to have a clear and clean release procedure, such that I could develop on my local machine and then release reliably to a production machine. I therefore made the decision to package the application into a war file (including all the static resources), to minimize the separate bits and pieces I would need to release. So far so good?
Decision 2) I wanted things on my local machine to be as similar as possible to the production environment. So in my html, for example, I may have a reference to a static file such as http://static.foo.com/file . To keep this code working seamlessly on dev and prod, I decided to put static.foo.com in my /etc/hosts when developing locally, so that all the urls work correctly without changing anything.
Decision 3) I decided to use eclipse and maven to give me a best practice environment for administering and building my project.
So I have a nice tight set up now, except that:
Every time I want to change anything in development, like one line in an html file, I have to rebuild the entire project and then wait for tomcat to load the war before I can see if it's what I wanted. So my questions are:
1) Is there a way to connect up eclipse and tomcat so that I don't have to rebuild the war each time? ie tomcat is looking straight at my actual workspace to serve up the static files?
2)I think I'm maybe making things harder by using /etc/hosts to reflect production urls - is there a better way that doesn't involve manually changing over urls (relative urls are fine of course, but where you have many subdomains, say one for static files and one for dynamic, you have to write out the full path, surely?)
3) Is this really best practice?? How do people set things up so that they balance the requirement for an automated, all-encompassing build process on the one hand, and the speed and flexibility to be able to develop javascript and html and css quickly, as quickly as if one just pointed apache at the directory and developed live? What do people find works?
Many thanks!
Edit: Thanks all for your great responses! If I could mark them all right, I would.. This has really helped me out. What I'm hearing is that best practice is to conserve the structure of the webapp in development, and run it in as close an environment to production as possible. Seems like the differences between people are the extent to which people are prepared to hot deploy resources into the servlet container, circumventing the build process for a little extra speed or convenience. That makes sense. Thanks again.
This is much like what I have to do at work, although we use ant (for now?). Also, while I use an IDE (or two), I refuse to have one as part of my build process, EVER. Somebody needs to be able to understand and tune your build.
Is there a way to connect up eclipse
and tomcat so that I don't have to
rebuild the war each time?
1) I think you're relying too much on your IDE. Usually I have an Ant build.xml that has a couple of tasks: one is "build war" the other is "update jsps." Building the war compiles all the code, packages it, deploys it to Tomcat and restarts everything. Updating the jsps doesn't restart the server, it's just a straight copy from my local files to Tomcat's deployed instance. No restart necessary since they're JSPs. Takes about half a second.
where you have many subdomains, say
one for static files and one for
dynamic, you have to write out the
full path, surely?
2) No way, Jose. So you mean any time the server name changes, you have to recompile your code? If you need to support dynamic URLs you might just want to bite the bullet and take a look at a framework to do the heavy lifting for you. I'm partial to Stripes (which supports dynamic URL rewriting out-of-the-box)... there are others.
To answer #1, I would suggest the following:
Spend some time learning maven to build your .war without eclipse. It's not that hard with the proper archetype. See here for more details: http://maven.apache.org/guides/mini/guide-webapp.html
Maven can generate eclipse projects either through mvn eclipse:eclipse or by using the m2 plugin
For deployment to your local machine and to production, use the maven cargo plugin. http://cargo.codehaus.org/Maven2+plugin and http://blank.jasonwhaley.com/2010/03/automated-deployment-with-cargo-drive.html
To answer question #2, there's nothing wrong with modifying your /etc/hosts file to mimic production. Just have a quick script that lets you add/remove those entries and flushes your dns cache. I do exactly that all of the time. (be sure to make your browser clear its cache frequently also through its relevant setting).
To answer question #3) yes this is how you should be doing things. Each build should result in a single deployable artifact that you can deploy to any of your environments in one step. You need to make sure you can do this without your IDE and use the IDE only as a tool to help you during the development phase.
Others have already answered you, I'll just comment on this (this too long for a comment btw so I make it an answer):
Every time I want to change anything
in development, like one line in an
html file, I have to rebuild the
entire project and then wait for
tomcat to load the war before I can
see if it's what I wanted.
If you change one line in an html file, there's no need to rebuild the entire project.
Note that I always rebuild the full .war and redeploy my .war but this takes less than two seconds (less than one second to rezip the .war [that's really what a .war is, a zipped file] and less than one second to redeploy it) because:
you don't need to recompile your entire project when you simply change one line in an html file
Same when you change one .java file: you can simply recompile that one file and re-war.
I wrote my own Ant build file from scratch (no Maven here) and I've got several targets. I can force a "clean build", that shall re-compile everything but typically I'm simply repackaging and redeploying the .war
You can check it for yourself: build a .war, unzip it in, say, directory dir1, then modify one .html (or one .java/.class file) and build a new .war and unzip that new .war in, say, dir2.
Then compare dir1 and dir2: now fix your build process so that you can create that second .war without needing to recompile everything.
Changing one .html, .java, .jsp, .css, .js / whatever file and redeploying a new .war should be a matter of seconds (less than two seconds if you didn't throw the kitchen sink in your Webapp).
Note that on the very same project, another developer here prefers to "hot deploy" / replace the files directly in the exploded webapp (I prefer to redeploy a .war everytime and because my complete repackage/redeploy takes less than two seconds I'm fine with it that way).
You don't need to reconstruct war file if your project is an Dynamic Web App in Eclipse and configured Tomcat server properly. Follow the below instructions:
1) Check out the below of how to configure tomcat server with eclipse:
http://greatwebguy.com/programming/eclipse/make-eclipse-and-tomcat-play-nice-together/
2) Use relative paths for your application but not absolute paths.
3) If you follow the above 2 steps properly then you have a best environment for development.
during development, you should configure eclipse and tomcat so that no rebuild/redeloy is required. just modify html/css/jsp etc, save, and refresh browser to see the result.
but before deploying to production site, you should do a clean full build and test it carefully.
domains: they should be in a config file; dev and prod should have different config files.

Restart tomcat when a class file is changed?

Why do we need to restart a tomcat server whenever a class file is changed, is there no other way?
You can configure Tomcat and make your webapp "reloadable". To do so, add reloadable=true to the <Context> element of your webapp. About the reloadable attribute, the documentation says:
Set to true if you want Catalina to monitor classes in /WEB-INF/classes/ and /WEB-INF/lib for changes, and automatically reload the web application if a change is detected. This feature is very useful during application development, but it requires significant runtime overhead and is not recommended for use on deployed production applications. That's why the default setting for this attribute is false. You can use the Manager web application, however, to trigger reloads of deployed applications on demand.
There certainly is! Start Tomcat in development mode, then each webapp will restart itself upon being redeployed.
From the Tomcat docs:
The servlet which implements Jasper is configured using init parameters in your global $CATALINA_BASE/conf/web.xml.
...
development - Is Jasper used in development mode (will check for JSP modification on every access)? true or false, default true.
There are settings you can change to adjust what exactly Tomcat will look for to check for updates. I usually deploy individual class files to their appropriate directory under WEB-INF/classes and then
touch WEB-INF/web.xml
to kick-start a restart of the application; I think web.xml is one of the files Tomcat checks by default.
On a more general note, the reason you have to do this is because in Java, when a classloader loads a class, it cannot unload it. What Tomcat has to do is use a new classloader and reload all the classes it needs.
Check out JRebel.
If you develop, your IDE should be able to do this transparently on a suitable server. E.g. the Dynamic Web Project in Eclipse knows how to talk to Tomcat.
If you deploy, then create WAR-files and deploy those. Tomcat knows how to redeploy a WAR-file.
If you're using WAR files to deploy, you can set autoDeploy=true in the Tomcat config, which causes Tomcat to watch the web application root ("webapps" by default) for new or changed WAR files. If such a file is found, it is automatically deployed.
As Pascal Thivent said, though, you can use the Tomcat Manager application (/manager/html) to start, stop, deploy, and undeploy specific applications. If the files you're changing are in a specific application, this is a good way to get Tomcat to recognize the changes.
Besides setting autoDeploy=true in server.conf , you also should be careful not to put any classes in the shared classloader. Classes which are loaded by the shared class loader cannot be re-loaded.
Your question doesn't actually say whether you are concerned about a production downtime (i.e. reduce it by reloading the classes) or you want non-stop development. So I will try to clarify using the following points:
1) using <Context reloadable=true... in your catalina.home/conf directory you can make sure that your webapp reloads when a any class changes. You can add the resource change watchlist in <WatchedResources> element.
2) But this will reload the context, re-initialise the classloader, empty it's cache, and everything will be as if the webapplication has just started.
This approach will still leave your server unusable, because you have reloaded the Servlet's context. The true "Reload" is
1) You swap the byte code of the class, with some restrictions
2) JVM will return that class when "loadClass()" is called for that classloader.
This is java instrumentation. You can write your own agent which can hook into your JVM either at the beginning or in flight. However, you cannot define new method, and change static variables. These are JVM native restrictions (for Oracle HotSpot JVM, that I know of). You can use a different JVM e.g. DCEVM which doesn't have such restriction. So it's up to you how you want to handle your problem. If you know what you are doing (!), you can get away with replacing classes one-by-one. And you can even define a "Brand New Class", reference that class object/method in an existing/loaded class and instrument it to to pick up changes.
I hope this helps. All the answers here are what you need to make your decision.

Categories

Resources