How to choose which maven executions are run? - java

THE SETUP
I have a complex project that I'm trying to build using Maven. What follows is a simplified example of that project. The directory structure is as follows:
main - The project has more than one 'ear', each of which contains more than one 'war' plus other supporting jars. Yet they share a common set of WSDL/XSD, as well as Java code.
pom.xml - This is the main pom.xml file, I'll describe it in more detail below.
common-code-one - the two 'ear' package have a body of code in common, it's just java code, no wsdl, no xsd, so no problem.
wsdl - single package holding all the XSD and WSDL files, it has a pom.xml that simply packs it all up inside a jar file, for later use in sub-directories.
ear-package-one
common-code-two - Some of the XSD from 'wsdl' is unpacked here, and turned into code via jaxb2. As part of that, an episode file is generated.
war-package-one - More of the XSD and WSDL files are unpacked here, and turned into code via jaxws. To avoid having duplicate code, I need the episode file from 'common-code-two', and I need the XSD/WSDL files from 'wsdl'.
war-package-two - Different XSD/WSDL, but I still need the episode file from common-code-two, as well as the XSD/WSDL from 'wsdl'.
ejb-package-one - Don't need anything from 'wsdl', but may need some of the code from 'common-code-two', without needing the episode file.
...
ear-package-two
common-code-two - Same problem, different XSD.
ejb-package-two - Same problem, different code.
war-package-three - Same problem, different XSD/WSDL.
war-package-four - Same problem, different XSD/WSDL.
Now, the main 'pom.xml' file. Following Maven's DRY principle, I've put both executions of the maven-dependency-plugin into the main pom.xml. The problem is that in some of the sub-packages above, I only want the 'unpack-schema' execution to run, in others I want both the 'unpack-schema' and 'unpack-common-binding' to run. Of course, for the ones that don't need either, I just don't add the dependency plugin to the build list.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-schema</id>
<phase>generate-sources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.foo.bar</groupId>
<artifactId>wsdl</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}</outputDirectory>
<includes>${schema.include.list}</includes>
</artifactItem>
</artifactItems>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
<execution>
<id>unpack-common-binding</id>
<phase>generate-sources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.foo.bar</groupId>
<artifactId>${common.code.jar}</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}</outputDirectory>
<includes>**/commonCode.xml</includes>
</artifactItem>
</artifactItems>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
THE QUESTION
What do I put in the sub-projects' pom.xml files so that only the executions that are desired happen?
If I simply put in
<build>
<plugins>
...
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
...
</plugins>
</build>
then both executions happen. In the 'war' packages, that's ok, that's what I want to have happen, but in the 'common-code' packages, I only want the 'unpack-schema' execution to happen.
I've seen this question but it was never really answered, and the commented solution (run multiple builds) just isn't suitable for my environment. This is going to be going through continuous integration/build, so it has to compile straight up. No scripts, no multiple build passes.

It's easy, most plugins have an <skip/> configuration item, dependency plugin is no exception!
so, you can overwrite the pom of common-code with <skip/>to disable a certain execution! for example:
<execution>
<id>unpack-schema</id>
<phase>generate-sources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
</execution>
BTW: a tip for you: for multi-module projects, a plugin configured at parent pom.xml will run on all sub-modules, unless you disable it on sub-module's pom.xml with !
Good Luck!

Related

Maven NAR plugin + Spring boot in webapp, loading .nar artifact in Tomcat

I've managed to add platform dependencies to war and generated by maven-nar-plugin jni artifact into WEB-INF/lib/.
But the problem is: added artifact has .nar extension while WebappClassLoaderBase adds only .jars to its internal class repositories, so my jni bridge is not loaded and class is inaccessible leading to ClassNotFoundException.
What are my options here? I assume it's possible to
somehow change artifact extension on spring-boot:repackage?
add this custom artifact to classloader repositories?
Which would be better and how would I implement it?
Ok, so I've ended up with maven-dependency-plugin:
<build>
...
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>${dep.groupId}</groupId>
<artifactId>${dep.artifactId}</artifactId>
<version>${dep.version}</version>
<type>nar</type>
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/lib</outputDirectory>
<destFileName>${dep.artifactId}-${dep.version}.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
But still, there is a problem with redeployments to deal with, so if you realy want to do this, here is the way, but you probably don't need it that hard.

How to generate 2 jars in one java module: one is uber jar and another is non-uber jar?

I know I can achieve it via creating 2 modules, but just want to know is it possible to do tha it in one module ? Thanks
Maven Shade Plugin, if you run the shade goal, will produce two JARs by default:
your-artifact.jar — the Uber-JAR, and
original-your-artifact.jar — the original, non-Uber-JAR.
Alternatively, you can specify a different name for the Uber-JAR by using the outputFile configuration option (see below).
In this case, your "normal" JAR will have the "usual" name.
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<outputFile>${project.build.directory}/uberjar-name.jar</outputFile>
</configuration>
</plugin>
With this configuration, the results will be:
your-artifact.jar — the original, non-Uber-JAR, and
uberjar-name.jar — the Uber-JAR.

Specifying destination for dependencies in a Maven project

In trying to see if this solution will work for my project, How to share Persistence.xml between ejb module and web module in EAR?
I cannot figure out how Maven determines where it packages files in the output.
In my web project it places dependencies in /WEB-INF/lib. This is the right place, but I don't see it specified.
In my ear project it places dependencies in /. This is also the right place, but I also don't see it specified or know how to override it.
I would like my web, ejb, and other dependencies in my ear project to continue to go to /, but I'd like my jpa/domain jar to be placed in /lib.
I tried:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>my.group.org</groupId>
<artifactId>myJpaProject</artifactId>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</artifactItem>
</artifactItems>
<!-- other configurations here -->
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
But this put the jar in /target/lib/myJpaProject.jar while leaving it at / inside the ear file.
I hope that what I'm missing is obvious, but I just can't seem to find it readily in tutorials or documentation.
The specific solution for putting shared libraries in the ear file under /lib is to set the defaultLibBundleDir tag for the maven-ear-plugin. It will place any dependencies of <type>jar</type> in the ear file's /lib directory.
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<defaultLibBundleDir>lib/</defaultLibBundleDir>
…
</plugin>

How to create a jar with dependencies as main build artifact, later used by assembly plugin?

I've been working on a Java Maven project that ultimately creates an executable jar file. At first I had no issues, but then I decided I wanted the dependencies to be copied into the jar as well.
I found the following (very helpful) stack overflow question and followed the instructions provided in the answer (substituting my own main class and target version): Problem building executable jar with maven
This worked wonderfully, but I end up with two jar files (ldap-daemon-0.0.1-SNAPSHOT.jar and ldap-daemon-0.0.1-SNAPSHOT-jar-with-dependencies.jar). I'd be ok with this, but as far as I can tell I can't actually get a copy of the jar with dependencies later using the maven-dependency-plugin's copy functionality.
So, what I want to know is how to accomplish one of the following:
Have my main build artifact, ldap-daemon-0.0.1-SNAPSHOT.jar, contain its dependencies
Use the maven-dependency-plugin to copy the second build artifact (ldap-daemon-0.0.1-SNAPSHOT-jar-with-dependencies.jar).
Here is my plugin configuration for the ldap-daemon (packaging configuration is "jar"):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.acuitus.ldapd.LDAPDaemonImp</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>6</source>
<target>6</target>
</configuration>
</plugin>
And here is my plugin configuration attempting to copy the resulting jar into a folder in a downstream project:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.acuitus</groupId>
<artifactId>ldap-daemon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/classes/www-export</outputDirectory>
<destFileName>ldap-daemon.jar</destFileName>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/wars</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
Any assistance is greatly appreciated. Thanks for your time!
Like you already know the assembly plugin generate two jar files the normal one and one with all dependencies. Maven uses the classifier construct for artefacts build from the same pom but differing in there content, for example one for jdk1.6 or jdk1.7. Or a more common example is the source code jar file from maven. This construct is also used by the assembly plugin. Your copy config looks like this:
<artifactItem>
<groupId>com.acuitus</groupId>
<artifactId>ldap-daemon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/classes/www-export</outputDirectory>
<destFileName>ldap-daemon.jar</destFileName>
</artifactItem>
So you tell maven to copy the normal jar file without the dependencies.
However the jar file you want is the ldap-daemon-0.0.1-SNAPSHOT-jar-with-dependencies.jar. So you need to specify the classifier so maven is able to fetch the correct jar file:
<artifactItem>
<groupId>com.acuitus</groupId>
<artifactId>ldap-daemon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>jar</type>
<classifier>jar-with-dependencies</classifier>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/classes/www-export</outputDirectory>
<destFileName>ldap-daemon.jar</destFileName>
</artifactItem>
I still recommend to have a look also at maven-shade-plugin when you need more control over the generated jar files and classifier used.

How do I specify a dependency rule in Maven between files of certain suffixes?

I have a Java program that generates Java classes for my application.
Basically it takes in a simple spec for a class and generates a specialized
form of Java bean. I want to integrate this into my Maven pom.xml so
that if the input file is changed, Maven automatically generates the
new .java file before the compile phase of Maven.
I know how to do this trivially in make but I didn't find anything
in the Maven doc with this functionality.
You didn't provide much details on your code generation process but you could maybe simply invoke the code generator with the exec-maven-plugin (see the Examples section). The convention is to generate sources in ${project.build.directory}/generated-sources/<tool>. Then add the generated sources with the build-helper-plugin and its add-sources mojo. Bind every thing on the generate-sources phase.
I'll just show the build-helper stuff below:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-mytool-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/mytool</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
You could also write a simple plugin to wrap your generator. In that case, have a look at the Guide to generating sources.
PS: I may have missed something, there is a kind of mismatch between my answer and the title of your question.
Maven have phase "generate-sources" for this

Categories

Resources