JAR vs WAR file specification - java

I noticed that WAR files are supposed to have classes/ and lib/ directories for containing their classfile root and dependencies, respectively.
I also noticed that it is not common practice for JARs to contain such a lib/ directory and to contain their own dependencies.
So now I'm wondering why JARs shouldn't/usually-don't contain their own dependencies, but WAR files are expected to. Unless I'm missing something, both require their dependencies to be on the classpath at runtime (JARs won't run if they're missing dependencies, just like WARs won't run). So to me, all the arguments for putting dependencies in a WAR file also apply to a JAR.
What am I not "getting" here?!?

From a conceptual point of view:
A jar typically represents a single library which can be used and may or may not have dependencies.
But the idea is that a specific functionality can be provided as a library in a jar.
A war is an application by itself and as such it should include all the dependencies

WAR files (mainly WEB applications) are uncompressed, and all JAR files inside the lib folder will be in the classpath of your web application while running.
JAR files might also contain jar files, but will not be found and loaded by the default class loader.
There are special class loaders that do load jar files inside jar files, but not standard.

Because unless you use a custom classloader that can load classes from nested jars (like JarClassLoader), you can't load classes from nested jars. Servlet and app containers will add jars contained inside war/ear files to their application's classpath.

They are containers with different purposes.
Jar is intended for Java class files and resources and can be a library or a directly runnable application.
War is a container to package complete Web applications including all dependencies (such as Jar files and other web resources).
The question boils down to, why can't a jar include other jars. This I would take as a design decision taken to allow maximum flexibility in interchanging dependencies.

Related

OpenJDK-11 issue while accessing Jaxb Jars packaged inside war/lib from tomcat/lib Jar

We are having a custom utility jar in tomcat/lib folder. This custom utility needs access to Jaxb jars which is not part of Jdk-11. We already modified application dependencies to include Jaxb jars & these are now getting packaged in our WAR/WEB-INF/lib folder.
Is there a way to access these JAXB jars packaged inside war/WEB-INF/lib folder from tomcat/lib Jar?
Probably both are loaded by different class loaders & this may not be possible, but we do not want to copy these Jaxb jars to tomcat/lib to avoid duplicating them.
Also moving custom utility jar from tomcat/lib to war/WEB-INF/lib does not looks an option here as its being managed by another team & multiple teams/applications are sharing it.

EJB Timer (#Schedule) not recognized by WildFly when inside a JAR which is also inside an EAR

I have an EAR file with 3 WARs and some common dependencies within lib/ folder. One of those dependencies has an EJB with a scheduled method, but it seems that the server is not recognizing it. No evidence in log, no code executed.
But when I deploy a simple war with the same jar within WEB-INF/lib, it works. I've already tried to package the jar as an ejb-jar with the maven plugin, but no success at all.
Any ideas on what must be going on?
Jars in the lib directory of an EAR are not considered to be EJB jars and their content is not considered at deployment time in that respect. The lib directory only exists to make it easier to provide library jars whose classes are automatically made visible to all the modules in an EAR file.
Your EAR file contains a META-INF/application.xml file that lists out the various modules that it contains. Prior to Java EE 6, only ejb-modules were considered for potential EJBs. Java EE 6 and newer added web-modules to that list. All jars within a web-module's WEB-INF/lib directory are considered to be part of the web-module, even if they contain ejb-jars. Any ejb-jar.xml files found within a web-module are merged together. This applies even if the web-module is deployed as a standalone WAR file.

Java Classpath patch concept for WAR files

There is a classpath patch concept frequently used by adding patch.jar file in classpath before main jar file. I have used this method for running J2SE applications.
I wonder if same concept is applied for J2EE projects such as in WAR files. If so how I can make it possible?
I'm not sure whether there's any guaranteed ordering among different JAR files in WEB-INF/lib, but it is guaranteed (Servlet Specification version 3.0, section 10.5) that WEB-INF/classes will be ahead of all the WEB-INF/lib JAR files. So you could put your "patch" class files under WEB-INF/classes instead of putting them in a JAR.

How hard is it to load JARs from another location?

I have the following scenario. I'm working with a server which has a lib folder which contains all of its JARs, but things get kind of complicated when having multiple applications for the server, as the lib directory gets kind of crazy.
What I'd like to do is put all of my application's JARs in a different location and instruct the classloader to load them when my application is loaded. How can I do this? How will I need to rewrite my application to facilitate this?
As far as I know, it is not possible to load the jar files or set the CLASSPATH at runtime unless you have written your own class loader. Tomcat is a good illustration in which the tomcat's class loader loads the jar files dynamically in multi-level.
http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html
There is a common class loader which allow the jar files to be shared accross all web application. However, if you want to addthe jar files which are only loaded for the web application then you should add it under webroot, e.g. WEB-INF/lib. The libraries in this folder are not shared to all applications. For example, this means if two web applications are using different versions of the same library, they will not be mixed up.
Since I am using maven to manage the project, I do not need to worry about where to put my ja dependencies. Maven automatically bundles the libraries into war file for me.
So if you are not using servlet container, e.g. tomcat, jetty, etc. , then you will need to write a class loader. If that is necessary, then have a look into tomcat but it may not be easy.
You can add directories to the class path in Java 6.

Multiple packages in java project and jar files

I am trying to build java client for rabbitmq.
I have my source folder as A.mq.client.
Also I have a libs folder where I have my rabbitmq jar files. These jars have been added to build path. Everything works OK in Eclipse.
Then I export the entire project in eclipse as jar. jar contents are .classpath, libs folder and my package folder + rest of stuffs.
Now I am getting exception :
java.lang.ClassNotFoundException: com.rabbitmq.client.Consumer
com.rabbitmq.client.Consumer is in lib jars.
I am running jar using java -cp rabbit.jar A.mq.client.Worker where I want to invoke main method of worker class in my package and Worker is accessing jar packages.
As far as I know, you can't generally package jar files inside of another jar file. Typically, you would have to expand all the various dependent jars prior to packaging up your final jar. If you've ever used Maven, this is what the maven-shade-plugin helps to automate.
See the answer in this question for more information.
The CLASSPATH lists places, where the classes are found - either in a directory or in a jar, but not
directories of directories
directories of jars
jars of directories
jars of jars

Categories