Maven compile a source jar dependency - maven

Let's say I have a project that uses a dependency that can be found in the Maven repository. However, lets also say that the jar file that will be downloaded is NOT in a format that is suitable for my project (e.g. if my maven project is an Android project and the jar has been compiled in a way the dex tool does not like). What I want to do instead is to downloaded the source version of that dependency. Once I add java-source, however, the classes are not accessible anymore from my own source code. I would like that maven downloads the source jar and compiles the java files inside it and places the compiled class files in the classpath. Is that possible?
My only alternative is to create a new project containing that library myself, but that's cumbersome.

You could do the following:
Use maven dependency plugin's unpack goal and place the contents of the dependency into a folder
Use build-helper-maven-plugin's add-source goal to add this folder as a source folder
Here is some code snippet...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>unpack</id>
<phase>process-sources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>my.group</groupId>
<artifactId>my.artifact</artifactId>
<version>my.artifact.version</version>
<classifier>sources</classifier>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/my.artifact</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/my.artifact.source</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>

Downloading the source packages using Maven is easy:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<classifier>sources</classifier>
</dependency>
How to configure Maven to expand this dependency and then compile it's contents is beyond me....
Have you considered an ANT solution? The ivy plug-in provides it with Maven-like abilities and the groovy plug-in can be used to script your special build logic:
build.xml
Ivy uses "configurations" (similar to Maven scopes) to group dependencies.
In this example the "sources" configuration holds the downloaded source packages. These are placed into a referenced fileset, which can be processed sequentially by the groovy task.
Each downloaded source jar is unzipped into the "build/src" directory:
<project name="demo" default="unzip-sources" xmlns:ivy="antlib:org.apache.ivy.ant">
<property name="build.dir" location="build"/>
<property name="src.dir" location="${build.dir}/src"/>
<target name="resolve">
<ivy:resolve/>
<ivy:cachepath pathid="build.path" conf="build"/>
<ivy:cachefileset setid="sourcezips" conf="sources"/>
</target>
<target name="unzip-sources" depends="resolve">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<groovy>
project.references.sourcezips.each {
ant.unzip(src: it, dest: properties["src.dir"])
}
</groovy>
</target>
<target name="clean">
<delete dir="${build.dir}"/>
</target>
</project>
ivy.xml
Each source package dependency uses the "sources" configuration. This maps directly to the "sources" scope of the Maven module.
<ivy-module version="2.0">
<info organisation="org.myspotontheweb" module="demo"/>
<configurations>
<conf name="build" description="ANT tasks"/>
<conf name="sources" description="Source packages"/>
</configurations>
<dependencies>
<!-- Build dependencies -->
<dependency org="org.codehaus.groovy" name="groovy-all" rev="1.8.2" conf="build->default"/>
<!-- Source dependencies -->
<dependency org="log4j" name="log4j" rev="1.2.16" conf="sources"/>
<dependency org="commons-lang" name="commons-lang" rev="2.6" conf="sources"/>
</dependencies>
</ivy-module>

Related

Maven Assembly Plugin jar-with-dependencies -> No Dependencies in Jar

The following reference mentions the descriptor Reference jar-with-dependencies. Afaik it is a predefined assembly, which includes all jar dependencies into a single big self-contained jar file. This is great if you have multiple dependencies and need to copy your project to another machine because you don't need to update/delete obsolete libraries separately.
https://newfivefour.com/category_maven-assembly.html
I added the maven-assembly-plugin to my pom, and the MyTool.jar-with-dependency.jar is created. I expected that the jar contains all external dependencies, but it is the same as the normal MyTool.jar and does not contain any dependencies like apache.commons or apache.logging.
The important detail is that the dependencies scope is set to provided. Without this it works as expected. But I use the scope later on with the maven-dependency-plugin to copy all dependencies in the provided scope to a specific directory.
[...]
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.5</version>
<scope>privided</scope>
</dependency>
</dependencies>
<build>
<!--pluginManagement-->
<plugins>
<plugin> <!-- This is the plugin I added. -->
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
[...]
I use Apache Maven 2.2.1 (rdebian-14).
How can I include the dependencies from the provided scope? Or is there an other solution?

Axis wsdl2java maven plugin with xmlbeans doesn't include resources folder

I'm using axis2 to re-generate the client code for an updated webservice that I need to use, for a legacy application.
Being a legacy application I would like to avoid changing the code that has been already written, and re-generate the classes as they were generated who-know-how-many years ago by the eclipse plugin, but this time using maven instead of eclipse.
So I seen that they were generated using axis2 and xmlbeans, and I produced the configuration in the maven plugin:
<plugin>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-wsdl2code-maven-plugin</artifactId>
<version>1.5.6</version>
<executions>
<execution>
<id>TheirsWs</id>
<goals>
<goal>wsdl2code</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<packageName>it.theirs.ws</packageName>
<wsdlFile>${basedir}/src/main/resources/theirWs.wsdl</wsdlFile>
<generateServerSide>false</generateServerSide>
<databindingName>xmlbeans</databindingName>
<unpackClasses>true</unpackClasses>
</configuration>
</execution>
</executions>
</plugin>
What happen now is a very nice thing.
The plugin generate a .class file in the generated-sources / axis2 / wsdl2code / resource folder, However it is not added by maven to the final package, causing a ClassNotFoundException when calling the webservice.
I solve the problem by adding the resource folder into the JAR using the maven default feature of including and excluding folder. The solution for your case will be:
<build>
<!-- This will the MAVEN to copy the entire folder, you can copy only the .class files -->
<resources>
<resource>
<directory>${project.build.directory}/generated-src/resources</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
<plugin>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-wsdl2code-maven-plugin</artifactId>
<version>1.5.6</version>
<executions>
<execution>
<id>TheirsWs</id>
<goals>
<goal>wsdl2code</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<packageName>it.theirs.ws</packageName>
<wsdlFile>${basedir}/src/main/resources/theirWs.wsdl</wsdlFile>
<generateServerSide>false</generateServerSide>
<databindingName>xmlbeans</databindingName>
<!-- I add this line just to be easy to referenciate the souce -->
<outputDirectory>${project.build.directory}/generated-src</outputDirectory>
<unpackClasses>true</unpackClasses>
</configuration>
</execution>
</executions>
</plugin>
Had the same problem, i changed the Ant build.xml buildfile from:
<target depends="pre.compile.test" name="compile.src" if="jars.ok">
<javac debug="on" memoryMaximumSize="256m" memoryInitialSize="256m" fork="true" destdir="${classes}" srcdir="${src}">
<classpath refid="axis2.class.path"/>
</javac>
</target>
To:
<target depends="pre.compile.test" name="compile.src" if="jars.ok">
<javac debug="on" memoryMaximumSize="256m" memoryInitialSize="256m" fork="true" destdir="${classes}" srcdir="${src}">
<classpath refid="axis2.class.path"/>
</javac>
<copy todir="${classes}">
<fileset dir="${resources}"/>
</copy>
</target>
The new Copy task add all the resources to the target classes folder so the generated Jar will include them.
Hope it helps.

Wrapping Ant in Maven - JAVA_HOME points to the JRE but works with just Ant

I have an Ant project that builds just fine on its own. I'm now trying to wrap it in a Maven build that will kick off the Ant build using maven-antrun-plugin. When I do this the build fails and I get this error,
[ERROR] C:\Users\bobby\workspace\libraries\build-targets\common-targets.xml:170: Unable to find a javac compiler;
[ERROR] com.sun.tools.javac.Main is not on the classpath.
[ERROR] Perhaps JAVA_HOME does not point to the JDK.
[ERROR] It is currently set to "C:\Java\jdk1.8.0_65\jre"
There are a lot of SOF posts on this error but I feel like mine is unique since it only happens when I'm wrapping the Ant build in Maven i.e., I do not get this error on the same project when I just say $ ant build.
This is part of my pom.xml file
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<tasks>
<ant antfile="build.xml" target="build" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>add-jar</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>build/bin/myWarFile.war</file>
<type>war</type>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
My JAVA_HOME Environment Variable is set to C:\Java\jdk1.8.0_65.
The file that is mentioned in the error is from a library my work maintains where we keep all of our Jars. In that file here is what's on line 170
<target name="compile-src">
<!-- Compile source -->
<javac srcdir="${java.src.dir}"
destdir="${class.dir}"
debug="${debug.flag}"
deprecation="${deprecation.flag}"
nowarn="${warnings.flag}"
optimize="off"
source="${source.value}">
<classpath refid="compile.classpath"/>
</javac>
</target>
The line with source= is line 170.
It's a common issue. Try with this configuration:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
...
<!-- Add this dependency to your ant-run configuration -->
<dependencies>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.5.0</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
...
</plugin>
Maven uses Java's system property java.home, which is not the same as the environment variable JAVA_HOME, but it is using it to compute its java.home by tacking on the jre sub-directory, as witnessed. Consequently, stuff needed by Ant is simply not available in the jre directory.
However, this configuration ensures that Ant's plugin dependencies are correctly satisfied.
You need to point to JDK not JRE. Just remove ire and try.
It is currently set to "C:\Java\jdk1.8.0_65\jre"
And if your JDK is set - another workaround - Can you copy tools.jar from jdk lib to jre lib and see if it works.

How to embed a library JAR in an OSGi bundle using Tycho

I am using Maven with the Tycho plugin to build my OSGi bundles.
In one of my bundles, I use the facebook API through the restfb-1.7.0.jar library.
For now, it is directly placed on the classpath (in Eclipse) and embedded in the effective OSGi bundle jar file with following build.properties configuration:
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
lib/restfb-1.7.0.jar
Now I would like to have this restfb lib downloaded from Maven (e.g. as dependency) and embedded into my OSGi bundle jar. Is it possible with Maven/Tycho? How?
You need the following configuration to embed a JAR into an OSGi plugin with Tycho:
In the pom.xml, configure the copy goal of the maven-dependency-plugin
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>copy-libraries</id>
<phase>validate</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<item>
<groupId>com.restfb</groupId>
<artifactId>restfb</artifactId>
<version>1.7.0</version>
</item>
</artifactItems>
<outputDirectory>lib</outputDirectory>
<stripVersion>true</stripVersion>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Edit the MANIFEST.MF to have the library added to the OSGi bundle classpath
Bundle-ClassPath: ., lib/restfb.jar
Edit the build.properties to have the library included in the JAR packaged by Tycho
bin.includes = META-INF/,\
.,\
lib/restfb.jar
I think what you would want is to have a dependency in the POM with the compile time scope like the example below: use the correct artifact and version info to get the item you want. you should investigate the dependencies section of the maven ref for poms
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>compile</scope>
</dependency>

Ivy project can't get the latest Maven snapshot (with assembly plugin)

When a Ivy project depends a maven project (using assembly plugin), there will be problems. For example:
Maven project:
Suppose the maven project will deploy 2 snapshot packages: for exmaple, one is my-app-1.0.0-20130504.000602-1.jar and the other is my-app-1.0.0-20130504.001348-1-myzip.zip. The pom.xml is shown below.
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0.0-SNAPSHOT</version>
<... ...>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.7</version>
<configuration>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<packaging>zip</packaging>
<file>my-app-1.01-myzip.zip</file>
</configuration>
</plugin>
</plugins>
</build>
</project>
The Ivy project
The Ivy project depends on the 2 artifacts published by above maven project. The ivy.xml is shown below:
<configurations>
<conf name="get-maven" />
</configurations>
<dependencies>
<dependency org="com.mycompany.app" name="my-app" rev="1.0.0-SNAPSHOT" changing="true" conf="get-maven->default">
<artifact name="my-app" ext="jar" type="jar"></artifact>
<artifact name="my-app" ext="zip" type="zip" m:classifier="myzip"></artifact>
</dependency>
</dependencies>
Issues:
Each time when the maven project deploy new snapshot to the artifactory server, the ivy project can retrieve the latest my-app-xxx.jar from the artifacory server but it can't retrieve the latest my-app-xxx-myzip.zip (ivy can't get to know that the zip is updated and just retrieve the zip from local cache).
What I have to do is to delete the local cache, and run the ivy project again.
I did some investigation, and found the ivy task "convertpom" didn't convert the app-xxx-myzip.zip from pom to ivy, and only 1 artifact (the my-app-xxx.jar) can be found in the converted ivy.xml. Not sure if this is the root cause.
Can anyone help on this? How can I get the lastet snapshots for both artifacts in ivy project?
Regards,
Alben
So to clarify, you're attempting to configure ivy to pull down a snapshot dependency published by a Maven project?
In that case, the following answer will help to explain:
What's wrong with this Ivy changingPattern / SNAPSHOT configuration?

Resources