repackage dependencies and fix pom - java

My maven project has a dependency. I use a few 3rd party classes. I would like to automatically repack them into my jar and exclude the dependency from pom.xml stored in jar file.
i checked shade plugin and jarjar plugin. none of them replaces pom in produced jar. what's the point of including dependencies' binaries if those dependencies are still listed in pom? how should i properly repack dependencies?

Maven shade plugin has the feature you need. After running
mvn shade:shade
It generates file named dependency-reduced-pom.xml in your projects folder, and this file doesn't have dependencies which are already placed in jar.
This behaviour is configured via following shade-plugin options:
createDependencyReducedPom
dependencyReducedPomLocation

You can use the maven-dependency-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id></id>
<phase>process-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
<includes>org\/apache\/commons\/lang\/StringUtils.class</includes>
</configuration>
</execution>
</plugin>
And then set the dependency scope of commons-lang to provided:
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
<scope>provided</scope>
</dependency>
commons-lang will not be carried as a transitive dependency nor be included in the jar packaging, but StringUtils will be included in the jar.

Related

Maven system scope dependency does not copy source jar to build target jar

I am in the situation right now, where I can not put a compiled jar into our custom maven repository. Our repository is configured in my maven config. What I am trying to achieve is to use the local compiled jar file of the dependency as a replacement for the checked out file from our file server.
<dependency>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<scope>system</scope>
<systemPath>*filepath*</systemPath>
</dependency>
This will find the file and compile my jar, but it will not copy the dependency into the lib directory inside the compiled jar, meaning my application can not run. Is there any way to link a local jar file and make it actually appear in the resulting jar files "lib" directory?
You may use the copy-rename-maven-plugin.
<build>
<!-- ... -->
<plugins>
<plugin>
<groupId>com.coderplus.maven.plugins</groupId>
<artifactId>copy-rename-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>copy-my-jar</id>
<phase>process-classes</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<sourceFile>*filepath*</sourceFile>
<destinationFile>${project.build.outputDirectory}/lib/my.jar</destinationFile>
</configuration>
</execution>
<executions>
</plugin>
</plugins>
</build>

how to set classpath properly in maven-javadoc-plugin?

I had a customized java doclet, it will call newInstance() on some classes:
clazz.newInstance()
When I ran it in Eclipse as Junit, it works well.
But When I ran it in maven , it throws an exception: NoClassDefFoundError
I checked that class, it is not in my current project, it is inside a maven dependency (third party jar).
I knew I can set classpath in maven-javadoc-plugin. But my project has more than 50 third party jars. How can I set those jars easily?
This is my code in maven pom:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.0-M1</version>
<configuration>
<doclet>my.company.common.doclet.MyDoclet</doclet>
<docletPath>${project.build.directory}/../../shared-java/target/classes;${project.build.directory}/classes</docletPath>
<sourcePath>${project.build.directory}/../../shared-java/src/java;${project.build.directory}/../src/java</sourcePath>
<encoding>UTF-8</encoding>
<show>public</show>
<subpackages>my.company.api</subpackages>
<useStandardDocletOptions>false</useStandardDocletOptions>
<docletArtifacts>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</docletArtifacts>
</configuration>
<executions>
<execution>
<id>attach-javadoc</id>
<phase>post-integration-test</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
Thanks!
What if adding them with the help of <additionalDependencies>?
<configuration>
...
<additionalDependencies>
<additionalDependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</additionalDependency>
</additionalDependencies>
...
</configuration>
See: https://maven.apache.org/plugins/maven-javadoc-plugin/examples/additional-dependencies.html
I found the maven-javadoc-plugin do pass the whole classpath to my doclet.
But the doclet ClassLoader.getSystemClassLoader() didn't use that classpath.
So I have to manually add those classpath into the current classLoader.
In Eclipse, it will automatically set those classpath.

Libraries not included in javaFX jar

I have built a javaFX application using Maven.The problem is that the javaFX jar file generated from maven, doesn't contain dependencies included.
I have included the javaFx dependency this way :
<dependency>
<groupId>com.oracle</groupId>
<artifactId>javafx</artifactId>
<version>8.0.151</version>
<scope>system</scope>
<systemPath>C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\jfxrt.jar</systemPath>
</dependency>
I have also included the javaFx plugin :
<plugin>
<groupId>com.zenjava</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>${javafx.plugin.version}</version>
<configuration>
<vendor>Vendor</vendor>
<mainClass>org.bsh.generator.App</mainClass>
<jarFileName>CSVGenerator</jarFileName>
</configuration>
<executions>
<execution>
<id>create-jfxjar</id>
<phase>package</phase>
<goals>
<goal>build-jar</goal>
</goals>
</execution>
</executions>
</plugin>
When I build the jar using goal "build-jar", the jar generated doesn't include other dependencies. Any help please?
Dependencies scoped as system are not respected, this is intentional. Only provided and runtime scoped dependencies/libraries are respected by the plugin.
Disclaimer: I'm the maintainer of the javafx-maven-plugin.

Duplicate classes when using Maven AspectJ weave dependencies

We are using the Maven AspectJ plugin to build our web application. It makes use of "weaveDependencies" to add aspects to some dependency jar files.
Now we end up with two versions of some classes in the web application archive, one in WEB-INF/classes and one in the original jar file in WEB-INF/lib. It seems that only the one in classes has the aspects.
I am afraid that this can cause problems.
What is the best way to fix this?
The same problem is discussed (without solution) over at the Eclipse forums.
The whole pom.xml itself is huge, and of course the sub-projects that are included have their own, too. I hope the extract below from the WAR project is informative enough.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
<filters>
<filter>${basedir}/src/etc/${environment}/environment.properties</filter>
</filters>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.2</version> <!-- NB: do use 1.3 or 1.3.x due to MASPECTJ-90 - wait for 1.4 -->
<dependencies>
<!-- NB: You must use Maven 2.0.9 or above or these are ignored (see
MNG-2972) -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
<weaveDependencies>
<weaveDependency>
<groupId>OURPROJECT</groupId>
<artifactId>OURPROJECT-api</artifactId>
</weaveDependency>
<weaveDependency>
<groupId>OURPROJECT</groupId>
<artifactId>OURPROJECT-service</artifactId>
</weaveDependency>
</weaveDependencies>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
In a servlet container and inside a WAR, the classes inside WEB-INF/classes always have precedence over classes with the exact same name found inside a jar in WEB-INF/lib.
This is a quote from the servlet spec:
The Web application class loader must load classes from the WEB-INF/
classes directory first, and then from library JARs in the
WEB-INF/lib directory.
This has been so since at least Servlet 2.4. This allows an application to selectively patch just a few library classes without having to repackage jars manually or via maven plugins.
In your case you can be certain that the classes with the aspects will always be taken, as they are in WEB-INF/classes and have priority over classes in WEB-INF/lib.

How to prevent maven from duplicating jars in an EAR file?

I have an EAR file built by maven and currently I have a commons project which I'd like to put in an EAR\lib, so I used the maven-ear-plugin with the 'bundleDir' tag which works fine, only that now my commons.jar appears in both the lib folder and the EAR root. How do I tell it to put it only in the lib folder?
My pom:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<outputDirectory>../../outputs/java</outputDirectory>
<version>5</version>
<modules>
<jarModule>
<groupId>com.sample.common</groupId>
<artifactId>common</artifactId>
<includeInApplicationXml>
true
</includeInApplicationXml>
<bundleDir>/lib</bundleDir>
</jarModule>
...
</modules>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>ear</goal>
</goals>
</execution>
</executions>
</plugin>
And here is the dependency definition:
<dependency>
<groupId>com.sample.common</groupId>
<artifactId>common</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
If your jar file is not ejb you can simply put it to ear dependency without definition into maven-ear-plugin. Otherwise try to setup scope provided to your jar inside the dependency list. This may help.

Categories

Resources