We have an Eclipse Plugin which we build using Maven and Tycho. Currently
however, we still provide all project dependencies through a bunch of manually
added JAR files and not by Maven. This is due to the following reasons: (1) The
dependencies are not available through a standard Eclipse update site (at least
not in a current version), (2) the dependencies are not available as bundles.
The biggest part of these dependencies are the Selenium libraries (API, Remote,
browser-specific libs and their transitive dependencies, such as Guava, etc.)
I've wasted hours, trying to pull those dependencies during our Maven build.
Following this SO question, I tried the p2-maven-plugin, created an update
site with our dependencies which I added to my Eclipse target platform. However,
during runtime, classes, which are referenced across different JARs could not be
loaded (I assume, from my very limited OSGi knowledge, because some
necessary information was missing in the MANIFEST.MF files). Here's an example
of the issue, when trying to create a RemoteWebDriver, which uses the
DesiredCapabilities class (both classes in different bundles):
Exception in thread "Thread-8" java.lang.NoClassDefFoundError: org/openqa/selenium/remote/DesiredCapabilities
at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:243)
at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:126)
at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:153)
…
Caused by: java.lang.ClassNotFoundException: org.openqa.selenium.remote.DesiredCapabilities cannot be found by org.seleniumhq.selenium.remote-driver_2.45.0
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:439)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:352)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:344)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:160)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 7 more
Is there anything I still need to take care of, when using the p2-maven-plugin? The relevant parts of the pom.xml looked like this:
<plugin>
<groupId>org.reficio</groupId>
<artifactId>p2-maven-plugin</artifactId>
<version>1.1.1-SNAPSHOT</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<artifacts>
<artifact>
<id>org.seleniumhq.selenium:selenium-remote-driver:2.45.0</id>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
Couldn't get it to work, so we're now using the maven-dependency-plugin with the copy-dependencies, which we execute during the Maven initialize phase to pull all necessary dependencies (contrary to my initial feeling, this can be combined with the pom.xml using the eclipse-plugin packaging and the "manifest first" approach). The relevant part looks like this:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>initialize</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The Maven dependencies are then copied to target/dependency.
Only little issue: The Bundle-ClassPath in the MANIFEST.MF needs to be manually updated in case the name of a JAR file changes when updating Maven dependencies (e.g. commons-io-2.4.jar becomes commons-io-2.5.jar).
[edit] Revisiting this answer in regards to the last sentence above: The version numbers can be conveniently stripped through the following option: <stripVersion>true</stripVersion>. This means, the above library will be renamed to commons-io.jar and thus no paths need to be updated when a version number changes.
Another possibility:
Some jar files may be broken (if you're using Eclipse, it's commonplace hibernate-commons-annotations-4.0.1.Final.jar; invalid LOC header (bad signature)? ). To check this possibility, try manually opening the jar to see if it's okay.
I also build an Eclipse plugin with Maven and Tycho. I have the same problem: the bundle org.eclipse.team.svn.core and org.eclipse.team.svn.ui are not available through a standard Eclipse update site.
Maybe you can try this to solve this kind of problem:
In Dependencies, find the box Automated Management of
Dependencies.
Add the wanted plugin using Add...
Choose Analyze code and add dependencies to the MANIFEST.MF via: Import-Package
Click on Add Dependencies so that you find required packages in the box Imported Packages nearby.
Then you can run the Maven build.
Related
Background:
I am working on a open source tool called draw.io which is based on ANT build system and uses Java servelets to handle request. I am supposed to migrate it to spring boot with using same front end files. I put those files in static folder and tried to build the project. I figured that the front end js files were not getting build (i.e. were not getting converted to app.min.js, which is the main entry point for front end files), in the process and none of the js changes were getting reflected in the file.
I figured that this process was mentioned in build.xml as part of various steps which is ANT specific configuration. Now, I have to achieve the same in maven as the migration process.
How do we convert build.xml to maven or what is the maven alternative of achieving the tasks mentioned in the build.xml as part of build process?
This is the high level view of build.xml:->
I am also providing the link of build.xml here...
Please provide me with some direction.
Before migrating to maven, I hope you understand why you are moving to maven from ant.
You should try for finding alternative plugins for the relevant ant task. The below plugin might do what you are trying to achieve in ant
<plugin>
<groupId>com.github.blutorange</groupId>
<artifactId>closure-compiler-maven-plugin</artifactId>
<version>2.16.0</version>
<configuration>
<!-- Base configuration for all executions (bundles) -->
<baseSourceDir>${project.basedir}/src/main/resources</baseSourceDir>
<baseTargetDir>${project.build.directory}/generated-resources</baseTargetDir>
</configuration>
<executions>
<!-- Process all files in the "includes" directory individually-->
<execution>
<id>default-minify</id>
<configuration>
<encoding>UTF-8</encoding>
<sourceDir>includes</sourceDir>
<targetDir>includes</targetDir>
<includes>**/*.js</includes>
<skipMerge>true</skipMerge>
<closureLanguageOut>ECMASCRIPT5</closureLanguageOut>
</configuration>
<goals>
<goal>minify</goal>
</goals>
<phase>generate-resources</phase>
</execution>
</executions>
</plugin>
More details about the plugin : closure-compiler-maven-plugin
There are few cases during my ant to maven migration, I came across some custom tasks which I was not able to find appropriate plugins.
I used maven-antrun-plugin which keeps existing ant tasks in maven.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
...
</executions>
</plugin>
More details about how to use the maven antrun plugin : See this
tutorial
For Maven, you need a pom.xml. There you need to define and configure the plugins you need. If you have a specific procedure written in Ant that you want to reuse, you can call it with the Maven Antrun Plugin.
Generally, Maven is very different from Ant. You don't write procedural code, but configure plugins running in a lifecycle.
I am having a problem with maven. I have included a dependency as such in my pom.xml:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.6</version>
</dependency>
I am using Intellij as an IDE, and I get no compile warnings there or anything. I am using the command line to run the maven commands, and I can run mvn install compile package all without trouble.
However, when I try running the jar as such:
java -cp target/stride-1.0-SNAPSHOT.jar com.myapp.maven.App
I get this error:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/csv/CSVFormat
at com.stride.maven.App.parseCsv(App.java:43)
at com.stride.maven.App.main(App.java:25)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.csv.CSVFormat
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
Clearly, maven cannot find that path. I tried deleting the .m2, rebuilding, and mostly everything I have found on stackoverflow, but I cannot find the issue, or get visibility into the issue. Note, in my Intellij I can see the dependency in the external libraries.
I have also tried using shade to copy the dependancies to the jar:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<transformers>
<transformer implementation=
"org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.myapp.maven.App</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
Following which I reran mvn clean install package and then my build command. No luck.
I have also tried Maven Assembly plugin. Guess what, no luck!
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>
com.myapp.maven.App
</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
I confirmed the dependencies are not even getting built in.
Thanks!
Maven works great in this case.
However, you seem to miss the point of dependency.
When you define a dependency maven uses it during the compilation (hence no errors in both intelliJ and when you execute mvn install)
But this doesn't mean that dependency is placed right into the jar.
There are more complicated packaging types of application where it indeed works like this (dependant jars are included into the artifact) for example Spring boot application, Web Archives (WAR) and so forth. But since you compile a regular JAR it will include only the classes of your module and won't include classes of commons-csv in this case.
So in order to be able to run this application you should chose one of:
Put Jar of commons-csv (as well as other dependencies that you might have) into class path: java -classpath <path-to-commons-csv> -jar YourApp
Use Maven Shade Plugin to create a jar that will indeed include all the dependencies as classes
As mentioned in the other answers, you need to package up your dependencies in your executable jar (a.k.a. Uber-JAR). You mention you have tried two ways: using the Maven assembly with a descriptorRef jar-with-dependencies and the Maven shade plugin.
First global remark: Maven plugin configuration can be defined in a <pluginManagement> block or directly in the <build> part of a POM. I would suggest to put them in the <build>, and I assume you already put them there, but I can't verify that since you only pasted a part of it in your question.
When using the jar-with-dependencies descriptorRef in the Maven assembly plugin, two jar files will be created in your target/ folder: stride-1.0-SNAPSHOT.jar and stride-1.0-SNAPSHOT-with-dependencies.jar. You should use the -with-dependencies.jar, so run java -cp target/stride-1.0-SNAPSHOT-with-dependencies.jar com.myapp.maven.App
The Shade plugin offers more options than the Maven assembly plugin. However in the code you pasted you have not bound the execution of the Maven Shade plugin to the package phase of Maven's lifecycle. If you run a mvn package you will NOT see the Maven shade plugin as part of the build steps that Maven did. If you look more closely to mkyongs guide, you'll see that you need to include a <phase>package</phase> in your <execution> block.
Hi the problem is that when the jar is getting created the dependencies being downloaded is not being attached to the executable jar that is why there error is showing up we can add the below section in the build tag to get the dependencies attached to the executable jar and then you can execute the jar with java -jar command
maven-assembly-plugin
package single
... wow.dxdatagenerator.App
jar-with-dependencies
-->
We have quite a strange requirement.
Spring boot with multiple project
xbean is old version of xmlbeans apache jar
We want to use both
xbean old jar with some custom changes in the same jar
latest xmlbeans apache jar
we have current implementation as
Main() -
|- XLSImportProject project- which requires latest jar for reading xlsx file
|- B project - which requires old jar for custom operation
|- C project - also require old jar for custom operation
If we give maven priority to xbean old jar then we will get exception as
org.apache.poi.ooxml.POIXMLException: org.apache.xmlbeans.XmlOptions.setEntityExpansionLimit(I)Lorg/apache/xmlbeans/XmlOptions;
at org.apache.poi.ooxml.POIXMLFactory.createDocumentPart(POIXMLFactory.java:66)
at org.apache.poi.ooxml.POIXMLDocumentPart.read(POIXMLDocumentPart.java:648)
at org.apache.poi.ooxml.POIXMLDocument.load(POIXMLDocument.java:180)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:286)
at org.apache.poi.xssf.usermodel.XSSFWorkbookFactory.createWorkbook(XSSFWorkbookFactory.java:83)
at org.apache.poi.xssf.usermodel.XSSFWorkbookFactory.createWorkbook(XSSFWorkbookFactory.java:130)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.poi.ss.usermodel.WorkbookFactory.createWorkbook(WorkbookFactory.java:314)
at org.apache.poi.ss.usermodel.WorkbookFactory.createXSSFWorkbook(WorkbookFactory.java:296)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:214)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:180)
If we give maven priority to latest xmlbeans then it will be errors as:
Exception in thread "Thread-14" java.lang.NoSuchMethodError: org.apache.xmlbeans.XmlObject.getParent()Lorg/apache/xmlbeans/XmlObject;
We have to use old xbean jar in sub project and latest xmlbeans jar in other project.
But Spring will always the jar which is define first in dependency.
That looks like a classical classloader customization problem. I wouldn't go down that road. Best suggestion would be
create your own jar with all dependencies (tricky since you will face the problems of backward compatibility). Take a look here for repackaging jars.
Break away the multi module project into different projects with each set of projects using a particular dependency.
Take a look at Maven shade plugin. It rename the packages if required based on the content of the jar. Create Uber jar for your main application using shade plugin.
Shade plugin configuration:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<configuration>
<!-- put your configurations here -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
I have a Maven Scala project that will be deployed on some container and therefore mark several of the dependencies with scope provided meaning those dependencies will be used for compiling but not taken into account for transitive resolution as they are "provided at runtime". However, when I run the following command, it produces the intended jar with dependencies but also including those dependencies that were marked as provided.
mvn clean install assembly:assembly -DdescriptorId=jar-with-dependencies -DskipTests
I tried existing answers to this problem e.g. Excluding “provided” dependencies from Maven assembly but for some reason produces an incorrect choice of dependencies and even missing the main code. In this OP I'd like to find a cleaner, more up to date solution to this problem ... is there one?
You may be better off with a different maven plugin. See Difference between maven plugins ( assembly-plugins , jar-plugins , shaded-plugins. Shade would probably suit you best in this case. What you are looking to create is referred to an uber-jar.
Regarding Shade, from the Maven website:
This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade - i.e. rename - the packages of some of the dependencies.
The goals for the Shade Plugin are bound to the package phase in the build lifecycle.
Configuring Your Shade Plugin:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<!-- put your configurations here -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
Note that the default implementation replaces your project's artifact with the shade version. Need both? Look here: Attaching the Shaded Artifact
Merging several jars at once is not necessarily utter simplicity and so Shade has the concept of Resource Transformers (link also has more samples).
Aggregating classes/resources from several artifacts into one uber JAR is straight forward as long as there is no overlap. Otherwise, some kind of logic to merge resources from several JARs is required. This is where resource transformers kick in.
The project site is actually quite good. There are lots of varied examples.
Currently we are working on the big maven project that has about 100 modules, some of them have submodules as well.
Some of modules use Maven Build Number plugin. The project is hosted under subversion.
Recently we started to use git locally in our development team.
After cloning subversion repo and trying to build the Project, we received following well known error:
The svn command failed.
Command output:
svn: ‘.’ is not a working copy
Unfortunately in our case it is not an option to create a new profile or just remove plugin definition from POM (this will follow to messing up hundreds of POM files).
I found the following article http://abstractionextraction.wordpress.com/2012/09/27/git-svn-vs-maven-build-number-plugin/ but honestly, it's not something that I would really like to do...
Is there any smart way to disable this plugin. Like command-line parameter?
I think you may skip failure on obtain revision without change project pom.xml - buildnumber-maven-plugin has option revisionOnScmFailure which you may use like:
mvn -Dmaven.buildNumber.revisionOnScmFailure=no-scm package
In that case value no-scm will be used if scm call was unsuccessful. Off course you may change it and provide any other string.
Per the mojo documentation, you could use the revisionOnScmFailure property.
However, it doesn't have a command line option. You'll have to modify those pom.xml files.
See "Defining Parameters Within a Mojo" in the Maven Java Plugin Development Guide
One approach would be to use a property in your pom to specify the execution phase of the build number plugin, as shown below.
<project>
..
<properties>
<buildnumber.plugin.phase>validate</buildnumber.plugin.phase>
..
</properties>
..
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<phase>${buildnumber.plugin.phase}</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
<configuration>
..
</configuration>
</plugin>
</plugins>
..
</project>
Then provide the property on the command line to disable the plugin, as shown in the following example.
mvn install -Dbuildnumber.plugin.phase=none