How to dynamically update (hot swap) jars in a web-app? - java

I have a webapp in a war archive which is deployed on cloudfoundry.
One of the libraries ("somelib.jar") used by the app is made by another developer.
I would like a way for him to upload several different versions of somelib.jar and test the behaviour of the app.
I have managed to get the jar uploaded to WEB-INF/lib directory of the deployment. I have also managed to unpack the jar into WEB-INF/classes. However, I have not managed to get the new version of the jar to be used. I tried various hacks such as those described in this question and this question without any luck.
Everytime, the classes/jars that get loaded the first time get used after that, even if we replace the actual .class or .jar file in the above directories.
Is there any easy way to achieve what I want?
Note: Since I dont have control of Tomcat (where it runs), I cannot configure Tomcat or make any changes to the server. I just have control on my war file, so everything needs to be done programmatically.
EDIT: the reason I want this is to reduce our testing time. Currently someone gives me a new version of somelib.jar, I repackage it into my application, upload to CF, send him a notification, then he tests the behavior of the new jar. What I would have preferred is that he upload his jar directly to CF and do the testing whenever he has a new version without the unnecessary intermediate delay.

In tomcat 7, you can version your WAR file and the new versions will gradually kick in.
http://www.tomcatexpert.com/blog/2011/05/31/parallel-deployment-tomcat-7

In order for you to control the application server yourself, you would need to deploy a standalone app into Cloud Foundry.
This blog should help you out with that:
http://blog.cloudfoundry.com/2012/05/11/running-standalone-web-applications-on-cloud-foundry/
This way you can custom configure your tomcat.

Everytime, the classes/jars that get loaded the first time get used after that, even if we replace the actual .class or .jar file in the above directories
That's the way that normal Tomcat (Java EE) classloading works. Your classes are loaded when first deployed, and any changes will be ignored (JSPs are managed slightly differently, but only in a development environment).
You should be able to solve this problem by using the Equinox OSGi bridge servlet. I haven't done this myself, but here's a writeup by a person that I respect.

Related

How java libraires from one EAR file could be accessed by another EAR file?

I have two .Ear files, namely A.EAR and B.EAR. The first file is my application (around 1.5 MB) and the second one contains all the needed libraries such as Hibernate, log4j, etc. (Around 70 MB). How can I deploy them on weblogic in such a way that my code in A.EAR use libraries in B.EAR?
I cannot pack them into one .EAR file, coz I need to email my app every week. On emailing I just send the A.EAR file.
I cannot put the used libraries in lib folder of weblogic, because other apps use different library versions.
Edit:
Having find the right answer, it seems that this Q on SO is somehow relevant.
You could define B.ear as a shared application library and access it from A
http://docs.oracle.com/cd/E17904_01/web.1111/e13706/libraries.htm#i1065356
This may not be a direct answer to your question, but I would question designing an actual deployable application's structure (i.e. splitting it across multiple EAR files) based on a need to "email the app every week".
To me, it seems dangerous to have 2 separate EAR files for one application. I understand that you are saying B.EAR contains non-changing libraries (Hibernate, log4j). However, by using them in A.EAR, they do inheritently become germaine to your application. In other words, your application really is A+B ... A.EAR cannot live without B.EAR.
Instead, would it be possible for you to set up some sort of revision/source control repository (SVN, Git, etc) and use Ant/Ivy or Maven to manage your dependencies?
This way anyone who needed a copy of your application could access the repository, pull down the source, allow Ant/Ivy to resolve dependencies, and build.

What's the simplest way to deploy a Grails-generated WAR file?

I've been having persistent problems (for several weeks) getting Tomcat to deploy a WAR file. I'm looking for a simple server. It does not need to have a lot of functionality-it just needs to be simple to set up. In particular I'm looking for a program that I can just drop a WAR file into and have the enclosed web application launch.
You might want to give jetty runner a try. It basically just uses an embedded jetty instance to run your war file.
http://blogs.webtide.com/janb/entry/jetty_runner
It is available on Maven and it is in fact how heroku apps built with grails are ran. http://devcenter.heroku.com/articles/deploy-a-java-web-application-that-launches-with-jetty-runner
If your application does not start on tomcat, it almost certainly means it won't start on any servlet container - containers implement a spec, and are very similar in many aspects.
What you should do is go and hunt each problem one by one, until the application starts. The problem is the app, not the container.
I recently had a similar problem where my app ran fine with "grails run-app" but not as a war file. It was caused by a missing "package" line in one of the files. I was getting 404 errors. When a war file is unpacked on the server it doesn't put files in the same directory locations as when the are in the grails environment. Not sure this will help you but maybe others with similar problems.
if you get a fresh tomcat instance, generate a hellow world app and generate your war file via grails dev war it should work without a hitch. typically problems arise form adding dependencies that clash with server libs.
if you want to give other servers a try I would suggest resin as one of the easiest to setup, run and maintain.

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.

Java EE Jar file sharing

At our shop, we are maintaining roughly 20 Java EE web applications. Most of these applications are fairly CRUD-like in their architecture, with a few of them being pretty processor intensive calculation applications.
For the deployment of these applications we have been using Hudson set up to monitor our CVS repository. When we have a check-in, the projects are set to be compiled and deployed to our Tomcat 6.0 server (Solaris 10, sparc Dual-core 1.6 GHz processor, 2 GB RAM...not the beefiest machine by any stretch of the imagination...) and, if any unit-tests exist for the project, those are executed and the project is only deployed if the unit-tests pass. This works great.
Now, over time, I've noticed myself that a lot of the projects I create utilize the same .jar files over and over again (Hibernate, POI (Excel output), SQL Server JDBC driver, JSF, ICEFaces, business logic .jar files, etc.). Our practice has been to just keep a folder on our network drive stocked with all the default .jar files we have been using, and when a new project is started we copy this set of .jar files into the new project and go from there...and I feel so dirty every time this happens it has started to keep me up at night. I have been told by my co-workers that it is "extremely difficult" to set up a .jar repository on the tomcat server, which I don't buy for a second...I attribute it to pure laziness and, probably, no desire to learn the best practice. I could be wrong, however, I am just stating my feelings on the matter. This seems to bloat the size of our .war files that get deployed to the server as well.
From my understanding, Tomcat itself has a set of .jar files that are accessible to all applications deployed to it, so I would think we would be able to consolidate all of these duplicate .jar files in all our projects and move them onto the tomcat server. This would involve only updating one .jar file on the server if, for example, we need to update the ICEFaces .jar files to a new version.
Another part of me says that by including only one copy of the .jar files on the server, I might need to keep a copy of the server's lib directory in my development environment as well (i.e. include those .jar files in eclipse dependency).
My gut instinct tells me that I want to move those duplicated .jar files onto the server...will this work?
I think Maven and Ivy were born to help manage JAR dependencies. Maybe you'll find that those are helpful.
As far as the debate about duplicating the JARs in every project versus putting them in the server/lib, I think it hinges on one point: How likely is it that you'll want to upgrade every single application deployed on Tomcat at the same time? Can you ever envision a time where you might have N apps running on that server, and the (N+1)th app could want or require a newer version of a particular JAR?
If you don't mind keeping all the apps in synch, by all means have them use a common library base.
Personally, I think that disk space is cheap. My preference is to duplicate JARs for each app and put them in the WAR file. I like the partitioning. I'd like to see more of it when OSGi becomes more mainstream.
It works most of the time, but you can get into annoying situations where the jar that you have moved into tomcat is trying to make an instance of a class in one of your web application jars, leading to ClassNotFoundException s being thrown. I used to do this, but stopped because of these problems.
I really don't think putting libraries in common/lib is a good idea. The idea behind the use of war files as applications into a servlet container, is to have a real idea of isolation between your webapps. You could face errors like deploy some third party WAR (with it own libraries inside WEB-INF/lib) and it behave unexpectedly because it loaded other version of one of it libraries from the common one (remember that the regular behavior for load classes is first look at the common classloader and if you don't find the class look into the one for your webapp). Don't even mention how painful could be to move some application to other servlet container or an Application Server.
As mentioned before, you could use maven to deal with jar dependencies, and if you like the homogeneous use of libraries, define a POM parent (maven jargon) across all your applications.
In my experience you should be very careful with sharing libraries between web applications by moving them into the web container itself.
Let them live in WEB-INF/lib so your wars are self contained (you WILL be glad you did one day).
What you might consider is employing maven or Ant Ivy to pull in library jars from a common repository instead. This is very useful and should not be a problem in your scenario.
Edit: A notable exception is the Metro library - web service layer from Glassfish - which needs to be in the web container and not in the web application.

Categories