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.
Related
What is the difference between Jar and Plugin in Java? Both looks the same by achieving the same purpose and when do use Jar and when do we use Plugin.
A plugin is an extension to Maven, something used to produce your artifact. Plugins are used only to make maven process successful. They are not directly connected to your application. plugins do not include in your last war/jar file for the service or client.
A dependency is a library that is needed by the application you are building, at compile and/or test and/or runtime time. the classes you used from jars will include in your final war/jar.
This will be helpful for you,
What is the difference in maven between dependency and plugin tags in pom xml?
Difference between plugin and external jar file
plug-in is a software component that adds a specific feature to any computer program.It specially use to customize any computer program.But .jar file is a java executable file which can only run on an environment which Java installed.
Today at work I came across something interesting. Say i have an old java project that were compiled with an ant build file and we have converted this project into a maven project. So now to build this project, we only need to do a mvn install.
When i do call
mvn install
I get a myproject.jar under the target folder, along with all the dependencies under a lib folder inside the target folder.
To run the executable of this jar I need to do something like :
java -classpath $classpath com.myproject.Mainclass $myArgs
Where $classpath is the path to all of my external libs and where $myArgs is the arguments that is passed to the main function.
I came across this website and I'm really considering to use the spring boot maven plugin to package my executable jar.
Wouldn't it be easier to execute it if all the dependencies are packaged in a single jar file ?
Why would I use the manual configuration vs the Spring Boot Maven Plugin for the executable jar ?
What are the pro and the cons of doing this ?
As the article you had linked covers with pros and cons how to do such single jar file packaging, I'll write out things that you need to consider if you want to use this approach.
Pros:
1. Simplicity of deployment
Users don't have to maintain any dependencies. All they need to do to run the app is get the jar file and execute java -jar file.jar.
2. No easy way to update dependencies by user
If your app uses some external dependencies, you can be sure they are in version that you have chosen. Using "classic" approach user can easily update it by himself to the version that may require some migration steps in your app.
Cons:
1. Size of final package
If your app has large dependencies, every update will require users to download the whole package,
even if dependencies haven't changed.
2. No easy way to update dependencies by user
To change a version of any dependency you will need to update the whole package, where using the old way you could update only the dependency jar.
Summarizing, if your app doesn't have any heavy (in sense of file size) dependencies, I'll personally use single jar file approach. Even if your dependencies changes frequently. It's a lot easier to change a single file, no matter if your app has to be updated or some of its dependency.
what is the difference between simple project/lib and project/web/WEB-INF/lib?
which jar should be in project/lib folder and which jars should be in web/WEB-INF/lib?
there is no standard project/lib thing, it might be a specific project designed that way to hold library there and while compiling and deploying it might be configured to read jars from there,
where as if you put it in WEB-INF/lib web contains puts all the jars from this directory in runtime classpath so they would be available when application is running
better to use maven without needing to holding library in source control and with lots of other advantages maven brings
I am beginning to use java packages like HTMLParser, I have downloaded it and finding that there are many files and directories in it.
I wander, where to place them in my linux system? Is there a convention or a standard?
The quick and dirty answer is "anywhere on the classpath", where the classpath is set either as a system property on the client machine (not recommended), as a temporary system property for the CLI session used to start the JVM (workable from a startup script), or as a commandline parameter to the JVM (usually the preferred choice).
First and second set the CLASSPATH environment variable, see the JDK or JRE documentation for the exact syntax and your operating system's and/or shell scripting documentation as well. Third uses the -cp commandline variable to the Java runtime and compiler, see their documentation for exact syntax.
Where to place the files on the filesystem? For development purposes I typically use a central folder on my computer containing all such libraries and link to that from my IDE or other development environment. For deployment/packaging to end users, it is traditional to have a "lib" subfolder to the product folder that contains all distributable content, and put the jar files in that.
Java packages come in two forms. Source code - all the files and directories you mention - and packaged as jars. A common convention in Java projects is that the project has a lib directory that contains all the jars that the project depends on. These projects often use a shell script which adds all the jars to the Java classpath prior to executing the project code.
However many projects are switching from this method of dealing with dependencies to using a build tool like Apache Maven which automatically handles dependency management. Other alternatives include Ivy or Gradle. For an introduction see the 5 minute introduction to Maven or the Maven 3 tutorial.
Here you write a pom.xml (project object model file) which specifies which libraries (jars) your project uses. Maven then stores all the jars for your different projects in a .m2 directory in your local directory, keeping track of where it obtained them, and their versioning information.
This makes developing much easier as you do not need to create the lib directory or manually manage dependencies. You also avoid a lot of the complexities of setting the classpath, as Maven automatically does this for you during common lifecyle stages such as compilation and test. Recent versions of Eclipse can read the Maven pom and automatically configure your classpath from it.
Once you have built the project, Maven can also help create "fat jars" that contain all the jars your project depends on, via the assembly plugin or the Shade plugin. This makes distributing the code easier when you are building an executable that you want someone to use. If you are distributing a jar, then your pom.xml describes the dependencies of your project, avoiding the need to distribute the jars it depends on.
For laying out files in general on a Linux system consult the Linux Filesystem hierarchy standard.
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.)