How to add a dependency into a lib directory of a jar using maven? - maven

I have a jar that contains map/reduce code for hadoop. It needs a dependency, which I need to put into the jar's lib directory so that the jar is self contained and can work in hadoop.
This is what I did in my pom:
1) add maven-dependency-plugin to copy the libs that I need into the target/lib folder
2) configure the jar plugin to take the libs in the target/lib folder, and add it into the generated jar.
I am just unable to get this to work. The generated jar does not contain the extra libs.
I also tried adding the target/lib directory to the / tag in the pom, and that didnt work either.
Here is my pom, annotated....
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>copy apache-httpcomponents</id>
<phase>process-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeTypes>jar</includeTypes>
<includeGroupIds>org.apache.httpcomponents</includeGroupIds>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<stripVersion>false</stripVersion>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>add lib directory to jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>jar</classifier>
<includes>
<include>${project.build.outputDirectory/lib/**</include>
<include>${project.build.outputDirectory/target/**</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Any help appreciated!

It looks like you left off the closing bracket in your include.
Add a bracket here: ${project.build.outputDirectory/lib after outputDirectory, and in the same place on the next line as well.
And I think it should be ${project.build.directory}/lib instead of ${project.build.outputDirectory}/lib because project.build.directory by default is the target folder

Related

Generate Javadoc for multimodule project

I have read everything I can find on solving this and my attempts still fail. The best I can do is to get the Javadoc of exactly one module to show up--the last one built. (For now, I'm not trying to bundle Javadoc into any JARs. I'm also not trying to do anything "site".) I just want to put Javadoc for easy access into a subdirectory under the project root.
Here's what's in my parent pom.xml:
<build>
<plugins>
.
.
.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<noqualifier>all</noqualifier>
<reportOutputDirectory>${user.dir}/documents</reportOutputDirectory>
<destDir>javadoc</destDir>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
What I'm putting into subordinate pom.xml files is identical to the above except for
<goals>
<goal>javadoc</goal>
</goals>
I have played with replacing the <execution> in the parent and sometimes subordinate pom.xml files with:
<execution>
<id>aggregate</id>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
but it makes no difference.
I think the following configuration is the reason your reports get overwritten:
<configuration>
<reportOutputDirectory>${user.dir}/documents</reportOutputDirectory>
</configuration>
All module builds will be written to the same directory, hence overwriting the previous build.
The solution is to use the default output directory and configure the output directory for the aggregated javadoc instead. This way the reactor build will create javadoc output files in each module's target directory. These can then be used by the aggregate goal to be combined.
This can be done by configuring your parent POM as follows:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<!-- Default configuration for all reports -->
<noqualifier>all</noqualifier>
<destDir>javadoc</destDir>
</configuration>
<executions>
<execution>
<id>aggregate</id>
<goals>
<goal>aggregate</goal>
</goals>
<configuration>
<!-- Specific configuration for the aggregate report -->
<reportOutputDirectory>${user.dir}/documents</reportOutputDirectory>
<destDir>javadoc</destDir>
</configuration>
</execution>
...
</executions>
</plugin>
...
</plugins>
</build>
(there is no need for any additional configuration in the module POM files)
The aggregated javadoc can now be created by running
mvn compile javadoc:javadoc javadoc:aggregate
(note that the compile or package goal is required for reactor to resolve inter-module dependencies)

How do I create an uber source jar with Maven?

Is there a well-known way to create an uber source jar? In other words, a jar of all the source code for a project and all its dependencies (or at least those that have a -sources.jar)?
I've looked into doing it with the maven-assembly-plugin, but using a dependencySet with includes of *.*.*.sources.* (or *.sources) doesn't work because those are not actually dependencies of the project, and I don't want to add them all.
You can use the maven-shade-plugin to create an uber jar. Just include the following within your <build> tag -
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>source-jar</id>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createSourcesJar>true</createSourcesJar>
<artifactSet>
<includes>
<include>...</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
To modify the configuration, you can use Resource Transformers within org.apache.maven.plugins.shade.resource package.
And to define the contents of the jar, you can further use includes and excludes within the filters.
I found some information on working with sources in the maven-dependency-plugin.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>src-dependencies</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<classifier>sources</classifier>
<failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
<outputDirectory>${project.build.directory}/sources</outputDirectory>
<includeGroupIds>{your group prefix}</includeGroupIds>
<includes>**/*.java</includes>
<includeScope>runtime</includeScope>
</configuration>
</execution>
So if I do that, and then run a maven-assembly-plugin referencing the unpacked files, I can do it in two steps.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<execution>
<id>uber-source</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>ubersource.xml</descriptor>
</descriptors>
<outputDirectory>${deploy.internal.directory}</outputDirectory>
<finalName>${project.artifactId}</finalName>
</configuration>
</execution>
</executions>
</plugin>
with a file set in the assembly descriptor ubsersource.xml:
<fileSet>
<directory>${project.build.directory}/sources</directory>
<outputDirectory>.</outputDirectory>
</fileSet>
And then I get my uber source jar...
There is perhaps a subtle distinction in the way the maven-assembly-plugin and maven-dependency-plugin treats sources. If you reference classifier sources in a dependencySet of an assembly descriptor, it looks for sources that are actual dependencies in your pom -- not that useful. However, in maven-dependency-plugin, referencing sources classifier means that sources of your dependencies. Hence why this solution works.
I also wrapped this up in my own plugin using mojo-executor to make it single step, and single declaration in my pom, but that's optional
This is a lot more pom code, but I like it better than the maven-shade-plugin because it does just what I want, and nothing more.

include package in maven while preparing jar

I have below project structure. I wanted to prepare a jar with dependencies including different packages which has .java files.
Project Structure:
src/com/rev/automation/utilities
src/com/rev/automation/testdata
src/com/rev/automation/pages
Main Class:
org.openqa.selenium.remote
How to include "src/com/rev/automation" packages into the jar in maven? i'm preparing the jar using below code, But it is not including packages and files present in "src/com/rev/automation". Kindly suggest
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<!-- get all project dependencies -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- MainClass in mainfest make a executable jar -->
<archive>
<manifest>
<mainClass>org.openqa.selenium.remote.RemoteWElement</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
While using Maven, you need to follow the Maven Standard Directory Structure.
In your case, create a folder structure like src/main/java and put all your code in java directory. So it should now look like src/main/java/com/rev/automation etc.
If you follow this structure, then your package will get included in the jar.
Update:
If you absolutely don't want to / cannot do what is mentioned above, alternatively, you can use the Maven Build Helper plugin. This will tell maven to include the specified directory as an additional source directory.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src</source> // specify your directory here
...
</sources>
</configuration>
</execution>
</executions>
</plugin>

How to resolve dependency between files generated by maven plugin at compile time?

Ok, let me try to put my problem across as less confusing as I can.
I have a standard maven project with a few Maven plugins -
1) maven-antrun-plugin
2) Custom maven plugin, say, my-maven-plugin
3) jaxws-maven-plugin
Now here's the complicated part.
The 1st plugin generates a few .java files which I'm currently placing in "${project.build.directory}/java"
The 2nd plugin generates another set of .java files all of which I'm placing again under "${project.build.directory}/java". However, they're placed under different package structures.
Both of these plugins run during the "generate-sources" phase.
Now my 3rd plugin, jaxws-maven-plugin, tries to use the class files for the files generated by 1st and 2nd plugins, as the SEI to generate WSDLs. But the class files won't be created by maven at that point during the compilation and the plugin errors out with a "Class Not found" message.
So how do I go about trying to resolve this? Also, since I error out during the "generate-sources" phase, I don't see the .class files for any of the other source files from my project in the target/classes directory.
And oh, here's another twist. Some of my source files import these compile time generated source files in the code (You have no idea how badly I'm searching for this developer right now!!)
I have tried to describe my problem in the best possible way so please feel free to ask any other details or clarifications.
Run manually build-helper-maven-plugin and maven-compile-plugin before jaxws-maven-plugin:
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
...
<executions>
<execution>
<phase>generate-sources</phase>
</execution>
...
</executions>
<plugin>
<plugin>
...
<artifactId>my-maven-plugin</artifactId>
...
<executions>
<execution>
<phase>generate-sources</phase>
</execution>
...
</executions>
<plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>some directory</source>
...
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compile-plugin</artifactId>
...
<executions>
<execution>
<phase>generate-sources</phase>
</execution>
<goals>
<goal>compile</goal>
</goals>
</executions>
<plugin>
<plugin>
<artifactId>jaxws-maven-pluginn</artifactId>
...
<plugin>
</plugins>
</build>
I haven't tested it but I think it should work.

Files got overwritten in maven project when building a war

I'm building a web application project using maven, and packaging is set to "war". I also use YUI compressor plugin to compress javascript codes in the webapp directory. I've set up the YUI compressor like this:
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>yuicompressor-maven-plugin</artifactId>
<version>1.3.0</version>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>compress</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>**/ext-2.0/**/*.js</exclude>
<exclude>**/lang/*.js</exclude>
<exclude>**/javascripts/flot/*.js</exclude>
<exclude>**/javascripts/jqplot/*.js</exclude>
</excludes>
<nosuffix>true</nosuffix>
<force>true</force>
<jswarn>false</jswarn>
</configuration>
</plugin>
If I do: mvn process-resources, src/main/webapp will get copied over to target/webapp-1.0/ directory, and javacripts are compressed. However, when I run mvn install, all the compressed javascripts are overwritten, apparently the packaging process copies the content from main/webapp one time before building the war file.
How can I get around this?
As you noticed, the /src/main/webapp dir (aka warSourceDirectory) contents is not copied into the project dir for packaging until the war plugin executes during the package phase. When the war plugin completes the archive is already built; too late to modify those resources. If the .js files you want to compress were moved into another directory (outside of /src/main/webapp) then you could do something like the below.
To test, I created a ${basedir}/src/play directory with a couple of files in it. I used the resource plugin for the example; you'd replace that config with the YUI compressor plugin config you needed and simply add the <webResource> element to your war plugin config as shown below; more info in the war plugin examples. My war ended up with the additional files right where I wanted them.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-resources</phase>
<goals><goal>copy-resources</goal></goals>
<configuration>
<outputDirectory>${project.build.directory}/tmpPlay</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/play</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<executions>
<execution>
<id>default-war</id>
<configuration>
<webResources>
<resource>
<directory>${project.build.directory}/tmpPlay</directory>
<targetPath>WEB-INF/yourLocationHere</targetPath>
<includes>
<include>**/*</include>
</includes>
</resource>
</webResources>
</configuration>
</execution>
</executions>
</plugin>
I think #user944849 answer is the correct answer, at least one of the correct answers. Another way of archiving this is to exclude the modified javascript directory from maven-war-plugin configuration, e.g.:
<plugin>
<artifactId> maven-war-plugin </artifactId>
<configuration>
<warSourceExcludes>**/external/ dojo/**/*.js </warSourceExcludes>
</configuration>
</plugin>
this will tell maven-war-plugin not to copy from the excluded directory, but since the modified javascript directory is already there, the war file still contains the javascript directory, BUT with the modified, in this case, compressed javascript codes.
in your execution directive, set the phase for applying your compression and copying to be install and that will hopefully do the trick. the code should be something like this:
<executions>
<execution>
....
<phase>install</phase>
....
</execution>
<executions>
Here is my solution, simply add an antrun plugin which updates the packaged war file using the processed outputs, which binds to the package phase:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>package</id>
<phase>package</phase>
<configuration>
<target>
<zip basedir="${project.build.directory}/${project.build.finalName}"
destfile="${project.build.directory}/${project.build.finalName}.war"
update="true">
</zip>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

Resources