Suppose you have several applications which share the same code and most of the other resources, but have a somewhat different look and feel, some labels change, etc. (think branding). If each web app is to go in its own WAR file, where do you put the shared resources?
I already use the classpath to share classes and property files. But what about javascript and css files? Is the best way to create and deploy one extra WAR file that will serve these shared files to whatever other application requires them?
I also thought of a build script that does some magic and from a common source spews out the (slightly) different WARs, but I don't like it because it just complicates stuff unnecessarily when you need to build/test/run a single application.
Any other tips and tricks would be appreciated.
You can deploy both WARs in the same EAR and put common resources in the EAR. Then put the appropriate dependencies in the manifest of the web apps to link to the jar files in the ear.
A strategy that I have seen used for such product-line like configurations is using WAR overlays when building with maven. You define a common WAR that contains the common stuff and overlay it with those other WARs that contain the specific stuff to generate different WARs for every application. This method is probably most useful if you deploy the WAR-variants on different machines. But I'm not sure whether I can actually recommend this.
Remember to specify the overlays configuration if you actually override stuff, since otherwise the overriding order is not deterministic. It might even change with a maven-war-plugin upgrade. (It did in our case.)
If you don't want to go the EAR route, using tomcat, etc; there are a few other ways to achieve the consistency you want.
If you want to share just js and css, look into pack:tag. You could host the .js and css from an apache server, set up your httpd.conf so your webapps can call it, then use pack:tag from your application wars - DRY and compression in one step.
Thanks for the replies so far, but I'm afraid I forgot to mention that the WARs will be deployed in different environments that are completely isolated from each other.
So maybe having a common WAR deployed next to the actual application is the only option. I think I'll go with the following:
WAR1, WAR2 containing app-specific stuff
CommonWAR containg common stuff (no kidding)
EAR1: WAR1 + CommonWAR, to be deployed in env1
EAR2: WAR2 + CommonWAR, to be deployed in env2
Update
Yes, me again. I have actually changed my mind (again :) ). I am currently trying (being more prudent here):
(Common)WAR: containing the application, common (most part) + some specific stuff
EAR1: CommonWAR + specific configuration file for env1
EAR2: CommonWAR + specific configuration file for env2
The configuration file is picked up by the WAR. It is on the the EAR classpath and only contains one property 'application' with a value. The single WAR will then use this information where appropriate to distinguish between the two apps (config, style sheets, ...).
With my solution of EAR1 = CommonWAR + WAR1, EAR2 = CommonWAR + WAR2, it was too difficult or impossible to lookup static resources in the CommonWAR without using a web url (e.g. images in PDF documents generated with iText).
How about putting your css and js in the classpath and serve them with a servlet? Then you can build the common resources as a jar and that jar can even contain the servlet (resource dispatcher if you like) and the war files can contain the jar file in the WEB-INF/lib folder.
Related
I have a project that will be separate as:
a) Business Layer ( containing all the core Java classes and some configurations (services, etc) ) and
b) Presentation Layer (containing all the web structure based on Spring webflow and also all the configuration files on it. So in the process of development we have several properties files spread in the java/main/src under a resource.properties.* package and we have other properties in the web structure under WEB-INF/conf and WEB-INF/i18n (which are label messages for the screen)..so my questions are the following:
It's correct to leave the properties files inside of
java/main/src under packages that later will be under classes
folder in the webapp?.
Which is the best approach to leave all the
properties files in one place let say WEB-INF/configurations ? or
leave some properties files of business layer in one place and some
properties files from presentation layer in another place?
Which is the best approach to have this properties in a best way to
install the webapp?, deliver the properties in a JAR file and
include it in the WAR or EAR? that allows us to modify on the fly
and include in the war without deploy the entire application... or which is the best or used approach to accomplish that?
I've found in helpful to separate properties into two categories:
Properties for conveniently changing application look and behavior
Properties for environment-specific settings (for example DEV vs. PRODUCTION)
Category #1 can be embedded in your WAR files wherever makes sense. In WEB-INF/classes is a popular place, but putting them in META-INF in jar files can also work well. It is worth choosing a standard you like and sticking with it. The bottom line is that these files are changed during development; they are not changed after deployment and remain the same at the system is released.
Category #2 should always be separate from the deployable. Ideally, environment-specific properties should be deployed only when they change. It is really a configuration-management (CM) decision where they live. Developers need to supply the basic versions of these configuration files and CM should edit them when they are deployed to specific environments (QA, PRE-PROD, PROD). In situations where delegation of duties is mandated (e.g. where SOX applies), the production version of the properties files should never be touched or seen by developers. I've seen a lot of cases where the different versions (DEV/QA/PROD) of these files are maintained by developers and kept in source control That's not appropriate.
I think its good to have a separate source folder 'resources' and keep all the properties file there. These also make sure that the property files don't get mixed up the source code.
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 have a war deployed on a Websphere box. It uses a file to build up a trie structure inside a web service. Instead of having to redeploy an updated ear with the file as a resource, we want to be able to put the file on Websphere and update it as necessary, then just cycle the servers (we have multiple nodes) to avoid downtime. Where would be the best place to store such a file so that it would be picked up in the classpath?
I'm pretty new to using Websphere, so if I'm not making sense, please let me know.
There is a shared library concept in WebSphere. You can add your data file to a jar and that jar will be deployed as a shared library. the library can then be specified as a dependency to your WAR module during deployment.
http://publib.boulder.ibm.com/infocenter/wasinfo/v5r1//index.jsp?topic=/com.ibm.websphere.base.doc/info/aes/ae/tcws_sharedlib.html
http://www.albeesonline.com/blog/2008/04/07/creating-a-shared-library-in-websphere/
But this is not Java EE compliant and specific to WAS only.
In my opinion, the best way to use a URL Provider as described in this article:
http://www.ibm.com/developerworks/websphere/library/techarticles/0502_botzum/0502_botzum.html
I have two jar files from a client, one of which is used for a testing and another for final versions. Currently I put them in different folders and modify the library path when deploying our code, but it would be nice to be able to load both jar files and switch between them dynamically at runtime.
Is this possible?
You can always write your own ClassLoader and chain it with the standard ClassLoader.
http://download.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html
I used this method 10 years ago to load classes that were recieved via sockets and specified in an XML file (via sockets as well). My java program didn't know that the classes even existed before it got the XML file and the classes.
Using OSGi bundles you can do that. Take a look at http://blog.springsource.com/2008/02/18/creating-osgi-bundles/. Search for "multiple versions".
justinjh,
chrisparker2000's suggestion looks to be the most feasible - You have to write a custom classloader, the only change that I can think of is something along the following lines:
1. For the client deliverable jars - say client.dev.jar and client.prod.jar, rename to a different extension and place these in the classpath. Rename to a different extension to prevent the container from loading the contents of the jar.
Using the custom classloader, load the contents on demand, based on the solution offered by chrisparker2000, by placing a small facade on top of the client classes, say ClientClassFactory which based on the environment(dev/prod/anything else) would use the custom classloader to load from either client.dev.otherext or client.prod.otherext .
If you use a build-tool like maven, you can define different jar files (dependencies) for different scopes (test vs production).
You may also use maven profiles to define different set of jar files/versions.
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.