For reasons that I won't go into, I need to build the following structure:
EAR
|
|-- Uber-JAR
|
|-- WAR
I can build the uber JAR with the Maven Assembly plugin, but when I try to include it in the EAR (built with the Maven EAR plugin) it includes a normal JAR version, which has no sources (because I'm using the uber JAR to pull all the sources in the project together).
How can I get the uber JAR included in the EAR?
This is one way to fix it. If there's a better way I'd like to know it :)
Just include:
<earSourceDirectory>${basedir}</earSourceDirectory>
<earSourceIncludes>/path/to/jar.jar</earSourceIncludes>
in the EAR plugin configuration.
EDIT: Seems I spoke too soon. In the project's parent pom I have all the modules listed to build, with the uber JAR above the EAR module (as the last two modules).
It won't build the whole project:
'Artifact <ARTIFACT> (included by module) does not have an artifact with a file'
EDIT (again):
Final Answer
So, finally, in the configuration for the Maven Assembly plugin, I have:
<configuration>
...
<finalName>myjarname</finalName>
</configuration>
This creates a JAR file called simply 'myjarname.jar'.
In the Maven EAR plugin configuration, I use the following structure:
<configuration>
...
<modules>
...
<ejbModule>
<groupId>com.mygroup</groupId>
<artifactId>myartifact</artifactId>
<bundleFileName>myjarname.jar</bundleFileName>
</ejbModule>
</modules>
</configuration>
This grabs the specific jar and puts it in the EAR. Voila!
Related
I have a Jersey Tomcat project B that depends on another similar project A, I am developing on Eclipse.
When I run A on it's own, it runs with no problems. The export configuration for its build path is:
And the deployment assembly for A is:
Then, for project B, I imported project A into the java build path like this:
The build path for project B looks like this:
And the web deployment assembly for project B is:
Project A is listed as a .war, I am not sure if this is related to the issue. The pom.xml for project A lists war as packaging:
<packaging>war</packaging>
The pom.xml for project B mentions project A like so:
<dependency>
<groupId>some.project.A</groupId>
<artifactId>flocktracker</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
Eclipse doesn't show any issues until when I try to deploy in a Tomcat server, whe I get this error:
java.lang.NoClassDefFoundError: some/project/A/SomeClassInA
at some.project.B.SomeClassInB.<init>(SomeClassInB.java:##)
If it helps, SomeClassInA is an implementation of org.glassfish.jersey.server.ResourceConfig.
SomeClassInA is mentioned in the web.xml file like so:
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>some.projectA.SomeClassInA</param-value>
</init-param>
SomeClassInA is an implementation of javax.ws.rs.ext.ContextResolver<T>
I used right click on project > export > WAR file to examine the contents of the file and I couldn't find the classes of Project A on WEB-INF/classess or elsewhere in the .war file.
Is there something I am missing or that I am doing wrong?
Thanks!
Keeping the Eclipse tooling aside, from a Maven configuration perspective:
Maven does not load classes from a WAR artifact, as it would load from a JAR artifact.
Ideally WAR artifacts are not supposed to be used as a dependency, unless you're building a final EAR artifact.
You have the following choices. All of them require a modification to ProjectB as well:
Although this is the least likely case, if ProjectA is not used for deploying a web application, you could just change its packaging to jar
You could move all the required classes to a separate module that builds a JAR, and use this dependency in both ProjectA and ProjectB.
If you do not want to move the classes to another module/project, you can configure the war plugin in ProjectA to generate a jar artifact alongside the war artifact, using <attachClasses>true</attachClasses>
<project>
...
<artifactId>yourWebapp</artifactId>
<version>yourVersion</version>
...
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
This produces a classes artifact in ProjectA, which can be used in ProjectB as a dependency with <classifier>classes</classifier>
<dependency>
<groupId>yourGroupId</groupId>
<artifactId>yourWebapp</artifactId>
<version>yourVersion</version>
<classifier>classes</classifier>
</dependency>
I have the following project package structure.
parent
|- module1
|- module2
|- module3
I am able to include module3 as a dependency in both pom.xml files of module1 & module2. This gives me access to all of the dependencies & code from module3.
<dependency>
<groupId>my.group</groupId>
<artifactId>module3</artifactId>
<version>1.0.0</version>
</dependency>
However, when I run maven commands such as dependency:tree on the pom file of module1 or module2, maven will try to search on certain <servers> that are listed in my settings.xml file in order to try & download module3 as an artifact. module3 is not deployed to any <server> at the moment so, the maven command fails with following error
[ERROR] Failed to execute goal on project module1: Could not resolve dependencies for project my.group:module1:jar:1.0.0-SNAPSHOT: Failed to collect dependencies at my.group:module3:jar:1.0.0-SNAPSHOT: Failed to read artifact descriptor for my.group:module3:jar:1.0.0-SNAPSHOT: Could not transfer artifact my.group:module3:jar:1.0.0-SNAPSHOT from/to MyServer (https://example): Access Denied to: .......etc.
Ideally, module3 would not be deployed at all as an artifact but, instead it might simply have <packaging>pom</packaging>. module3 is just some module that should only be used by module1 & module2. Also, FYI the dependency tree of module3 builds perfectly fine.
Dependencies should never be of packaging pom. The need to be proper JARs and also need to be deployed to the repository.
Usually, you run build commands on the parent of the multi module project. If you want to restrict the build to one module, use -pl.
As far as I understand the question, the following maven module are part of the same reactor:
parent
|- module1
|- module2
|- module3
parent should have:
<modules>
<module>module1</module>
<module>module2</module>
<module>module3</module>
</modules>
Otherwise, Maven will not look in the file system but in the local repository.
Also, to my understanding, in your example module1 and module2 are two jar packaged module (eg: <packaging>jar</packaging> or omitted) but parent and module3 are two pom packaged module (eg: <packaging>pom</packaging>).
I suppose you want to create some kind of module importing only dependencies without code, in which case you should import it using:
<dependency>
<groupId>my.group</groupId>
<artifactId>module3</artifactId>
<version>1.0.0</version>
<type>pom</type>
</dependency>
Strange as it may be, this should work.
You can also use --offline to force maven to not go online.
Make sure the version of the module is correct.
Normally, when you run "mvn clean install" in parent project, all modules will be built, Order builds module3 -> module1 and module2. module3 is always built first.
Thanks
I use maven-shade-plugin in my java project.
I have a module called core and i would like to pack all its dependencies into one single jar. I don't wan't to create fat big jar every time and deploy it along with my application code. My application jar has size < 1 MB but dependencies > 20 MB
On my server i would run my application like:
java -cp core.lib.jar:core.jar myApp
I need to deploy only core.jar to my server when i change application code and need to upload core.lib.jar only when i change dependencies (this is very rare).
There's a lot of docs how to build fat jar with java sources but i want to exclude them and deliver it to the server independently.
There is two maven plugins for building fat jar: assembly and shade. I want to stick with shade.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.3</version>
<executions>
<execution>
<phase>none</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<excludes>
<exclude>core</exclude>
</excludes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
When i run mvn -pl core shade:shade i get error: core: Failed to create shaded artifact, project main artifact does not exist
I thought that that option:
core
would exclude my sources from the artifact.
I set phase to none because i don't want to create fat jar when i want to run package.
I would like to run mvn shade:shade and have updated fat jar.
I'm not an expert in maven or its plugins, so any help is very appreciated :)
I haven't used shade plugin by myself so I can't provide any practical guidance, however it seems like you need a multi-module maven project:
Refactor your project (move the folders) to look like this:
my-project
|__app
| |__src
| | |__main( (and all the production sources/resources inside)
| | |__test (all the tests/test resources inside)
| |__pom.xml
|__core-lib
| |__pom.xml
|__ pom.xml
my-project/pom.xml could be a "multi-module" aggregator: it should have <packaging>pom</packaging> and have the following:
<modules>
<module>app</module>
<module>core-lib</module>
</modules>
Now app module could be a place where you write the code of your application. It will change often, but it won't produce any fat jar - only a regular jar with a compiled code from this module only (in your example, it will be 1mb artifact).
The core-lib module will be a module that in it's pom.xml will contain the definitions of the shade / assembly plugin and this module will be responsible for the creation of the "fat jar". In its dependences section it will list all the 3rd party dependencies/code that you'll have to change 'rarely' (in your case, the one with 20 mb artifact).
If you need that, the "app" module could depend on "core-lib" module so that the application will have an access to the classes from the library.
So your usual workflow will be:
cd my-project/app
mvn package
If you want to build both application and core-libraries, then:
cd my-project
mvn package
You can read about multi modules here or here
I needed to move this block under plugin / configuration
<artifactSet>
<excludes>
<exclude>core</exclude>
</excludes>
</artifactSet>
Used to be in executions block.
Now i can run mvn -pl core shade:shade and have fat jar with dependencies only :)
i have 3 modules in my maven project , each of the modules generate a jar file.
And then i have a 4th module that generates war out of these jars
Here is my POM which is parent of all modules
<modules>
<module>A</module>
<module>B</module>
<module>C</module>
<module>DWAR</module>
</modules>
IN DWAR's pom , I have specified dependencies on all the three modules A,B,C
<dependency>
<groupId>yyyy</groupId>
<artifactId>A</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
.
. And So on.
My war builds successfully, the lib folder of war contains all the jars, but classes folder is empty.
But in each of the modules A,B,C classes folder is populated with compiled classes.
What am I missing?
What you describe is the expected behaviour: Your war contains the three jars. The war itself has no java source files, so its classes folder is empty.
Building a war does not unpack the included jars, but adds them into the war as a whole.
I have a multi module Maven project. Parent project and then two other modules, one of which builds the war through its pom.xml.
Parent Project
---- Java Project
---- War Project
I build the war from parent project. There is another external war dependency in War project's pom.xml. Jars in that project are needed to build a specific profile, which is specified in War project's pom.xml. Maven cannot get those jars from war dependency. I ran the following command
mvn install:install <information about war>
to put it in local.m2 repository, but Maven doesn't pick anything from that dependency. I understand that Maven processes war dependencies differently than it does a jar dependency but I am unable to understand as to how will it pick it up? Any help will be appreciated. Thanks.
Edit
This is how I try to include the war dependency
<dependency>
<groupId>com.example</groupId>
<artifactId>my-id-artifact</artifactId>
<version>1.0.0</version>
<type>war</type>
</dependency>
Also, I would like to mention that I use that maven war dependency in <overlay> tag.