How do I incrementally patch a war file - java

I am having war file deployment at customer site. War file contains lib folder which contains dependent jars e.g.
/lib/app-01.jar
/lib/spring-2.5.1.jar
/lib/somefile-1.2.jar
...
...
If we need to update lets say app-01.jar to app-02.jar, is there any elegant solution? how does these dependent jars are packaged into WAR file as industry standard?
Is it good idea to package those dependent jars without version number?
e.g.
/lib/app.jar
/lib/spring.jar
/lib/somefile.jar
...
...
EDIT NOTE:
Actually, War is deployed to Webshpere, WebLogic, Tomcat on Windows or Linux platform. And Customer's IT department is involved for deployment

Probably the most elegant solution is just to generate a new war, and deploy it.
Here are the reasons:
If you are worried about uptime, some application servers supports side by side deployment. It means that you can deploy a new version and have it up at the same time of the old one. And stop the old when no one is using it. (I've used that on WebLogic, like 5yrs ago, so I suppose that is a common feature now). But that kind of feature only works if you deploy a new .WAR version.
Probably the WAR was generated using Maven, Ant or Gradle, so changing the dependency version and do a mvn package is usually faster and less error prone than unzipping the WAR, change it, and zip it again.
All the application servers provides a "hot replace" feature, that works by refreshing the class loader. Its fine for development, but in production it can be problematic (class loader leaks can be common, and problems caused by incorrect initialization or bad programming practices can give you unexpected bugs like having two versions of a class)
About JAR file names: I recommend to keep the versions on the file name.
Most of the JARs contains version information inside META-INF/Manifest.mf. But if for some reason you have to know which versions are using your app... opening each JAR file to see the version in the manifest is a lot of work.
As a final advice. If you don't use any automatic build tool... adopt one (take a look to Gradle, which is nice). Updating a library version, usually consist on changing the version number on the build file and execute something like gradle deploy. Even if you are not the developer, but the one in charge of devops, having an automated build is going to help you with deployments and updates.

In Tomcat I don't think the war is relevant after the files have been uncompressed. You could just ignore the war and extract the new/changed files into the correct webapp's directory (The one with the same name as the war.)

Related

How are java dependencies deployed on server machine

Did a lot of research but could not find a proper answer. My question is simple - I am building an executable jar file which has few external dependencies like spring etc. Now I want to deploy my executable jar file to server machine. Is there a easy and safe way of achieving it? Few options I am aware of:
Build an uber jar with all the dependencies bundled along with application code and deploy it
Deploy the source code executable jar and then manually add all the dependency jar files to the class path
Is there any other better way? Any tools which can help here? How are dependency jar upgrades handled? - Are they manually replaced on server machine?
If you 'just' have an executable jar and some other jar files as dependencies (this is the most common case actually), you can follow best practice standards and create a zip file containing them all. Check how various open source projects offer their stuff for download.
If you use some framework that might also guide you about deployment. As an example, the servlet specification tells you how to create that zip file in chapter 10.
If you want another way more compliant to the OS package manager, you could take a look at JPackage. It also bundles a Java Runtime so you have tight control not just about the jar dependencies but also the runtime.

java maven how to create app with bundled tomcat

I wonder if this is a somewhat awkward way of thinking, but I couldn't really find any hint on the internet to my idea. Maybe I just did not phrase my question right, but anyhow, this is what I would like to do:
I have a complex application written in java with spring and quartz and a whole load of dependencies. The application is run inside an apache tomcat servlet container. Now I know, I can create a war file and deploy that to the productive server machine (after our internal IT has installed and configured the tomcat on that machine), but I would like to do this a bit different.
I would like maven to create a pre-packaged tomcat application server with all dependencies and configuration settings AND my application. In effect, all that would need to be done on the productive system is, copy the package (or zip or tar.gz or whatever is needed) to the server, unpack it in a directory of my or their choice and fire up this local isolated tomcat. It would only run my application (which poses enough load on the machine anyway) and I could even go so far and deploy a second variant, say for a different customer in the directory next to the first one. Neither of both could interfere with each other, even if they use different versions with different dependencies.
Is it possible to do that? Is it a desirable approach or am I on the completely wrong track here?
What I think would be a benefit of this approach (despite the thing with incompatible dependencies or settings between two or more different installations) is, that I can hand the whole package over to our administration guys and they can simply deploy it to a server without the need to configure anything in the tomcat after installing it and so on.
Any hint???
Create a Maven project as the parent project (type pom). Include your webapp as a module project (type war). Create another module project, maybe "myapp-standalone" (type jar) and include the Embeddable Tomcat as a dependency. Write a starter class to launch the internal Tomcat (see executable jar / überjar). When building the app, copy the created war file into the jar, into Tomcats webapp directoy.
Your launcher class needs to make sure, that the ports of the current Tomcat are not yet in use.

Maven - deploying large war files

This question is somewhat similar to this one Best way to deploy large *.war to tomcat so it's a good read first, but keep on reading my q, it's different at the end...
Using maven 2 my war files are awfully large (60M). I deploy them to a set of tomcat servers and just copying the files takes too long (it's about 1m per war).
On top of that I added an RPM layer that'll package the war in an RPM file (using maven's rpm plugin). When the RPM is executed on the target machine it'll cleanup, "install" the war (just copy it), stop and start the tomcat (that's how we do things here, no hot deploys) and set up a proper context file in place. This all works fine.
The problem, however, is that the RPM files are too large and slow to copy. What take almost eh entire space is naturally the war file.
I haven't seen any off-the-shelf solution so I'm thinking of implementing one myself so I'll describe it below and this description will hopefully help explain the problem domain. I'll be happy to hear your thought on the planned solution, and better yet point me at other existing solutions and random tips.
The war files contain:
Application jars
3rd party jars
resources (property files and other resources)
WEB-INF files such as JSPs, web.xml, struts.xml etc
Most of the space is taken by #2, the 3rd party jars.
The 3rd party jars are also installed on an internal nexus server we have in the company so I can take advantage of that.
You probably guessed that by now, so the plan is to create thin wars that'll include only the application jars (the ones authored by my company), resources and WEB-INF stuff and add smartness to the RPM install script that'll copy the 3rd party jars when needed.
RPM allows you to run arbitrary scripts before or after installation so the plan is to use mvn write a list of 3rd party dependencies when building the war and add it as a resource to the RPM and then when installing an RPM the RPM installation script will run over the list of required 3rd party jars and download the new jars from nexus only if they don't exist yet.
The RPM will have to delete jars if they are not used.
The RPM will also have to either rebuild the war for tomcat to explode it or add the 3rd party jars to common/lib or something like that although we have a few web-apps per tomcat so it'll make things complicated in that sense. Maybe explode the jar by itself and then copy the 3rd party jars to WEB-INF/lib
Your input is appreciated :)
We have a directory on the target machines with all third party jars we're using (about 110Mb). The jars are using a naming coding convention that includes their version number (asm-3.2.jar, asm-2.2.3.jar ...). When adding a new version of a third party we don't delete the older version.
When deploying, our jar files contains only business logic classes and resources we compile in the build (no third party). The classpath is defined in the jar manifest where we cherry pick which third party it should be using at runtime. We're doing that with ant, no maven involved and we have more then 25 types of services in our system (very "soa" though I dislike this over buzzed word). That business logic jar is the only jar in the jvm classpath when starting the process and it is also versioned by our code repo revision number. If you go back to older revision (rollback) of our code that might be using an older third party jar its still going to work as we don't remove old jars. New third party jars should be propagated to production machines before the business code that uses them does. But once they're there they're not going to be re-pushed on each deployment.
Overall we lean towards simplicity (i.e. not OSGi) and we don't use Maven.
I would advise against your proposed plan. It sounds like a lot of moving pieces that are likely hard to test and/or diagnose problem when they arise.
We don't have the problem of "large" WARs but we do have the problem that most of our WARs all need the exact same 3-rd party libraries on their classpath. The solution we went forth with (that has worked very well) was to utilize OSGi to build our application modularly. We use Felix as our OSGi container which runs inside of Tomcat. We then deploy all of our dependencies/libraries to Felix once. Then we deploy "thin" WARs which just reference OSGi dependencies by Importing the packages it needs from the bundles it cares about.
This has a few other advantages:
Deploying new versions of OSGi bundles while the old ones are running is not an issue which allows for no downtime (similar to hot deploy).
If you need to upgrade one of your dependencies (e.g. Spring 2.5 -> 3.0), you only need to upgrade the Spring bundle running in OSGi; no need to deliver (or package) new WARs if the APIs did not change. This can all (once again) be done on a live running OSGi container, no need to turn anything off.
OSGI guarantees your bundles do not share classpaths. This helps keep your code cleaner because each WAR only needs knowledge of what it cares about.
Setting up your WARs to be "OSGi ready" is not trivial but it is well documented. Try checking out How to get started with OSGi or just Google for 3rd party tutorials. Trust me, the initial investment will save you much time and many headaches in the future.
It is probably best not to re-invent the modularity wheel if possible.

packages deployment best definition

How we can define the term "deploy a package"?
Is correct to say that to deploy a package means to make a procedure
in which we create, put into a file system location and make them visible
to the compiler an VM with options like -classpath CLASSPATH etc????
How we can define the term "deploy a package"?
It depends on that kind of package you are talking about and what kind of deployment you are talking about.
For example, you probably wouldn't talk about deploying a Java package, because a Java package is not normally a sensible "unit of deployment". (Normally you would deploy a Java application or webapp, or possibly a Java library. And in the context of Maven, you would deploy an "artifact".)
If you are not talking about a Java package, what kind of package are you talking about?
Is correct to say that to deploy a package means to make a procedure in which we create, put into a file system location and make them visible to the compiler an VM with options like -classpath CLASSPATH etc????
That doesn't sound like a conventional definition of deployment to me. For a start, there is no standard file system location to deploy (for example) JAR files to.
I have become accustomed to the way maven uses the word deploy.
The deploy plugin is primarily used during the deploy phase, to add your artifact(s) to a remote repository for sharing with other developers and projects. This is usually done in an integration or release environment. It can also be used to deploy a particular artifact (e.g. a third party jar like Sun's non redistributable reference implementations).
I am not saying that your definition is incorrect, it just doesn't rhyme with my interpretation.
I would separate "build" from "deploy". Building would take source code and construct a deployable artefact. In this case we have some .java files, we compile them to .class files and (usually) put them in a JAR. The JAR is the thing that we deploy. In Java EE we might go a step further and put several JARs (and WARs ...) into an EAR and deploy that.
So deploying is making the deployable artefact executable in a runtime environment, in this case making the JAR visible to a chosen JVM. Quite possbly you might have many runtime environments, many customers, many machines. You build once, deploy many times.
In practice we often find that there's a little bit more to doing the deployment than just getting the JAR onto a Classpath. You often find you need to:
Remove previous versions of the JAR, possibly keeping then ready for to be reinstated if something bad happens.
Make other resources available, eg. databases
Do some environment specific configuration
Validate the deployment by running some kind of tests
Restart dependent components
Keep an audit trail ofthe deployment
In non-trivial cases it's often very useful to automate steps such as these using scripts.

How to use common libraries for multiple Java web project

I am having four different project, and i am using Weblogic to deploy my projects. There are several libraries ( jar files ) which are common for all projects. Currently each of my project are having lib directory and have almost same set of libraries. Now, is it possible to have this lib directory outside WAR files and access them.
Resist the temptation of putting the jar files in the "shared" folder of your container. It is better to keep the jar files where they are now. It may sound a good idea to use a shared folder now, but in the future you may need to deploy an application that requires a shared library, but a different version.
That being said, I have no experience with WebLogic. In Tomcat there is a shared folder with libraries common for all deployed applications. It is not a good idea to use this. If WebLogic can be configured to use a shared folder per a set of applications (and not for all deployed applications) you could go for it.
Do you want to do this ? Unless you're stuck for deployment space, I would (perhaps) advise against it.
Why ? At the moment you have 4 solutions running off these libs. If you have to upgrade one of the libs (say, if you discover a bug, or if you require a new feature), then you're going to have to test compatibility and functionality for all 4 solutions. If each solution has its own set of libs, then they're sandboxed and you don't have to move all 4 in step.
Note that all this hinges on how easy it is to regression-test your solutions. You may find it easy, in which case using the same set of libs is feasible.
Don't do that.
The whole idea of WAR files is that they are self-contained units. This makes deployment so much easier.
In addition to the possible version conflicts that others have pointed out, putting jar files in /shared can have very nested consequences for class visibility. They will be on a separate classloader, and be unable to see the classes in the WAR file. If you use libraries that rely on Class.forName() to work (and there are plenty), this could get very painful.
If you really, really cannot afford the extra disk space and memory look at OSGi or Spring DM. They have solved this problem, but at the price of increased complexity.
Put all the shared jar files under common\lib folder of weblogic. common\lib is accessible by all the deployed apps.
Well first of all you can put your libs all on the same place and have your build process import the ones needed.
Has for on deploy the new Weblogic 10 has a lib folder in each domain where you can put shared libs. i dont think that is possible before Weblogic 10
You can put the jars in their own ear file and deploy it as a shared library.
You can also put the wars in an ear and add the shared jars to APP-INF/lib. This is a Weblogic extension of J2EE, so it won't work on other servers.
I'm currently using another approach.
Create a central repository folder and put all common libraries in there.
In each project you can create a reference to all needed libraries. In Subversion it works with externals
Everytime, the local working copy is updated, the externals are updated to, so you just need to commit to the central folder and it's automatically distributed to all projects.

Categories