I am trying to run my java program TopicPublisher.java via command line. There are several dependencies specified through Maven.
In the directory with the pom.xml file, I ran the following commands: mvn clean, mvn package, and java -cp target/SOM_Enrichment-1.0-SNAPSHOT.jar TopicPublisher.
I get the following error:
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: om/solacesystems/jcsmp/JCSMPStreamingPublishEventHandler
Below is a screenshot of my directory tree:
Any ideas how to solve this?
[EDIT]
Pom File:
<?xml version="1.0" encoding="UTF-8"?>
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
<groupId>CAMM</groupId>
<artifactId>SOM_Enrichment</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.solacesystems</groupId>
<artifactId>sol-jcsmp</artifactId>
<version>[10,)</version>
</dependency>
</dependencies>
Your program loads classes from the com.solacesystems dependency in your pom.xml, but your classpath only contains your build artifact jar. Build a fat jar, as #Kerry suggests, or use the exec-maven-plugin to run from the command line. From within your project directory (where you execute mvn package), execute:
mvn exec:java -Dexec.mainClass=TopicPublisher
The plugin builds the classpath argument from the dependencies defined in your pom. See https://www.mojohaus.org/exec-maven-plugin/ for more options.
Without seeing your full POM.xml I am assuming you have not build the final artifact to be a 'fat jar'. By this I mean that the JAR not only contains your own classes but all the third party dependencies.
You would need to use something like the Maven assembly plugin or the Maven shade pluginto do this for you. From the screenshot though I see you are using IntelliJ so you should also be able to run through your IDE obviously for just testing purposes.
Related
I am trying to implement semantic versioning in our project. I tested maven semver plugin but that didn't help me so please don't ask me why. I finally ended up using maven groovy. It works like a charm, however, when I install or deploy the maven project the version in repository is the variable name.
This is despite the fact that all the artefacts and jar files are packaged with correct version.
So please look at my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mytest.test</groupId>
<artifactId>test-tag</artifactId>
<version>${revision}</version>
<description>Test</description>
<properties>
<ChangeType>TO_BE_SET</ChangeType>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<providerSelection>2.0</providerSelection>
<properties>
<script>git describe --abbrev=0 --tags</script>
</properties>
<source>
def tagIt = 'git tag -a vXXXX -m "Auto tagged"'
def changeType = project.properties.ChangeType
def command = project.properties.script
def process = command.execute()
process.waitFor()
def describe = process.in.text.trim()
println "Setting revision to: " + describe
if(!describe.startsWith("v")) {
describe = "1.0.1"
} else {
describe = describe.substring(1)
}
project.properties.setProperty('revision', describe)
</source>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>default-testResources</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>default-jar</id>
<phase>package</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>default-test</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
the version is ${revision} a variable name that is being set in groovy script. What groovy code does is getting the last tag from GIT and and then set it to the property 'revision'.
The final jar file has the correct version extracted but when installed into repository, the folder name and jar name are like:
m2\repository\com\mytest\test\test-tag\${revision}\test-tag-${revision}.jar
I tried to default 'revision' to a value using:
<properties>
<revision>1.0.1</revision>
</properties>
but then groovy code setting the value has no effect.
I also tried different phase for the maven groovy plugin, no luck. Have I missed anything? Can anyone please help me on this?
I'd like to mention that as vatbub and StefanHeimberg mentioned I can use versions:set to set the version but this requires me to do an extra commit to GIT which I am trying to avoid, wondering if I can achieve this by writing a maven plugin instead?
With Maven you can set the version at build time with
mvn versions:set -DnewVersion=${bamboo.inject.version}
as #vatbub already commented in your question.
In addition to this i wrote a Shell script that can be used in build pipeline to generate the version according to the maven project version and add the build number from the build server.
https://gist.github.com/StefanHeimberg/c19d7665e8df087845c036fe8b88c4f2
The Script reads the maven project version, add a the build number and writes a text file with all the new numbers that can be used.
The next step is to inject this text file in the Build Pipeline and call the versions plugin as stated above
pom.xml:
something like
<project>
<groupId>ch.stefanheimberg.example</groupId>
<artifactId>your-awesome-app</artifactId>
<version>5.1.2-SNAPSHOT</version>
</project>
or
<project>
<groupId>ch.stefanheimberg.example</groupId>
<artifactId>your-awesome-app</artifactId>
<version>5.1-SNAPSHOT</version>
</project>
Step 1:
./generate_version_txt.sh ${bamboo.buildNumber}
Step 2:
Inject generated version.txt in the build system that all the properties can be used in all tasks / plugins, etc...
In my case Bamboo CI ready the version.txt file and declares the content of the file as environment variables under the bamboo.inject. prefix.
For example ${bamboo.inject.long_version}
Step 3:
Update Maven Project version
mvn versions:set -DnewVersion=${bamboo.inject.version}
Step 4:
Run Maven Build
mvn clean verify
Step 5:
Run Docker build
for example use it also as docker tag version. etc...
docker build --build-arg version=${bamboo.inject.version} --tag your-awesome-app:${bamboo.inject.version} .
Example Dockerfile:
FROM jboss/wildlfy
ARG version
ADD target/your-awesome-app-${version}.war /opt/jboss/wildfly/standalone/deployments/
I know that can be a problem / not possible in your case with the groovy script. but perhaps it is an other view at your problem. and possibly also another solution for it.
(sorry for my english. but i hope it is understandable what i mean)
I ran into a similar problem and ended up using the maven flatten plugin to ensure that all variables are removed from the POMs before being deployed. This remove all references to the string ${revision} and replace by the actual value at build time, without interfering with the original POMs.
So I run maven package to build my dependencies into a jar. However, I need Maven to ignore any compilation errors and package the jar regardless.
How would this be accomplished? My pom.xml is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- Project specific stuff would be here... -->
<build>
<sourceDirectory>wherever</sourceDirectory>
<plugins>
<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>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!-- etc... -->
</dependencies>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
Searching through SO only showed me how to ignore compilation errors from unit testing. I simply want my package to be compiled despite any errors in the code.
Edit: People seem to be bashing on me. I've been doing Java for 5 years. I know you're not supposed to compile with errors. I know what it entails.
My boss programs with me. He specifically said, "I can compile with errors in Eclipse, so compile with errors in Maven." It's not because I am ignorant, or because I refuse to accept my mistakes. It is because that is what I was specifically ordered to do. I did not ask this question because I am incompetent as many of you would like to assume.
Hate on me all you want, just know that you are doing so unfairly.
Use the exclude option to the compiler plugin to exclude the classes that have compile errors.
Building on Top of #wings Answer
You can use the flag failOnError=false in your pom, too
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<failOnError>false</failOnError>
</configuration>
</plugin>
or via command line
mvn package -Dmaven.compiler.failOnError=false
Maybe this is what you want:
https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#failOnError
Set failOnError=false to ignore compilation errors.
When you run maven package. That means maven will run all phases before "package" phase. Hence maven compile will be triggered for sure. And because of compilation error, maven will stop at "compile" phase.
To package your project even with compilation error. I think you should use "maven assembly plugin" to package your depensencies ONLY and the phase of that plugin should be something before "compile". ex: "process-sources" or "process-resources".
By that way, before maven compiles your project's source code, you will have a bundle which includes all dependencies. Of course, maven will stop at the "compile" phase again. But you already have what you want.
Hope this help.
If it's just about the dependencies there's dependency:copy-dependencies:
Goal that copies the project dependencies from the repository to a defined location.
Use assembly:single with a user-defined descriptor to create the JAR with the dependencies from the location defined above:
Assemble an application bundle or distribution from an assembly descriptor.
Until now i made runnable jars with Ant and there were no problems with it.
However i now try to mavenize my project and i realy can't figured out how to do runable jar with this tool.
I've read tons of tutorials (also here, on Stackoverflow), helps, advices and... nothing. In my case all of them don't work which probably means i don't understand some basics.
I have such simple project:
This is app, witch use mysql-connector-java-5.1.24-bin.jar (placed in 'lib' dir) to connect to MySQL database.
I want to include this jar into final jar (DBPreformatter.jar).
I used assembly and shaded plugins in many configurations, but they NEVER added this jar into DBPreformatter.jar.
This is my pom.xml:
<modelVersion>4.0.0</modelVersion>
<groupId>com.icd4you</groupId>
<artifactId>DBPreformatter</artifactId>
<version>1.0.0</version>
<name>DBPreformatter</name>
<description>DB processing and cleaning tool</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>mysql-connector-java-5.1.24-bin</groupId>
<artifactId>mysql-connector-java-5.1.24-bin</artifactId>
<version>5.1.24</version>
<scope>system</scope>
<systemPath>${basedir}/lib/mysql-connector-java-5.1.24-bin.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<!-- WHAT SHOULD I USE HERE? -->
</plugins>
</build>
How to solve this problem?
There is a maven plugin Apache Maven Shade Plugin that will build an uber jar for you
Add the Maven Assembly plugin with the descriptor jar-with-dependencies:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.pany.your.MainClass</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Note that this doesn't add the JAR; instead it unpacks all JARs which are listed as dependencies and adds their content to the resulting JAR (so you'll see all the class files from the MySQL JAR in the result instead of the MySQL JAR itself).
EDIT There is a caveat, though: Maven ignores JARs with scope=system for many operations. See also: How to include external jars in maven jar build process?
If Maven doesn't add the JAR to the output, then you must install all JARs with this scope into your local maven repo ($HOME/.m2/repository) using the mvn install:file-install command. See http://maven.apache.org/plugins/maven-install-plugin/usage.html how to do that.
Note: Installing libraries in your local repo is the preferred way; you should really consider it. For one, the scope=system will no longer confuse you (since many plugins handle them in a special way). Plus you need to do this only once. Afterwards, you can use this library in many Maven projects.
Before installing, you should check http://search.maven.org/ to see if the dependency isn't already known to Maven.
MySQL is: http://search.maven.org/#artifactdetails%7Cmysql%7Cmysql-connector-java%7C5.1.32%7Cjar
I can not create javadocs to a folder I like, Here is how my javadoc plugin looks like;
<build>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<outputDirectory>${build.dir}/resources/javadoc</outputDirectory>
<reportOutputDirectory>${project.reporting.outputDirectory}/javadoc</reportOutputDirectory>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<phase>package</phase>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Any ideas?
EDIT MAven install leads to error"
Failed to execute goal org.apache.maven.plugins:maven-javadoc-plugin:2.9.1:aggregate
(attach-javadocs) on project priTool: An error has occurred in JavaDocs report generation:
[ERROR] Exit code: 1 - C:\pricing\priWebApp\src\main\..webapp\backend\local\PriUpgradeHelper.java:5:
package ..upgrademanager does not exist
[ERROR] import ...upgrademanager.ComponentInfo;
Upgrade Manager is an external dependency, but I can see its jar in library
You need to understand the difference between mvn package and mvn install. package creates the JARs in the target folder of the Maven project/module.
If there are more modules, they won't be able to see these JARs - for each project/module, Maven only looks into the local repository to resolve dependencies, even if could resolve them in the same project.
And that's what install does: Package the JARs and then install them into the local repository.
When you have a Maven project, with several modules (a.k.a a reactor build), then never use mvn package. Always use mvn install.
My first use of Maven and I'm stuck with dependencies.
I created a Maven project with Eclipse and added dependencies, and it was working without problems.
But when I try to run it via command line:
$ mvn package # successfully completes
$ java -cp target/bil138_4-0.0.1-SNAPSHOT.jar tr.edu.hacettepe.cs.b21127113.bil138_4.App # NoClassDefFoundError for dependencies
It downloads dependencies, successfully builds, but when I try to run it, I get NoClassDefFoundError:
Exception in thread "main" java.lang.NoClassDefFoundError: org/codehaus/jackson/JsonParseException
at tr.edu.hacettepe.cs.b21127113.bil138_4.db.DatabaseManager.<init>(DatabaseManager.java:16)
at tr.edu.hacettepe.cs.b21127113.bil138_4.db.DatabaseManager.<init>(DatabaseManager.java:22)
at tr.edu.hacettepe.cs.b21127113.bil138_4.App.main(App.java:10)
Caused by: java.lang.ClassNotFoundException: org.codehaus.jackson.JsonParseException
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
... 3 more
My pom.xml is like this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>tr.edu.hacettepe.cs.b21127113</groupId>
<artifactId>bil138_4</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>bil138_4</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.6</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Can anyone help me?
By default, Maven doesn't bundle dependencies in the JAR file it builds, and you're not providing them on the classpath when you're trying to execute your JAR file at the command-line. This is why the Java VM can't find the library class files when trying to execute your code.
You could manually specify the libraries on the classpath with the -cp parameter, but that quickly becomes tiresome.
A better solution is to "shade" the library code into your output JAR file. There is a Maven plugin called the maven-shade-plugin to do this. You need to register it in your POM, and it will automatically build an "uber-JAR" containing your classes and the classes for your library code too when you run mvn package.
To simply bundle all required libraries, add the following to your POM:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
Once this is done, you can rerun the commands you used above:
$ mvn package
$ java -cp target/bil138_4-0.0.1-SNAPSHOT.jar tr.edu.hacettepe.cs.b21127113.bil138_4.App
If you want to do further configuration of the shade plugin in terms of what JARs should be included, specifying a Main-Class for an executable JAR file, and so on, see the "Examples" section on the maven-shade-plugin site.
when I try to run it, I get NoClassDefFoundError
Run it how? You're probably trying to run it with eclipse without having correctly imported your maven classpath. See the m2eclipse plugin for integrating maven with eclipse for that.
To verify that your maven config is correct, you could run your app with the exec plugin using:
mvn exec:java -D exec.mainClass=<your main class>
Update: First, regarding your error when running exec:java, your main class is tr.edu.hacettepe.cs.b21127113.bil138_4.App. When talking about class names, they're (almost) always dot-separated. The simple class name is just the last part: App in your case. The fully-qualified name is the full package plus the simple class name, and that's what you give to maven or java when you want to run something. What you were trying to use was a file system path to a source file. That's an entirely different beast. A class name generally translates directly to a class file that's found in the class path, as compared to a source file in the file system. In your specific case, the class file in question would probably be at target/classes/tr/edu/hacettepe/cs/b21127113/bil138_4/App.class because maven compiles to target/classes, and java traditionally creates a directory for each level of packaging.
Your original problem is simply that you haven't put the Jackson jars on your class path. When you run a java program from the command line, you have to set the class path to let it know where it can load classes from. You've added your own jar, but not the other required ones. Your comment makes me think you don't understand how to manually build a class path. In short, the class path can have two things: directories containing class files and jars containing class files. Directories containing jars won't work. For more details on building a class path, see "Setting the class path" and the java and javac tool documentation.
Your class path would need to be at least, and without the line feeds:
target/bil138_4-0.0.1-SNAPSHOT.jar:
/home/utdemir/.m2/repository/org/codehaus/jackson/jackson-core-asl/1.9.6/jackson-core-asl-1.9.6.jar:
/home/utdemir/.m2/repository/org/codehaus/jackson/jackson-mapper-asl/1.9.6/jackson-mapper-asl-1.9.6.jar
Note that the separator on Windows is a semicolon (;).
I apologize for not noticing it sooner. The problem was sitting there in your original post, but I missed it.
You have to make classpath in pom file for your dependency. Therefore you have to copy all the dependencies into one place.
Check my blog.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>$fullqualified path to your main Class</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
This is due to Morphia jar not being part of your output war/jar. Eclipse or local build includes them as part of classpath, but remote builds or auto/scheduled build don't consider them part of classpath.
You can include dependent jars using plugin.
Add below snippet into your pom's plugins section
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
For some reason, the lib is present while compiling, but missing while running.
My situation is, two versions of one lib conflict.
For example, A depends on B and C, while B depends on D:1.0, C depends on D:1.1, maven may
just import D:1.0. If A uses one class which is in D:1.1 but not in D:1.0, a NoClassDefFoundError will be throwed.
If you are in this situation too, you need to resolve the dependency conflict.
I was able to work around it by running mvn install:install-file with -Dpackaging=class. Then adding entry to POM as described here:
Choosing to Project -> Clean should resolve this