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.
Related
Massively messed up production issue:
I have inherited a massive ( 1 million line code base ) web application that my predecessors botched up completely.
They thought it would be a wonderful idea to just add the WEB-INF/classes directory the the system classpath in the startupWeblogic script instead of properly packaging up the application in an ear or war file, and manually point all the paths in the console to the various non-standard paths they just conceived of themselves.
Now my problem is I have to install another application as a proper war file that uses classes with the same packages and names, just even older code, into the same Weblogic 10.3.6 instances. But as you can imagine the stuff that is hacked into the system classpath takes precedence over everything in the additional webapp, even with the prefer web app lib preference set in the weblogic.xml file.
Notes:
Repackaging the offending application is not an option on my timeline, it is going to be done, but just not in the timeline I have to meet. Running on other instances of Weblogic isn't in my timeline either, I don't have the time to go through the provisioning process to get the assets in time.
Given this how can I get this additional webapp to play nice and deploy in the same weblogic instance as the one that is hacked into the system classpath.
If someone can give me an answer that solves this issue, I will make sure to put a massive bounty on this when I am able to and award it to you after the fact. The sooner the answer the bigger the bounty will be!
Did you try prefer-application-packages within the weblogic-application.xml as well?
The mechanism that Weblogic calls the Filtering Classloader, here are the links:
http://docs.oracle.com/cd/E15051_01/wls/docs103/programming/classloading.html#wp1097187
http://hasamali.blogspot.in/2011/08/weblogic-identifying-class-conflict-and.html
http://atheek.wordpress.com/2011/12/20/weblogic-filtering-classloaders/
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.
We have developed a web based application in java(STRUTS 2.0). Now we want to deploy the application. The client is having one pre UAT environment ,UAT environment and a production environment.
Now when we are deploying for pre-UAT we have created the copy of our project and renamed it to pre-UAT. Similarly we are planning for UAT environment and one we already have for development. So in all we will be having 3 copies of our code.
I want to ask is this approach correct or what is the standard approach followed. This is not our final release as we are first releasing a version and then we will be working on other modules.
So please can anyone guide me for approach to follow for creating this 3 different environments.Thanks in advance
I am not sure what you refer to by "we will be having 3 copies of our code". If you are implying that you actually copied the code-base around multiple times, please stop reading and refer to this:
Why is "copy and paste" of code dangerous?
And once you finish reading, do some research about source control and how to use branching/tagging for concurrent development.
If you were referring to multi-environment deployment:
Assuming your application is designed correctly (and I'm treading very carefully here), one WAR file (you were mentioning you're using Tomcat, so I am concluding that your application is packaged as a WAR) should be sufficient. The application code should be environment-independent and should read its environment-specific configuration from external resources, such as a database, configuration files or JNDI.
If your application code is environment-independent, then all you need to do is simply deploy the WAR file to each of the environments (the same WAR file), plus the environment-specific set of external artifacts (such as configuration files).
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.
I am developing a WebSphere portlet in IDEA 11. The portlet is using some methods defined on portal. I don't have the production environment compiled classes or jars on my PC but I have the source code.
Can I somehow "attach" the .java files to my projects in order to build a war file that will be deployed into the production environment? Or do I have to build the production sources first (this seems to be harder since there are lots of dependencies)?
If this is just to test something while you await the JARs/compiled classes, you can likely do this by only bringing over the API (e.g., referenced interfaces that hopefully don't have external dependencies). Then, open up the compiled WAR and remove those .class files manually to avoid collisions with the real code on the server.
The biggest problem is that you will definitely run into issues trying to limit the exposure to the real code, unless the rest of the code was setup nicely to expose an API that has very limited dependencies.