How to embed maven modules as .class dependencies as opposed to jars? - java

I have a multi-module maven project that is used to produce a single spring boot fat jar. My project looks something like this.
- Parent Module Aggergator
- A
- B
- C
- app <-- app.jar is the only thing I want to publish
In my case module A, B, C are only ever used by app and should not be published into maven repo. I have split up the app into multi-module project because it's a lot of code in the app and it's to work with that way.
Currently the app.jar will contain inside it a.jar, b.jar c.jar.
Is there a way to tell maven that the compiled classes from module A, B, C should just be inserted into app.jar classes folder without ever producing A.JAR, B.JAR, C.JAR?

I use the Maven Shade Plugin for my multi-module project; it creates a single JAR and extracts each module into it rather than creating multiple JAR files:
Parent pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<groupId>...</groupId>
<artifactId>pipeline</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>firehose</module>
<module>gson</module>
<module>lambda</module>
<module>mapper</module>
<module>model</module>
<module>receiver</module>
<module>redshift</module>
<module>reloader</module>
<module>s3</module>
<module>sns</module>
<module>sqs</module>
<module>systemstests</module>
<module>transaction</module>
<module>utility</module>
</modules>
<dependencies>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Child pom.xml (the JAR):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>...</groupId>
<artifactId>pipeline</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>lambda</artifactId>
<dependencies>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<finalName>MyJar</finalName>
</configuration>
</plugin>
</plugins>
</build>
</project>

Here is a non answer.
Is there a way to tell maven that the compiled classes from module A,
B, C should just be inserted into app.jar classes folder without ever
producing A.JAR, B.JAR, C.JAR?
You could use the repackage goal of the spring boot maven plugin that flatten the dependencies into classes in the uber jar.
In my case module A, B, C are only ever used by app and should not be
published into maven repo.
Adding the modules in a local repository is really wanted to have a efficient and standard build.
Without that, you will need to compile systematically each module at each time you want to run your spring boot app.
While actually sometimes you need to build dependencies, but other times you don't need because these are already updated.
Or else you will be constraint to twist the default Maven way of work by adding manual tasks to compile from the spring boot module the other modules and to move the compiled classes into the spring boot module. Really not a gift for the people that will have to read/maintain this configuration.

Related

Why is OSGI bundle module getting built twice

I am building this multi-module project with Maven. The folder structure of the project at root is as follows:
core (dir)
|--- pom.xml
|--- pom (dir)
|---com.loc.dist.core.msp.osgi.pom (dir)
|---pom.xml
|--- com.lgc.dist.core.msp.example.helloservice.client (dir)
|---pom.xml
Project com.lgc.dist.core.msp.example.helloservice.client is packaged as OSGI bundle and it is a child module of com.loc.dist.core.msp.osgi.pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lgc.dist</groupId>
<artifactId>com.lgc.dist.core.msp.osgi.pom</artifactId>
<relativePath>../pom/com.lgc.dist.core.msp.osgi.pom</relativePath>
<version>0.1</version>
</parent>
<artifactId>com.lgc.dist.core.msp.example.helloservice.client</artifactId>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>com.lgc.dist</groupId>
<artifactId>com.lgc.dist.core.msp.service</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Export-Package>com.lgc.dist.core.msp.example.helloservice.client.*;version=${project.version}</Export-Package>
<Private-Package>com.lgc.dist.core.msp.example.helloservice.client.internal</Private-Package>
<Import-Package>*</Import-Package>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The pom.xml in top level shows pom folder and com.lgc.dist.core.msp.example.helloservice.client are in the reactor list.
<modules>
<module>pom</module>
<module>com.lgc.dist.core.msp.example.helloservice.client</module>
</modules>
When I ran mvn clean install from the root, it tends to build com.lgc.dist.core.msp.example.helloservice.client back to back twice. It is ok to install twice, but it will cause trouble when I run mvn deploy. All other submodules just built once. It is only the child modules of com.loc.dist.core.msp.osgi.pom are being built twice. I guess osgi builds all the bundle modules by default. But if I comment it out in pom.xml, the osgi bundle modules won't get built at all. What should I do to build these OSGI bundles just once?
EDIT It works fine if I change the packaging mode from bundle to jar, but that negates the purpose of having OSGI bundles.
Since the project "com.lgc.dist.core.msp.example.helloservice.client" is not a direct child of top level pom.xml, remove it from there.
So, in top level pom.xml, the entries should be :
<modules>
<module>pom/com.loc.dist.core.msp.osgi.pom</module>
</modules>
And pom.xml in pom/com.loc.dist.core.msp.osgi.pom should be having :
<modules>
<module>com.lgc.dist.core.msp.example.helloservice.client</module>
</modules>
After some research, it turns out maven-bundle-plugin 2.5.4 deploys the bundles by default. According to one of the answers of When using “bundle” packaging with maven-bundle-plugin goals are executed twice
(I'm surprised it did not get any up votes), you need to stop deploying by adding the execution block
<executions>
<execution>
<id>default-deploy</id>
<phase>no-execute</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
It is working now.
EDIT, based on the comment of this answer, it is resolved in 2.5.5. Haven't tried it though.

mvn process-resources doesn't pull down uber jar created with shade plugin

Goal: Create an executable uber jar with maven shade plugin that can be executed during the mvn compile of another pom.
Repro steps:
Create a pom.xml for the "publisher" component using below pom.
Use a Jenkins build to mvn deploy it (mvn install will work as well)
Add dependency to pom.xml for "consumer" (pom below)
mvn compile the consumer
Expected behavior:
Uber jar for publisher is downloaded somewhere in consumer/target directories
Actual:
Uber jar does not appear in consumer directory
Component 1: Publisher
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mec.experiment</groupId>
<artifactId>publisher</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.6.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.mf</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Component 2: Consumer
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mec.experiment</groupId>
<artifactId>consumer</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.mec.experiment</groupId>
<artifactId>publisher</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
The answer from the possible duplicate I linked to in the comments has a link to a dead example page. Here's a supplement for you. The plugin configuration would belong inside the consumer pom.
exec:java
Full name:
org.codehaus.mojo:exec-maven-plugin:1.5.0:java
Description:
Executes the supplied java class in the current VM with the enclosing project's dependencies as classpath.
Attributes:
Requires a Maven project to be executed.
Requires dependency resolution of artifacts in scope: test.
The goal is thread-safe and supports parallel builds.
Since version: 1.0.
See especially executableDependency for your use case. That looks like it will allow you to reference producer according to its group id and artifact instead of hard-coding a path.

Can't resolve class dependencies in a MAVEN project with Child/Modules (seen in Eclipse and mnv CLI)

I have an Eclipse Maven Project (parent) that hosts three Maven MODULES (it's children). Only the child MODULES have code under "src/main/java/..." (i.e. the PARENT is just a stub place holder for the children).
Each MODULE is independent of one another... I just set it up that way to reduce clutter. =:)
Now the project structure didn't start out this way. Initially it was just one big PARENT and no child MODULES; and everything worked fine. But then I reorganized things within Eclipse (again to reduce clutter) using various moves/refactors, and things stopped working.
The Problem: My source code can't find imported classes now, so my dependency resolution became problematic somewhere. And the problem isn't just seen in Eclipse, but also when I run, say, 'mvn clean install' from the CLI. So I suspect something is wrong with the set of POM files that resulted from my moves/refactors.
Here they are (the PARENT and one CHILD). Am I missing something, or is something incorrect? Maybe I should check something Eclipse, too?
Note that I embedded a couple of little in-line questions inside the POM files below. :)
The PARENT pom.xml file:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<name>someName</name>
<packaging>pom</packaging>
<groupId>someParentGroupId</groupId>
<artifactId>someParentArtifactId</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<jdk.version>1.7</jdk.version>
<example-core.version>0.9.3</example-core.version>
<!-- Intended to be used by some Child/Module.
I hope PARENT/CHILD POM inheritance works that way? -->
</properties>
<dependencies>
<!-- Dependencies are all in the Children/Modules -->
</dependencies>
<!-- ################### BUILD SETTINGS BEGIN ##################### -->
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin> <!-- Used to create an UBER/FAT-JAR. -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<finalName>uber-${project.artifactId}-${project.version}</finalName>
</configuration>
</plugin>
</plugins>
</build>
<!-- ################### BUILD SETTINGS END ####################### -->
<modules>
<module>childModule1</module>
<module>childModule2</module>
<module>chileModule3</module>
</modules>
</project>
Example CHILD pom.xml file:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>someParentGroupId</groupId>
<artifactId>someParentArtifactId</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>someChildArtifactId</artifactId>
<!-- I noticed this missing in the Children/Module POM. Is that okay?
<name>
</name>
-->
<dependencies>
<dependency>
<groupId>org.example.somgGroupId</groupId>
<artifactId>example-core</artifactId>
<version>${example-core.version}</version>
</dependency>
</dependencies>
</project>
Again, the problem seems simple. I can't resolve imports (so, naturally, my Classes have import-ralated errors).
Thank you in advance!
name is not a mandatory attribute in pom.xml.
I assume someChildArtifactId is given as an example. If not, the same artifact id should be used in the parent pom.

Deploy maven project ear in websphere

I am using eclipse JUNO integrated with websphere 8.5.My problem is that,my project is in MAVEN module so each time i have to clean and install the MAVEN Project to generate the EAR.
After EAR generation, I have to remove the ibm related xml's inside the META-INF folder and WEB-INF folder and then I have to open the administrative console in websphere to deploy the EAR.This alone is taking huge amount of time.
Could any one please suggest a script to deploy and run the MAVEN project in websphere.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample.app</groupId>
<artifactId>SAMPLE_APP</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<name>SAMPLE APP</name>
<modules>
<module>SAMPLE_APP_Props</module>
<!-- Changes to UI Framework -->
<module>SAMPLE_APP_UIFile</module>
<module>SAMPLE_APP_Web</module>
<module>SAMPLE_APP_EAR</module>
<module>SAMPLE_APP_Forms</module>
<module>SAMPLE_APP_Filters</module>
<module>SAMPLE_APP_Logging</module>
<module>SAMPLE_APP_Security</module>
</modules>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
The below 2Files i have to remove before i deploy the generated ear in websphere.
ibm-application-bnd.xmi
ibm-application-ext.xmi

Maven: how to include module dependencies into general dependency-jars folder

I'm working on a multi module maven project structured as follows:
SQR
+ pom.xml
+ core
| + src
| + target
| | + dependency-jars
| pom.xml
+ connector
| + src
| pom.xml
+ xmlreader
| + src
| pom.xml
+ xmlwriter
| + src
| pom.xml
The SQR is the top level project, whereas the core, connector, xmlreader, xmlwriter are modules. Currently the core builds everything together into a executable jar with external jar libs. The core uses several dependencies i.e. log4j, commons. So far so good. The problem arises modules are using specific dependencies i.e. http-client, commons-io. They all get added into class-path but they don't get copied to the core/target/dependency-jars. Another drawback is that I have to extend the pom.xml of every module when using dependencies (e.g. copy-dependencies etc.).
Currently I have the following files:
SQR/pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sqr</groupId>
<artifactId>SQR</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>SQR</name>
<url>http://maven.apache.org</url>
<modules>
<module>core</module>
<module>connector</module>
<module>xmlwriter</module>
<module>xmlreader</module>
</modules>
</project>
core/pom.xml:
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.sqr</groupId>
<artifactId>SQR</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>core</artifactId>
<packaging>jar</packaging>
<name>core</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
[...]
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
[...]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>com.sqr, org.apache.commons</includeGroupIds>
<outputDirectory>${project.build.directory}/dependency-jars/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Other module pom.xml files look similar to the one listed above. It feels like much overhead, extending each pom.xml file. Is there a best practice to solve this problem? Or is there a quick and clean fix for this problem?
tl;dr: I want a multi module project where all modules and their dependencies get build into seperate .jar files and linked together. As follows:
+ dependency-jars
| commons-lang3-3.3.2.jar (used by only xmlwriter)
| connector-1.0-SNAPSHOT.jar
| xmlreader-1.0-SNAPSHOT.jar
| xmlwriter-1.0-SNAPSHOT.jar
| log4j-1.2.17.jar (used by all modules)
core-1.0-SNAPSHOT.jar (being the main entry of the application)
The solution to your problem seems to be a distribution.
The following solution will help you to build a distribution artifact:
boot/core.jar
libs/connector.jar
libs/xmlwriter.jar
libs/xmlreader.jar
Don't worry it's simpler as it sounds!
create a new module called ditrib
create an assembly file: distribution.xml in the directory: src/main/assembly.
The content should be closed to this one:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">`
<id>distrib</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/boot</outputDirectory>
<includes>
<include>${project.groupId}:core</include>
</includes>
</dependencySet>
<dependencySet>
<outputDirectory>/libs</outputDirectory>
<includes>
<include>${project.groupId}:connector</include>
<include>${project.groupId}:xmlwriter</include>
<include>${project.groupId}:xmlreader</include>
<include>*:commons-lang3</include>
<include>*:log4j</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
Inside your pom, to create the distribution then declare:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/distrib.xml</descriptor>
</descriptors>
<finalName>${project.artifactId}-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
This will generate a jar named *-distrib.jar in your target folder after issuing: mvn package.
NB: generally distribution comes with a config/config.properties file that does the glue between what is in the boot dir and what is in the libs directory. Also the distribution cannot be fully fledged without a bin/run.{sh|bat} files.
I hope, I helped you!
Cheers!
If your goal is to include the connector, xmlreader, and xmlwriter jars, along with all of their dependencies, into the dependencies folder of the core module, then a common method is to list those three modules as compile dependencies in the core module pom.xml, just as you would if the core module were a web module dependent upon lower level modules, such as domain or common.
Those modules do not appear in the dependencies section of the core module pom.xml that was listed. Adding them may not provide 100% of the solution to your problem, as custom packaging is being performed, but should move you significantly closer to the goal.
Edit: Remove
<includeGroupIds>com.sqr, org.apache.commons</includeGroupIds>
, then all transitive dependencies should be copied for connector, xmlreader, xmlwriter.
Take a look to the Shade Plugin of Maven, maybe it could be helpful.
http://maven.apache.org/plugins/maven-shade-plugin/

Categories