Best place for Jars - java

A quick question for best practice please if anyone can help.
I am about the implement my project onto a webserver running tomcat. This will host quite a few domains which are mainly static with just HTML code. Mine however includes a database connector and also some JAX jars.
My question is
For best practice is it better to put the .JAR files into $TOMCAT_HOME/lib so that they are avaialable to all webapps, (maybe used by others in the future), or should I keep them in the WEB-INF/lib folder which is webapp specific. If I then build another webapp that uses these JARs I would then have to duplicate them in the WEB-INF/lib folder for that new webapp.
I know it would work either way but what is best practice please.

I would tend to keep them per-webapp. That gives you the opportunity to upgrade one webapp without having to touch the others. So you can roll out fixes etc. to one app without having to rebuild/retest the others.

An application server like Tomcat is designed to be able to isolate webapps from one another, enabling them to change independently, use different versions of the same libraries etc. Unless you are absolutely sure that your apps will always need the same version, and will always be ready to upgrade simultaneously (or never) to newer versions, then keeping them per-webapp makes more sense.

Related

How can a ninjaframework-web-application be split up?

I just started to develop a java web application based on the ninjaframework. Everything works great, but: With all the ninja-dependencies, the deploy-war has around 25MB. I really hope, I won't have to upload a 25MB java archive all the time - especially due to the fact, that the dependencies won't barely change as often as e.g. a stylesheet of my app.
Is there a practical solution to move the ninjaframework-dependencies to a separated jar? I am working with eclipse, therefore a solution that integrates in the IDE would be great.
So far, I have had a look into the maven dependency-scoping and have (unsuccessfully) tried to move the dependencies into a separated project and refer to the project with a system-scoped dependency (which I would in my understanding be able to deploy as a separated jar file). I currently fail at building this dependency-jar with maven - but I also wonder, if there are better approaches.
I deploy the application on a tomcat-server in a plesk installation
Another option would be to exclude libraries that you don't use. For instance if you don't use JPA you can safely exclude it from the build via Maven's xml tag.
Background: Ninja 4 potentially bundles too many libraries by default. That's cool, because everything will work out of the box without thinking about libraries needed. The downside is that the jar/war may be too big for what you want to do. There are discussions on the way to make Ninja more modular - feel free to chime in on our mailing list :)
But as written above - you can cut Ninja's bundle down yourself using Maven's exclude.
If you have to use all the dependencies, there is no way to avoid deploying them with your application.
You don't tell if you are deploying into a container (maybe Tomcat). If you do, you can try to deploy the needed libraries into the container and set the Maven scope to provided to avoid redeploying the libraries.
Having the libraries provided by the container has benefits, but it can also be a burden. Depends strongly on your deployment and operation processes.

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

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.

turn api with hibernate objects into service for multiple applications

i have an API that is being written for a large group of 40 or so applications to share.
my problem is currently they plan on having the API as a simple library included in each war file for each program. the problem thats going to occur is when two apps are running on the same instance with different versions of the api library. ive had a lot of problems in the past with this.
i seem to remember a while ago something where i can wrap my library into an ear file or something and deploy it to tomcat to make it global. simply including it in the lib folder won't work because it will include hibernate systems that have to be deployed to allow the api methods to access the database. then in each application i would have an interface i can implement that allows me to call those api methods. very similar to local EJB3 but not as complex and didn't require an enterprise level server to implement.
anyone else remember something like this or was it a bad dream on my part?
You will have problems if you use a single jar shared by all the webapps, since it will then be impossible for two apps to use a different version of a library. But if each webapp has its own version of the library in its WEB-INF/lib, the container shouldn't have any problem: each webapp has its own classloader, which doesn't see the libraries of other webapps.

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.

Incremental deployment of java web applications

We have following problem. Developers frequently need to make small changes to our web applications. When I say small, I mean things like correcting the spelling on a web page or similar. Generating and redeploying war archives can be slow and costly in such scenarios.
How could we automate and install changes incrementally? For example, generate new exploded war, compare files with exploded war in production and then replace in production only the files affected by change: .jsp .html .class etc.
This need not be hot deployment, it’s ok to restart the server. What I wish to avoid is having to copy and deploy wars that can be 80Mb in size. Sometimes connections are slow and making such minuscule change to web application as simple spelling correction can take hours.
We use Maven to automate our build process. The key issue is to automate the whole process, so that I can be sure that app v2.2.3 in my Subversion is exactly what I have in production after incremental deployment.
We used to do this sort of thing all of the time. We worked in a bank, and there were sometimes changes to legal phrases or terms and conditions that needed to be changed today (or more usually yesterday).
We did two things to help us deploy quickly. We had a good change control and build process. We could change and deploy any version we liked. We also had a good test suite, with which we could test changes easily.
The second was more controversial. All of our html was deployed as separate files on the server. There was no WAR. Therefore, when the circumstances came up that we needed to change something textual quickly, we could do it. If java needed changing, we always did a FULL build and deploy.
This is not something I'd recommend, but it was good for our situation.
The point of a WAR is so that everything gets deployed at the same time. If you're using a WAR, that means you want it to be deployed all at once.
One suggestion is not to do such corrections so often (once a week?). Then you don't have so much pain.
Hard to say. You can ofcourse replace single class files in an exploded webapp, but this is generally a bad idea and you don't see many people doing this.
The reason is that when you make small changes it becomes harder and harder to detect differences between production and development. The chances of you sending a wrong classfile and breaking the production server increases over time.
When you say text changes, isn't it an idea to keep the text resources seperate from the war file? That way, not only developers but maybe even the customer can easily add/change translations.
To the customer it's important, but technically it's silly to do a 80MB deploy over a slow line to fix a small typo.
You can also try to look at your build/delivery cycle and increase testing efforts to prevent these small changes.
Hope this helps.
You can have the master war deployed somewhere the running servers can access it, and instead of deploying war files to the individual servers you can use rsync and perl to determine if there are changes to any files in the master war, distribute them to the servers and execute restarts.
diff and patch:
http://stephenjungels.com/jungels.net/articles/diff-patch-ten-minutes.html
At the moment I installed SVN on the remote server so in case of a simple udate you can just update single file. Transfering the big WAR file would be quite impractical.
You can automate to a single click deployment using putty / plink [if you are using windows] by creating a simple script on the local machine an another one in the remote machine.
At the moment I have a DEVELOPMENT SVN and a LIVE SVN. The ANT build is merging the DEV to LIVE and the commit again back to the LIVE repository. At that stage the remote server can do a SVN UP and you will get automatically the file requested.
You can furter improve the update script to restart the server in case some classes are changed and do not restart in case of updating scripts/JSP.
In this way you will have also the option to rollback to a previous version to be sure that you have a working web app all the times.
To improve the process of merging SVN this tool is quite useful. : http://www.orcaware.com/svn/wiki/Svnmerge.py
The usual answer is to use a Continuous Integration sstem which watches your subversion and build the artifacts and deploy them - you just want your web application to be abel to work even after being redeployed. Question is if that is fast enough for you?
I don't think there's a straightforward answer to this one. T
The key here is modularisation - a problem which I don't think is solved very well with Java applications at present. You may want to look at OSGi or dynamic modules lathough I'm not sure how effective they are in terms of this problem.
I've seen solutions where people drop classes into application server/servlet container, I don't agree with it, but it does appear to work... I'm sure there are horror stories though!
Maven certainly makes things easier by splitting applications into modules, but if you do this and deploy modules independently you need to make sure that the various versions play nice together in a test environment to begin with...
An alternative is to partition your application in terms of functionality and host separate functions on various servers, e.g:
Customer Accounts - Server A
Search - Server B
Online Booking - Server C
Payment Services - Server D
The partitioning makes it easier to deploy applications, but again you have to make sure that your modules play nicely together first. Hope that helps.
I have had a similar situation before. It really is a separation of concerns issue, and it's not too straight forward. What you need to do is separate the text from the template/HTML page.
We solved this by placing our text in a database table, and using the table as a message resource - the same way people use myMessages.properties for internationalization (i8n). This gives you two advantages, you can i8n the text, and make changes in prod instantly and easily without a code deployment. We also cached the table to ensure performance didn't suffer much at all.
Not a solution for all, but it did work really well for us.

Categories