Is fat jar equal to runnable/executable jar? [duplicate] - java

I am reading Maven documentation and came across the name uber-jar.
What does an uber-jar mean and what are its features/advantages?

Über is the German word for above or over (it's actually cognate with the English over).
Hence, in this context, an uber-jar is an "over-jar", one level up from a simple JAR (a), defined as one that contains both your package and all its dependencies in one single JAR file. The name can be thought to come from the same stable as ultrageek, superman, hyperspace, and metadata, which all have similar meanings of "beyond the normal".
The advantage is that you can distribute your uber-jar and not care at all whether or not dependencies are installed at the destination, as your uber-jar actually has no dependencies.
All the dependencies of your own stuff within the uber-jar are also within that uber-jar. As are all dependencies of those dependencies. And so on.
(a) I probably shouldn't have to explain what a JAR is to a Java developer but I'll include it for completeness. It's a Java archive, basically a single file that typically contains a number of Java class files along with associated metadata and resources.

ubar jar is also known as fat jar i.e. jar with dependencies.
There are three common methods for constructing an uber jar:
Unshaded: Unpack all JAR files, then repack them into a single JAR.
Works with Java's default class loader. Tools maven-assembly-plugin
Shaded: Same as unshaded, but rename (i.e., "shade") all packages of all dependencies. Works with Java's default class loader. Avoids some (not all) dependency version clashes. Tools maven-shade-plugin
JAR of JARs: The final JAR file contains the other JAR files embedded within. Avoids dependency version clashes. All resource files are preserved. Tools: Eclipse JAR File Exporter
for more

Paxdiablo's definition is really good.
In addition, please consider delivering an uber-jar is sometimes quite useful, if you really want to distribute a software and don't want customer to download dependencies by themselves. As a draw back, if their own policy don't allow usage of some library, or if they have to bind some extra-components (slf4j, system compliant libs, arch specialiez libs, ...) this will probably increase difficulties for them.
You can perform that :
basically with maven-assembly-plugin
a bit more further with maven-shade-plugin
A cleaner solution is to provide their library separately; maven-shade-plugin has preconfigured descriptor for that. This is not more complicated to do (with maven and its plugin).
Finally, a really good solution is to use an OSGI Bundle. There is plenty of good tutorials on that :)
For further configuration, please read those topics :
Should you provide dependent libraries in client jar?
Best practices in building and deploying Clojure applications: good tutorials?

The different names are just ways of packaging java apps.
Skinny – Contains ONLY the bits you literally type into your code editor, and NOTHING else.
Thin – Contains all of the above PLUS the app’s direct dependencies of your app (db drivers, utility libraries, etc).
Hollow – The inverse of Thin – Contains only the bits needed to run your app but does NOT contain the app itself. Basically a pre-packaged “app server” to which you can later deploy your app, in the same style as traditional Java EE app servers, but with important differences.
Fat/Uber – Contains the bit you literally write yourself PLUS the direct dependencies of your app PLUS the bits needed to run your app “on its own”.
Source: Article from Dzone
Reposted from: https://stackoverflow.com/a/57592130/9470346

A self-contained, executable Java archive. In the case of WildFly Swarm uberjars, it is a single .jar file containing your application, the portions of WildFly required to support it, an internal Maven repository of dependencies, plus a shim to bootstrap it all. see this

According to uber-JAR Documentation Approaches:
There are three common methods for constructing an uber-JAR:
Unshaded Unpack all JAR files, then repack them into a single JAR.
Tools: Maven Assembly Plugin, Classworlds Uberjar
Shaded Same as unshaded, but rename (i.e., "shade") all packages of all dependencies.
Tools: Maven Shade Plugin
JAR of JARs The final JAR file contains the other JAR files embedded within.
Tools: Eclipse JAR File Exporter, One-JAR.

For Java Developers who use SpringBoot, ÜBER/FAT JAR is normally the final result of the package phase of maven (or build task if you use gradle).
Inside the Fat JAR one can find a META-INF directory inside which the MANIFEST.MF file lives with all the info regarding the Main class. More importantly, at the same level of META-INF directory you find the BOOT-INF directory inside which the directory lib lives and contains all the .jar files that are the dependencies of your application.

Related

How to run jar after maven package [duplicate]

I am reading Maven documentation and came across the name uber-jar.
What does an uber-jar mean and what are its features/advantages?
Über is the German word for above or over (it's actually cognate with the English over).
Hence, in this context, an uber-jar is an "over-jar", one level up from a simple JAR (a), defined as one that contains both your package and all its dependencies in one single JAR file. The name can be thought to come from the same stable as ultrageek, superman, hyperspace, and metadata, which all have similar meanings of "beyond the normal".
The advantage is that you can distribute your uber-jar and not care at all whether or not dependencies are installed at the destination, as your uber-jar actually has no dependencies.
All the dependencies of your own stuff within the uber-jar are also within that uber-jar. As are all dependencies of those dependencies. And so on.
(a) I probably shouldn't have to explain what a JAR is to a Java developer but I'll include it for completeness. It's a Java archive, basically a single file that typically contains a number of Java class files along with associated metadata and resources.
ubar jar is also known as fat jar i.e. jar with dependencies.
There are three common methods for constructing an uber jar:
Unshaded: Unpack all JAR files, then repack them into a single JAR.
Works with Java's default class loader. Tools maven-assembly-plugin
Shaded: Same as unshaded, but rename (i.e., "shade") all packages of all dependencies. Works with Java's default class loader. Avoids some (not all) dependency version clashes. Tools maven-shade-plugin
JAR of JARs: The final JAR file contains the other JAR files embedded within. Avoids dependency version clashes. All resource files are preserved. Tools: Eclipse JAR File Exporter
for more
Paxdiablo's definition is really good.
In addition, please consider delivering an uber-jar is sometimes quite useful, if you really want to distribute a software and don't want customer to download dependencies by themselves. As a draw back, if their own policy don't allow usage of some library, or if they have to bind some extra-components (slf4j, system compliant libs, arch specialiez libs, ...) this will probably increase difficulties for them.
You can perform that :
basically with maven-assembly-plugin
a bit more further with maven-shade-plugin
A cleaner solution is to provide their library separately; maven-shade-plugin has preconfigured descriptor for that. This is not more complicated to do (with maven and its plugin).
Finally, a really good solution is to use an OSGI Bundle. There is plenty of good tutorials on that :)
For further configuration, please read those topics :
Should you provide dependent libraries in client jar?
Best practices in building and deploying Clojure applications: good tutorials?
The different names are just ways of packaging java apps.
Skinny – Contains ONLY the bits you literally type into your code editor, and NOTHING else.
Thin – Contains all of the above PLUS the app’s direct dependencies of your app (db drivers, utility libraries, etc).
Hollow – The inverse of Thin – Contains only the bits needed to run your app but does NOT contain the app itself. Basically a pre-packaged “app server” to which you can later deploy your app, in the same style as traditional Java EE app servers, but with important differences.
Fat/Uber – Contains the bit you literally write yourself PLUS the direct dependencies of your app PLUS the bits needed to run your app “on its own”.
Source: Article from Dzone
Reposted from: https://stackoverflow.com/a/57592130/9470346
A self-contained, executable Java archive. In the case of WildFly Swarm uberjars, it is a single .jar file containing your application, the portions of WildFly required to support it, an internal Maven repository of dependencies, plus a shim to bootstrap it all. see this
According to uber-JAR Documentation Approaches:
There are three common methods for constructing an uber-JAR:
Unshaded Unpack all JAR files, then repack them into a single JAR.
Tools: Maven Assembly Plugin, Classworlds Uberjar
Shaded Same as unshaded, but rename (i.e., "shade") all packages of all dependencies.
Tools: Maven Shade Plugin
JAR of JARs The final JAR file contains the other JAR files embedded within.
Tools: Eclipse JAR File Exporter, One-JAR.
For Java Developers who use SpringBoot, ÜBER/FAT JAR is normally the final result of the package phase of maven (or build task if you use gradle).
Inside the Fat JAR one can find a META-INF directory inside which the MANIFEST.MF file lives with all the info regarding the Main class. More importantly, at the same level of META-INF directory you find the BOOT-INF directory inside which the directory lib lives and contains all the .jar files that are the dependencies of your application.

What are the differences between uberJar, fatJar and shadowJar in Gradle?

I'm trying to understand when should I use which. I understand that they all assemble all the dependent classes, but how are they different from each other?
The terms are sometimes used interchangeably, but usually refers to:
Fat jar (also named Uber jar) - used to describe a jar that has all classes from dependent jars zipped directly inside it in the correct directory structure, and not in other jars. There is a good explanation here.
Shaded jar (or shaded classes) - usually refers to a process of changing classes bytecode to change packages names of the classes, and also modify were it is used in the jar. It is used to link classes to a specific version of other classes and avoid versions collisions. It can be created by Maven Shade Plugin. Shaded jar do not necessary contain all the dependencies needed.
The gradle shadow plugin can generate both fat jars and shaded jars, and same for the maven shaded plugin. I guess that is why people mix those terms.
Note: I have seen cases that refers to fat jar as a jar contains dependencies as a packed jars inside it.
There is no difference whatsoever. These terms are all synonyms of each other.
The term "uber-jar" may be more commonly used in documentations (take the maven-shade-plugin documentation for example) but "fat-jar" is also widely used.
Uber Jar, Fat Jar and Shadow Jar are synonyms.
All three tasks do the same thing - you can choose the term you personally prefer the most.

Is it correct or incorrect for a Java JAR to contain its own dependencies?

I guess this is a two-part question. I am trying to write my own Ant task (MyFirstTask) that can be used in other project's build.xml buildfiles. To do this, I need to compile and package my Ant task inside its own JAR. Because this Ant task that I have written is fairly complicated, it has about 20 dependencies (other JAR files), such as using XStream for OX-mapping, Guice for DI, etc.
I am currently writing the package task in the build.xml file inside the MyFirstTask project (the buildfile that will package myfirsttask.jar, which is the reusable Ant task).
I am suddenly realizing that I don't fully understand the intention of a Java JAR. Is it that a JAR should not contain dependencies, and leave it to the runtime configuration (the app container, the runtime environment, etc.) to supply it with the dependencies it needs? I would assume if this is the case, an executable JAR is an exception to the rule, yes?
Or, is it the intention for Java JARs to also include their dependencies?
Either way, I don't want to be forcing my users to be copying-n-pasting 25+ JARs into their Ant libs; that's just cruel. I like the way WAR files are set up, where the classpath for dependencies is defined under the classes/ directory.
I guess, ultimately, I'd like my JAR structure to look like:
myfirsttask.jar/
com/ --> the root package of my compiled binaries
config/ --> config files, XML, XSD, etc.
classes/ --> all dependencies, guice-3.0.jar, xstream-1.4.3.jar, etc.
META-INF/
MANIFEST.MF
I assume that in order to accomplish this (and get the runtime classpath to also look into the classes/ directory), I'll need to modify the MANIFEST.MF somehow (I know there's a manifest attribute called ClassPath, I believe?). I'm just having a tough time putting everything together, and have a looming/lingering question about the very intent of JARs to begin with.
Can someone please confirm whether Oracle intends for JARs to contain their dependencies or not? And, either way, what I would have to do in the manifest (or anywhere else) to make sure that, at runtime, the classpath can find the dependencies stored under the classes/ directory? Thanks in advance!
The term 'JAR file' can mean at least two things, or rather, has at least two facets to its meaning. Most basically, it means a container format: basically, a ZIP file with a META-INF directory. More refinedly, it means this container used as a way to package class files.
In the sense of being a container, there is no intent with respect to contents; the file could contain class files, other JARs (in either sense!), etc. But in the sense of being a packaging of code, i believe the intent for JAR files proper is for them not to contain any dependencies.
If you have a read of the JAR File Specification, you'll find there are several allusions to the storage of class files, but nothing about storing other JAR files. Correspondingly, if you look at the implementation of the JAR file classloader in the JRE, it can't do anything useful with nested JARs.
Furthermore, the JAR specification does detail a mechanism for dealing with non-nested dependencies: the Class-Path attribute. This lets a JAR file make relative references to other JAR files in the filesystem.
Now, in-the-sense-of-a-packaging JAR files are not the only use of in-the-sense-of-a-container JAR files. WAR, EAR, and RAR files (and more besides) are all JAR files used for particular purposes. Each of those is capable of containing other JARs: WARs can contain in-the-sense-of-a-packaging JAR files, and EARs can contain those and also WARs. However, those are quite different beasts than in-the-sense-of-a-packaging JAR files. It's worth noting that special classloaders, that are not in the Java standard library, are needed to make use of them.
The way that WARs etc can collect many JAR files together is indeed very useful, and it's a real shame there's no generic mechanism for doing this in Java outside of Java EE. It would be great to have an 'application archive' or 'meta-archive' format that simply bundled some JARs.
So, you're left with this problem of users needing 25 JARs in order to use your plugin. You have roughly two options.
First, you accept the pain, and distribute your plugin as a zip full of JARs, which users will have to unpack.
Secondly, you join the 21st century, and use a build tool and distribution mechanism which handles dependencies automatically: in practice, that means using Gradle, or Maven, or some other tool (such as Ant) in concert with Ivy, to obtain dependencies from Maven Central, and then then releasing your code along with a POM file which lists those dependencies. Users can then download your JAR and your POM, and have their own build tool obtain the dependencies.
If you do go the second route, it might be prudent to also release a zip of the dependencies, for the benefit of users who are not using automatic dependency management.
The intent (AFAIU) is for JAR files to behave like native code shared object files (.so on Unix, .dll on Windows). Generally, an application will install several shared object files as siblings, plus an executable with which to launch them.
An executable JAR is more like a standalone executable, and so it is more common to include all dependencies (similar to the way a statically-linked native code executable contains all its dependent objects directly).
Unfortunately, the default ClassLoader is not able to load classes from nested JARs. It is possible to write a ClassLoader that does. Or you can use one someone else has written. From the description of your problem, it sounds like Jar Jar Links is exactly what you're looking for.
Is it correct or incorrect for a Java JAR to contain its own dependencies?
There are use cases where it is correct for a JAR file to contain its own
dependencies. If you would like to support users who do not use modern
dependency management, you may want to provide a JAR file containing your Ant
task code as well as all dependencies. The more powerful, flexible, and modular
approach is to publish versioned JAR files to the Maven repository that
only contain your project code.
1) JAR file containing your project code and all dependencies
Pros
Easy to download and the only setup for end users is including a
<taskdef> in their Ant build files
No setup required to publish Maven artificats
Example Ant target to build JAR
<target name="jar" depends="compile"
description="Creates a standalone JAR of all class files and dependencies.">
<jar destfile="${my.ant.task.jar.file}" update="true">
<fileset dir="${build.classes.dir}" />
<zipfileset src="${lib.dir}/javax.inject.jar" />
<zipfileset src="${lib.dir}/guice-3.0.jar" />
<zipfileset src="${lib.dir}/guice-multibindings-3.0.jar" />
<zipfileset src="${lib.dir}/guice-assistedinject-3.0.jar" />
</jar>
</target>
Cons
If end users of your Ant task already have some or all of the dependencies
included in their projects, then they will end up with redundant copies of the
dependencies
The JAR file could be very large
2) JAR file containing only your project code published to Maven Repository
Pros
Users may fetch any version of your Ant task that you have published to
the Maven repository, which provides more flexibility in releasing new
versions of your task while allowing existing users to continue using previous
versions to avoid possible regressions
Avoids duplicate copies of common dependencies (except where different versions of a dependency cause errors)
JAR file will be small
Cons
Need to learn about the following:
Maven Repository
Publishing Maven Artifacts - see
Ant + Ivy specific preparations and procedures
Apache Ivy - Dependency manager integrated with Apache Ant
For reference, the Java™ Tutorials provide a good summary of JAR files.
Lesson: Packaging Programs in JAR Files
The Java™ Archive (JAR) file format enables you to bundle multiple files
into a single archive file. Typically a JAR file contains the class files and
auxiliary resources associated with... applications.
The JAR file format provides many benefits:
Security: You can digitally sign the contents of a JAR file...
Decreased download time: If your applet is bundled in a JAR...
Compression: The JAR format allows you to compress your files for efficient
storage.
Packaging for extensions: The extensions framework provides a means by
which you can add functionality to the Java core platform, and the JAR file
format defines the packaging for extensions...
Package Sealing: Packages stored in JAR files can be optionally sealed so
that the package can enforce version consistency. Sealing a package within a
JAR file means that all classes defined in that package must be found in the
same JAR file.
Package Versioning: A JAR file can hold data about the files it contains,
such as vendor and version information.
Portability: The mechanism for handling JAR files is a standard part of the
Java platform's core API.
"Jar Jar Links" is only good for a standalone applications. But not for Ant.
If your project has the same dependencies and they are upgraded to newer versions later on, like xstream-*.jar, then there will be a conflict, and the wrong version may be picked up. In the worst case there will be MethodNotFoundException. That's why it is a bad practice to include dependencies in a single jar.
What's a problem with "I don't want to be forcing my users to be copying-n-pasting 25+ JARs"?
That's the easiest solution. And the best, because you will avoid problems in the future.
Now, when you see the inconveniences of Ant, you might want to compare it to Gradle. With Gradle you get tasks a bit similar to Ant and you don't need to provide any dependency jars. All dependencies for you will resolve Gradle. And like in Ant you still can create your tasks.
Some java application vendors use the following scenario to distribute their application which depend on other jars, it reminds of static linking. At the stage of building the jar all dependencies (being also jars) are unpacked. When building the final jar, they include both their freshly compiled classes and the classes extracted from dependencies.
Possible issues:
Applications cannot reuse the libraries as they are contained in the app. Usual static linking issue.
The licenses of the repacked libraries must be respected. Usually it will be ok to repack them, but sometimes additional care must be paid to their license files, which may happen to be inside their jars.
AFAIK it's not possible to have jars inside the jar or it will be impossible to specify a classpath for them. Hence the repacking procedure.

Benefits in Android to importing a library internally vs externally

Post ADT 17, non-Android libraries need to be included either in the "libs" folders of the project or exported via the "Order and Export" tab in the build path. What's the difference (if any) between importing a library externally:
And internally:
Is there an advantage to importing a library in a way that it is included in the "Android Dependencies" group?
How do you add external jar dependencies into your Android project's build path (internally or externally) make no difference on the actual build process (more specifically at compile and dex step), all it does is to tell build process where to looking for the required jars at compile and dex step.
The Android Dependencies element shown in Java Build Path - Libraries window is just another abstract layer that ADT plugin used for managing/grouping jar dependencies. where your external jar files (in your case android-support-v4.jar) appears (inside or outside Android Dependencies) in that window makes no difference.
Since r17, dependencies management has been much improved, and it is recommended to use libs/ directory store all jar dependencies (refer to you internal way), which is considered as a automation approach (as ADT plugin becomes more smarter now), see Revisions for ADT 17.0.0:
New build features
Added feature to automatically setup JAR dependencies. Any .jar files in the /libs folder are added to the build configuration (similar to how the Ant build system works). Also, .jar files needed by library projects are also automatically added to projects that depend on those library projects. (more info)
However, you can still use the old way (refer to you external way) if you prefer, which is considered as a manual approach (as ADT plugin was stupid before), see Recent Changes‎ for r17 Release:
Important: If you are still referencing jar libraries manually instead of putting them under libs/ be aware of the following:
If the project is a Library project, these jar libraries will not be automatically visible to application projects. You should really move these to libs/
If the project is an application, this can work but you must make sure to mark the jar files as exported.
Is there an advantage to importing a library in a way that it is included in the "Android Dependencies" group?
Automation vs. Manual from dependency management perspective, automation is always considered as more errorless than manual in the world of computer science.
The number one, show stopping, 'I can't believe they didn't test this', disadvantage of putting external jars in the libs directory is that you can't set the javadocs location for them, as the option shows as 'None (non modifiable)'.
Hence I still use Export option in build properties
It has to do with library dependency management of Android. for details see http://tools.android.com/recent/dealingwithdependenciesinandroidprojects
From the Eclipse FAQ
An internal resource resides in some project in the workbench and is therefore managed by the workbench; like other resources, these resources can be version managed by the workbench. An external resource is not part of the workbench and can be used only by reference. For example, a JRE is often external and very large, and there is no need to associate it with a VCM system.
So, quite simply, if you want to be able to manage a JAR as part as the project, exposing it to SCM and such, then treat it as a internal resource otherwise, treat it as a external resource. It will not make any difference in the APK produced in the end, its simply a eclipse thing.
If you want to avoid creating a copy each time you want to use your library, treat it as a external resource. But, can I suggest you look into maven and the android maven plugin, maven has a bit of a learning curve (especially if you are used to "make" or "ant" style build scripts), but it is very much worth the effort.

Deploying Java Files

What are the best practices (and enabling tools) to deploy Java standalone applications along with any required jar dependencies, config files, and launch scripts?
Are there any Maven plugins that easies publishing binary releases, so that users don't need to use maven for example?
Are there any Maven plugins that easies publishing binary releases, so that users don't need to use maven for example?
Use the Maven Assembly Plugin to create a binary distribution as zip/tar.gz/tar.bz2 of your project. This plugin is extremely flexible - at the price of some complexity - and you can do almost anything you want. Then deploy (in the maven sense) the produced artifact, upload it somewhere, etc.
As for dependency, I just use maven dependency copy plugin and copy all dependencies into a ./lib folder, and supply a launch script that uses the class path wildcard (that way you can change your dependencies as much as you want and don't have to change the launch script). As for configuration files, I put it in a ./config folder and again include it in my app's classpath in the launch script (The former admittedly only works for > java 1.6).
So in the end almost all my app has the following structure:
mystuff.jar launch.sh
./lib
./config
Then I'll just zip up the whole thing and give it to my users. The whole process is probably easy to automate using maven, but I confess that I do it by hand :p
If you prefer and the licenses permit, you could also just bundle all dependencies into a single jar (with expanded dependencies inside) using the assembly plugin. This tends to make the jar bulky and giving the users an updated app. more difficult. Also I had issues with it several time because of class files getting overwritten or something so I personally stick to the ./lib folder.
There's launch4j, which, if you can get it to work, will bundle up a Java app into an executable for your platform.
If your deployment target supports RPM files, I strongly suggest you investigate the rpm-maven-plugin. It allows you to easily map your project artifacts , including dependencies, to a RPM package.
I've been using it with great success to medium-scale application deployment.
You can use Oracle's ant or maven scripts:
http://docs.oracle.com/javafx/2/deployment/jfxpub-deployment.htm
The above will not only compile your code and create jar files, but it will also create binary executable (windows exe file or Mac app file). It can also create native installers. In addition it lets you include JVM with your distribution so the end use doesn't need to install Java.
Take a look at the Appassembler Maven Plugin. You may also want to combine it with the Assembly Maven Plugin.
Use the appassembler plugin to generate a set of "programs" by specifying executable names and main classes. You can also have it prepend and create an etc directory in which you can add configuration files.
If generating the directory with the start-up scripts and directory of binary files isn't enough, you can use the assembly plugin to copy over additional files (say your configuration files) into the appropriate directory and/or package your application into an archive.

Categories

Resources