Java files in a jar file - java

Is there a technical reason for not having the source java files in the jar file? I came across a service jar that had both the class jars and the source java files in the same jar. Typical third-party libraries will bundle these different types of files into separate jars. The binary is necessary for execution and the src.jar file is useful to debug using the exact code that the class files were built with.
To me the reasoning is: it slows down server startup because the additional files need to be decompressed and perhaps indexed. Are there any other reasons I can use to advocate for abandoning this one-off build process?
Please do not respond that jar files are essentially zip files and anything goes, I am looking for technical reasons during runtime to avoid this situation. BTW the services using these JARs have been working for a long time, so it is not manifesting any actual perceived defects.

It shouldn't cause any problems to have source files in the JAR with the binary class files. The main reason to keep them separate is to avoid making JARs bigger than necessary for runtime deployment. As far as I know, the convention of distributing a -sources JAR file for open source libraries originated with Maven, which will produce artifacts in this way by default.

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.

How do I incrementally patch a war file

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.)

What is a good deployment directory structure for java console apps

I have a Java console application that I am ready to deploy onto a Unix server. I am writing a shell script to run the application.
I plan to put my shell scripts in one folder, my application jar and dependent jars (spring, etc.) into a different folder and properties files (those that need to be maintained 'live') in a separate folder again. I would then have my shell script iterate through the files in the 'jars' and 'properties' folders, appending them to the classpath, before finally calling java ...
Is this a 'good' deployment structure? Are there any guidelines for how to arrange files to maximise maintainability and stability? Are there obvious 'wrong' ways to do this that are best avoided?
I should add that, for a previous project, I put all shell scripts (those that start java processes and those that don't) into a scripts folder, my application jar into a folder with the library jars in a library subfolder and external resources into a config subfolder. I then wrote a script that explicitly loads all the files. It was long winded to write and needs to be maintained whenever I upgrade a library jar. This time around I'd like to do it better. Also, it feels unnecessary to separate my application JAR from the libraries.
For what it's worth, this is what we use;
/
/class
//package hierarchy here, raw .class files
/lib
//library jars here, apache commons, gson etc, all .jars
/conf
//.properties files go here, including ones for libraries
/doc
//program documentation files, typically .txt
/javadocs
//java doc html root
/sh
//shell scripts including execute.sh and compile.sh
We use ant for building, often have a src folder for the source tree if necessary. This way you just add /class and /lib to your classpath, and that never changes.
Good structure for your case is so called uberJar or oneJar, that can be made with number of utils, just google it. Also I can recommend such a nice piece of code as http://www.jdotsoft.com/JarClassLoader.php
Frankly, if it is just a small app, I would put it all under /opt/<my_java_app> and have a directory substructure there just like you did in dev.
If you want to be more compliant with the UNIX recommended practices, then put your executable (including your jar) in /usr/local/bin/<my_java_app>, config files in /etc/<my_java_app>, log files and other data files in /var/<my_java_app>.
Also, you may want to refer to this document.
Build a system-native package, and use system defaults. If using Debian, create a .deb direct from your build system (for instance, using ant deb task). If using rpms, use the rpm task. That way you can easily deploy, undeploy and update the application just like any other one.
The system package should separate libraries (I use /usr/share/java/AppName for my jars) and configuration (to /etc/AppName or /home/UserName/.AppName); the launch-scripts I symlink to /usr/bin. Beyond that, there is no great complication getting things to work. I recommend finding well-known java-based packages in your distribution and copying their launch scripts (in particular, their VM-locating magic).

Single jar vs Multiple jars - performance benefits

I have an application which is deployed into Jetty but is not packaged into single war file. Contrary, it is stored as a folder. There are quite a lot of dependencies in war/WEB-INF/lib folder which I am thinking of merging into one jar.
Are there any performance benefits that I would get by doing so?
It does not matter. I do not know about jetty but all other servers I know extract archives anyway, i.e. store war/ear files in temporary directory in extracted form.
#markovuksanovic: performance should not really matter or very insignificant.
Jar file is meant for archiving set of meaningful collection of classes and resources...that is all...

Obfuscating Jar files with other Jar files embedded

So figure we have a Jar file with our Java application, and it has inside of it the Jar files for the libraries it depends of, a the jdbc or any other third party jar.
How do you proceed to obfuscate it with free software? I mean, obfuscate your code and leave the Jars untouched.
I tried with Proguard, to no avail. Even the author told me at the sourceforge forums it wasn't possible.
But you can do it manually with an ugly hack involving the renaming of the jar to zip and mangling with the inner data, so, why wouldn't a software be able to do it?
You can create a single jar from multiple jars using Jar Jar Links.
Then you process the result with ProGuard.
Presumably, you have some sort of build script in place to compile your source, package it with the other jars (One-Jar/Fat Jar/etc.), and build your jar.
You should be able to insert the obfuscation task between the compilation and packaging.
If your obfuscation tool of choice will only take a jar input, you should be able to compile, jar, and obfuscate your code independently. After that, have your script unjar the obfuscated file and do your packaging.
Don't waste your time. Anyone can decompile your obfuscated code, the only thing you're going to do is frustrate your legitimate users who want to debug problems with your software.
Obfuscation is a technical solution (and a poor one at that) to a legal problem.

Categories