Can A Maven Dependency Be Executable? - java

I am creating a generic utils maven project. I have added this utils project as a dependency into my main maven project. It looks like I can use plugins in my utils pom to generate an executable jar. If the jar is executable, could I run it in my main project by adding it as a dependency? If I can, how do I add the path of the dependency to the exec-maven-plugin?
main_pom.xml
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>default-cli</id>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>java</executable>
<arguments>
<argument>-jar</argument>
<!-- How can I get the dependency path here? -->
<argument>path/to/executable-dependency-jar/name.jar</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
I want it as a dependency for convenience. But I don't know if a dependency can be executable. And I don't know how to get the dependency path as shown above in the xml. My idea was to:
Add an executable dependency.
Add maven exec plugin to run the
executable dependency as shown above.
When I want my utils ran I
would just have to execute mvn exec:exec.

Not sure what you're trying to do, but you can have an executable jar, and use it in another project.
But in this case, you don't need to call it as an executable. This is way simpler to just call some java code.
An executable jar is basically a jar with at least one class containing a valid main method (plus a manifest to know which class is the main class).
You can use this class from your Java code, without going "out" of the jvm, and use your jar as an executable.
And yet, you keep the ability to call your executable jar from outside (i.e from command line).
Typically, you have a business method doStuff(some signature), that you can call from any java code (this might be a static method) and main methods that just parses the command line arguments and calls the doStuff method.

Related

Maven Exception NoClassDefFoundError ClassNotFoundException but Maven Dependency Exists Command Line

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
-->

How do I fail a Maven build from inside Java logic?

I am developing a project in which I would like to use Maven to execute a Java Main class as part of the build process. The Main class's job is to validate that some given (currently hardcoded) files are valid RAML files. In a perfect world, I would like the build to be able to fail the build from within this class's logic, if they are invalid, and have that failure report back to the terminal with the "[BUILD FAILURE]" message just like maven does natively.
I added tho org.codehaus.mojo.exec-maven-plugin plugin to my POM, which is allowing me to execute the Java Main class I mentioned earlier. That section of the POM looks like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.example.ubunfu.MainClass</mainClass>
<arguments>
<argument></argument>
</arguments>
<cleanupDaemonThreads>false</cleanupDaemonThreads> <!-- Prevents thread hanging -->
</configuration>
</execution>
</executions>
</plugin>
However, I'm not sure how to signal from the logic inside of MainClass that the build should fail - if that's necessary. I read about the org.apache.maven.plugins.MojoFailureException in the Maven - Guide to Developing Java Plugins. There it seems to say that I can throw one of these and it will fail the build like I'm hoping for.
I'm not sure what I need to do in order to have the MojoFailureException class available to me inside MainClass. I haven't been able to find a JAR or anything, but if I understand how Maven works, this should be fixed with some kind of addition to the POM, not a JAR.
If you have any insight for me on this, I'd really appreciate it.
-Ryan
It appears that throwing any exception will cause the build to fail. See this answer.
To get access to MojoFailureException, add the following dependency:
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.3.3</version>
</dependency>
Hint: According to Exec Maven Plugin, Usage <configuration> resides outside of <executions>.
"I would like the build to be able to fail the build from within this class's logic" → Simply throw new RuntimeException().

issue in test classes jar creation(without test classes run only compile) using maven and java

my java project structure looks like below
MyJavaProject
|
src/main/java
|
src/test/java
my project link https://docs.google.com/file/d/0BytpaaWh1xMbb19XNDd4MURqMmc
please correct my code
My pom mentioned below:
How do i create a test module classes jar and main module classes jar with all maven dependencies.
Without running test module(only compile) i need to get test jar.What changes needed to my pom and what maven command i need to mention(or what maven goal i need to mention in eclipse).
When i used jar:test-jar (as per my pom) in the goal field ,test jar created with all classes some times but some times jar contains no class at all.
When i used compile assembly:single in the goal field ,main module classes jar created with all dependencies every time.
please can any one help me.i need a sample pom that creates main,test modules of a java project compiled classes jar with maven dependencies
i got answer:
goal as : mvn clean install -DskipTests
Add this in your pom.xml
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>

Is it possible to include a dependency at a specific phase of the build?

I am currently using the maven-jar-plugin to build a JAR from a specific class folder which I have included as a provided scope dependency. I now need to include this JAR as a dependency in my final build.
So, is it possible to include a dependency at a specific phase of the build?
NOTE: The dependency is built during the build process, so it is only available during the compile phase.
The simplest way to tackle this would be to separate the code you are building with the maven-jar-plugin into a separate Maven project, and just refer to it as a normal dependency in the main Maven project.
This way you don't need to mess around with having one Maven build produce two different artifacts (the JAR you are generating and then the main output minus that JAR's classes) while having the output of the first being referred to in the second.
Alternatively, assuming your main project has the package type set to jar, you could just add the "specific class folder" classes to the project's <resources> element and then configure/override the maven-jar-plugin execution that runs during the package phase to exclude these classes, with the <excludes> element in the <configuration>.
You could configure the files included in the generated jar :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<includes>
<include>relative_path_to_your_jar</include>
<include>**/**</include>
</includes>
</configuration>
</plugin>
http://maven.apache.org/plugins/maven-jar-plugin/jar-mojo.html#includes

How to change the default output from a Maven 2 / Cobertura instrument goal?

when i instrument my classes using Maven 2 using the command
mvn cobertura:instrument
The output (the instrumented classes) are put in \target\generated-classes. Is there a way to change the output location to \target\classes?
I checked the instrumentation tasks of the cobertura-maven plugin but this does not give me a solution sofar.
You have not said why you want to overwrite the default location, but I assume it is so that you can use the instrumented classes from another project, or perhaps include them in a web archive or something similar.
I added the following to my pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>instrumented-classes</id>
<goals>
<goal>jar</goal>
</goals>
<phase>package</phase>
<configuration>
<classifier>instrumented</classifier>
<classesDirectory>${project.build.directory}/generated-classes/cobertura</classesDirectory>
</configuration>
</execution>
</executions>
</plugin>
This makes maven generate an additional jar file called projectname-instrumented.jar
It is then possible to depend on this jar file from any other pom (including for example a web module) using
<depends>
<group>mygroup</group>
<project>projectname</project>
<version>1</version>
<classifier>instrumented</classifier>
</depends>
I did not test this 100% but have used similar mechanisms in the past
As far as I understand, the instrumented classes are only needed by cobertura for report generation. If you create them in target/classes, they will overwrite the original class files.
If you need the instrumented files in a jar as a result, you can configure the maven-jar-plugin to pick up the files from the target/generated-classes directory instead of or in addition to the files from the standard ${build.project.outputDirectory}.
Edit
Have a look at the maven-jar-plugin description. To only use target/generated-classes, the following addition to your POM should work - try it and modify it to your needs:
<project>
...
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3</version> <!-- replace with correct version nbr! -->
<configuration>
<includes>
<include>${project.build.directory}/generated-classes/**/*.class</include>
</includes>
<excludes>
<exclude>${project.build.directory}/classes/**/*.class</include>
</excludes>
</configuration>
</plugin>
...
</plugins>
</build>
...
</project>
${project.build.directory} points to your target folder, ${project.build.ouputDirectory} to target/classes. I do not know if you can simply set ${project.build.ouputDirectory} to a new value - have a look at the this chapter of the maven book, maybe you find some hints
Edit 2
Alternativly or additionally you can use maven to copy the files from target/generated-classes to target/classes after coberture:instrument has finished. This question has one answer with an example POM (fragment), you just have to identify the correct phase (process-resources is definitely too early for your case)
Did you try "mvn cobertura:instrument install"? It will generate a jar file including all the cobertura version classes.
If you want to change back original version, just run the command without "cobertura:instrument".
I just implemented the solution proposed by Andreas_D, modified my pom and uses the maven-resources-plugin. So on some stage of my build the Cobertura generated files are copied to the /target/classes directory.
You can configure it using <classesDirectory>[Your DIR]</classesDirectory>
In cobertura-maven-plugin version 2.4 this is still not supported. I've just created an improvement ticket, patch is attached to the ticket.

Categories

Resources