Having a jboss-deployment-structure.xml with dependencies in common libraries - jboss

I have a small issue that is annoying me somewhat. We have built numerous commons libraries for all our applications deployed on JBoss/Wildfly. Some of those common libraries have dependencies to JBoss modules.
The common way for EAR and WAR files is to add a jboss-deployment-structure.xml to the archive, which contains a bunch of module-dependencies.
I have tried several times to add a jboss-deployment-structure.xml to my Commons JARs so that the WAR/EAR-archives that import them will automatically see the dependencies the JAR has as it's own, however, no attempt of doing this renders the correct result.
Has anyone successfully managed to declare "transitive" dependencies in JAR-files packed inside of WAR-files without having to redeclare the same dependencies in the WAR-file's jboss-deployment-structure.xml?
Any examples would be greatly appreciated!

You can use the MANIFEST.MF to declare dependencies for a JAR. The line will look something like:
Dependencies: org.some.module, org.another.module
The Maven plugin maven-jar-plugin will add it for you as part of the build process.
Your best option is to create your own JBoss module to hold all your common JARs used by all your different applications. This module would have it's own module.xml file declaring the dependencies on the JARs contained within it and one any libraries on other JBoss modules. These custom modules can also be versioned and applications can also depend on specific versions.

Related

EAP 7: Ignore or exclude Dependencies from 3rd party liberies MANIFEST.MF

In our war we bundle some 3rd party libraries that contain the Dependencies entries in their MANIFEST.MF files. JBoss modules with such names exist, so JBoss adds them to the application dependency list which causes that these JBoss-provided modules are used.
As we bundle all the required libraries in the war (they're different versions than those provided by JBoss anyway) we want to use these instead. However we don't seem to be able to exclude those undesired dependencies in any easy way so that we wouldn't have to modify those 3rd party libraries. jboss-deployment-structure.xml would be great, but excluding those modules here doesn't seem to have any effect.
Is there any way how to ignore the Dependencies entries in MANIFEST.MF files, or any other way how to force exclude those dependencies?
On a module dependency you can define the imports element and filter with exclude and include the paths inside your module that you don't want to be 'seen'. Something like this should work:
<imports>
<exclude-set>
<path name="META-INF/services"/>
</exclude-set>
</imports>

Skinny War file with Maven in Eclipse

I have a Maven project 'Project A' which contains dependencies. I have a requirement to abstract the dependencies from this project into another project called 'Shared Lib' so that I can make what is called a "Skinny War" file from Project A. Both these files will then be uploaded to a Weblogic server.
However, I am having a lot of difficulties being able to get Project A to pick up the dependencies in Shared Lib.
Some guidance on how I should approach this problem would be much appreciated.
Thanks!
I would split the maven project into two modules. If we call one module SharedLib and the second one Skinny War then you will have something like:
<modules>
<module>sharedLib</module>
<module>skinnyWar</module>
</modules>
In the shared lib module pom.xml you will fill all the dependencies required for the project. In the skinnyWar module your first dependency in the list will be for the sharedLib module. You might need to setup the assembly plugin for the sharedLib module to create a jar in the package phase and you are good to go ;)
Some food of though - do you really want to do this? An important part about using maven is to take care of dependencies for you and package a easy to deploy jar. If you create two different jars it would cause all other kinds of troubles like - were both deployed. Are we using an older version of the dependencies etc.

multi-project sbt build - package all dependent JARs in one directory

I have a multi-project SBT build: some projects are dependent on each other, some are dependent on third-party JARs, and there's a "main" project which depends on everything .
When I sbt package it, I get one JAR in each target/ directory.
What I want to achieve is getting all relevant JARs (mine and external) is one directory. Very similar to the way you package a WAR with Maven.
(And to clarify - I'm not interested in an assembled "FAT JAR" that contains all the dependencies in a single file. Just one directory with all JARs in it)
Im not 100% sure about the suprobject dependencies but I think SBT native packager should help you do something like that, and will also provide a start-script for windows and unixes:
http://www.scala-sbt.org/sbt-native-packager/GettingStartedApplications/MyFirstProject.html
I would recommend sbt-pack for creating self-contained JARs:
https://github.com/xerial/sbt-pack
I use it and haven't seen a glitch so far.
It also generates both OS X/Linux as well as Windows .bat entry scripts for the main classes/objects you choose.

How does Maven handle WAR dependencies at compile time?

I'm using Maven 3 to handle a (large) project. This project defines a set of REST services, using Scala, Akka and the Spray framework. Each service is defined as an independent project, producing a WAR thanks to the "mvn package" command.
I have to "assemble" these different services into a "system", that is, a subset of these services to be deployed for a given purpose, in a single WAR. Maven WAR overlay works good as a first impression: simply create a new project, and add the services to be included as dependencies.
<dependencies>
<dependency>
<groupId>net.modelbased.sensapp.service</groupId>
<artifactId>net.modelbased.sensapp.service.metamodel.repository</artifactId>
<version>0.0.1</version>
<type>war</type>
</dependency>
</dependencies>
It works well, and the classes contained in the independent services are included in the final WAR.
jar tf target/net.modelbased.sensapp.system.envision-0.0.1-SNAPSHOT.war
[...]
WEB-INF/classes/net/modelbased/sensapp/service/metamodel/repository/ModelLister.class
[...]
But ... The Spray framework requires the implementation of a bootstrap, that is, a class that load the implemented services. This file has to be compiled, as it is a plain scala class. But it looks like maven did not includes the WAR dependencies in the compilation classpath.
I saw the WARpath plugin (http://static.appfuse.org/maven-warpath-plugin/) ... But It does not look more or less outdated. Is there a "standard" way of doing what I'd like to do (i.e., include a WAr in the compilation classpath).
Ps. One of the requirement of the project is that each service MUST be deployable as an independent artifact. A solution could be to implement the core of the service as a JAR project, and also provide a WAR project that includes a refarence to the JAR and the associated config file. But it will multiply by 2 the number of project defined, which is not optimal in a way ...
The solution you propose looks good.
You can build a jar from your classes, and then build a war using this jar as a dependency.
You probably can also do this in one single project, I can see no need for two different projects.
You can use the configuration of the maven-war-plugin which offers you a way to create a separate jar file out of the files from src/main/java.
You have to add the configuration items:
<configuration>
<archiveClasses>true</archiveClasses>
<attachClasses>true</attachClasses>
</configuration>
This will create a separate jar file with the classifier classes which can be used as a usual dependency.

Deployment Concepts: Packaging JAR Dependencies, When & Why

So I'm relatively new to Java EE and I am having a tough time understanding when, where and why Java deployment files are packaged with their dependencies.
Say I build my project into myapp.jar, and it depends on fizz.jar, buzz.jar and JODA (joda-time-2.0.jar).
I've heard that the default classloader doesn't package jars inside of other jars, so I have to assume that if I called a jar task from Ant, then the default classloader would get invoked and myapp.jar would be created without those 3 dependencies in it.
Is this because the mentality is to deploy main-less jars in containers or other systems that will provide its requirements at runtime? If not, then how does myapp.jar ever run correctly?
What about executable jars? To met, these must be different than main-less jars, because they are meant to be standalone units, right? That means they would need all of their dependencies packaged with them, right?
Last but not least, what about jars that depend on jars that depend on jars...etc. (i.e., dependencygraphs that are huge)?
I guess all of these questions can be summed up as follows:
Is the idea behind a non-executable jar that it will be ran in such a way that it will know what classpath(s) to look on for its dependencies at runtime? (And thus doesn't need to be packaged with its dependencies)?
Is the idea behind an executable jar that it is a standalone unit and should be pacakged with its dependencies?
If my assertion to Question #1 above is correct, how does such classpath configuration take place? Are these settings that are stored inside the jar (such as in the manifest)? Else, how would a JRE know where to search for a particular jars dependencies at runtime?
Answers to these questions will actually clarify quite a lot of hangups I have with Java fundamentals, and so any input/help here will be appreciated enormously! Thanks
Jars do not know about other jars (unless assisted by some tools like Maven). The inter dependency of the jars is purely resolved by the Classloaders. I strongly recommend to have some idea about classloaders.
To address your questions,
Is the idea behind a non-executable jar that it will be ran in such a way that it will know what classpath(s) to look on for its dependencies at runtime? (And thus doesn't need to be packaged with its dependencies)?
NO. As mentioned, it's the classloader which looks the classpath and the jars mentioned therein. The jars do not have any information about other jars.
Is the idea behind an executable jar that it is a standalone unit and should be packaged with its dependencies?
NO. A classloader loads the standalone executable jars at the start of execution. If it needs other dependency jars it'll look into the classpath for those jars.
If my assertion to Question #1 above is correct, how does such classpath configuration take place? Are these settings that are stored inside the jar (such as in the manifest)? Else, how would a JRE know where to search for a particular jars dependencies at runtime?
For standalone jar (executable jar), the classloader looks for the classpath variable OR classpath passed while invoking the application.
For other type of application (WAR, EAR), There are predefined places/folders where the dependencies should be placed in order to get picked up. This is standardized by specs.
In a nutshell, it's the classloader which is pulling all the threads. There is standard places where it looks for all the dependent jars. This link nicely describes how the classloaders in standalone application and in a deployed (in some container) works.
JAR files are a way to package togher complex java application. Jar application are easy to move between diffrent machines and operating system.
I think the right way to use Jars is not tu put everything (every dependencies) into a single jar.
For example if your application uses a jar libryra (for example jdbc) to access a database you should not put the jdbc jar into your jar.
You had better to build a jar file with only your .class file.
Of course your code needs the jdbc jar to work properly. Here comes to explain how the virtual machine searches for extarnal classes:
-it first searches in the directories that contain the classes that come standard with J2SE (the path depends on your installation)
-it searches in the directories specified by the classpath (a classpath is either an environment variable or an option of the java command)
for example:
java -jar -c /your/path/ yourApp.jar
will run your application and will search th classes your application refers to in the directory /your/path/ so if you have external jars you can put them in that directory.
For detailed documentation: http://download.oracle.com/javase/tutorial/deployment/jar/index.html