I'm trying to use(import) a class added by a dependency of my project.
I added the dependency gson in my pom.xml as follows:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
And I ran mvn install after that.
Now I can find the jar dependencies in C:\Users\%Name%\.m2\repository\com\google\code\gson\gson\2.8.5, so I assume it is correctly installed.
When I try to import the class Gson in Java, several problems occurs:
The path to import isn't com.google.code.gson but com.google.gson, I don't understand why.
When I compile with mvn package, everything runs smoothly. But if I try to run the code with java -cp .\target\testJSON-1.0-SNAPSHOT.jar json.App I get the following error telling me the Gson class isn't found :
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/gson/Gson
at json.App.main(App.java:13)
Caused by: java.lang.ClassNotFoundException: com.google.gson.Gson
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
Now from what I understood by looking for solutions:
While maven know the dependencies of the project, java won't. And I need to manually add the jar to the classpath.
So my questions are:
If I bother to tell maven I need gson to run my project, why do I need to manually include all dependencies to run it ? Is there a way to automate this thing in an easy and intuitive manner ?
When I look for ways to add multiples jars to the classpath, the only answers I find assume that all the jars are in the same folder, hence proposing to do java -cp folder/*.jar. The jar generated by Maven is located in the target subfolder of my project, while the gson jar is located in the .m2 folder. How to add multiple jars (located in different locations) to the classpath ?
Thank you,
The path to import isn't com.google.code.gson
Google Code got shut down in 2016, they have changed their group IDs.
the Gson class isn't found
The GSON JAR isn't on the classpath.
If I bother to tell maven I need gson to run my project, why do I need
to manually include all dependencies to run it ? Is there a way to
automate this thing in an easy and intuitive manner ?
Maven is a build tool, and it has built your app successfully. Java requires you to include the JARs on the classpath. This not a deficiency of Maven. If you want to bundle all the dependencies together into one JAR that "just runs" then create a fat JAR.
How to add multiple jars (located in different locations) to the
classpath ?
If you create a fat JAR, you won't have to, but you can separate classpath entries like so (OS-specific):
java -cp folder/*.jar;another/folder/*.jar
You may want to include the dependencies in when creating a jar with maven. You can use maven-assembly plugin,
<build>
<plugins>
<!-- any other 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>
Related
I am having a group of external jars(in hundreds) which I have added in the build path of my project to make it work.
But while packaging it is failing as these jar's are not available to maven.
I have gone though many articles and all the solutions(like adding the jar at system path) are for a single jar only.
<dependency>
<groupId>com.sample</groupId>
<artifactId>sample</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/Name_Your_JAR.jar</systemPath>
</dependency>
Is there any way we can add the group of jars(folder) to the packaging on the project? or any other solution by which my project can build successfully?
can we create a single jar containing all my jars inside and then use the system scope of maven
I have tried creating jar by jar -cvf my_jar.jar * and placed this jar in the system scope. But it does not worked for me.
My solution : Maven pluggin addjar let us add all jar at a place(projectdirectory/lib in this case).
this enables you to add these jar's in the final package(jar in my case) when you maven build, but to run locally you have to add those jar files directly in the classpath.
<plugin>
<groupId>com.googlecode.addjars-maven-plugin</groupId>
<artifactId>addjars-maven-plugin</artifactId>
<version>1.0.5</version>
<executions>
<execution>
<goals>
<goal>add-jars</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>${basedir}/lib</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
Now create a shade jar using mvn clean install shade:shade
The bad news: For a proper Maven project, you need to add each and every artifact you use as <dependency> in your POM.
The good news: I very much doubt that these 100 jars are all
- directly used in your source code
- not available in a public Maven repository like MavenCentral
So the better strategy would be to figure out what you really need and find that in MavenCentral. Then Maven finds all the transitive dependencies for you. So if you really need 10 of the jars and all other jars are just dependencies of your dependencies, just add these 10 ones (from MavenCentral) and you are done.
I would like to use existing step definition classes coming from maven jar dependency.
My cucumber tests works if ran from Runner Class (with glue to packages) & mvn CLI. But the
problem is with IntelliJ Cucumber plugin for the steps which are coming from jar. In feature file steps that I am using from the jar are shown as "Undefined step reference:...". I am not even able to run directly from feature file.
Is there a way I can configure cucumber plugin to use stepdefinations from classloader/jar?
Posting the solution worked for Me:
Use IntelliJ 2020.1 +
In cucumber run configuration : select jar manifest for classpath
Deploy the Jar with source jar as well to Nexus as below
You can simple do this by adding maven-source-plugin plugin to your build
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
In other project add dependency and confirm source is downloaded from repo
File -> Project Structure -> Libraries -> Select the Artifact -> Sources , Make sure it's not in red.
Update IntelliJ to use latest version, for me IntelliJ version 2019 did not work but 2020.1 was able to find the step definitions.
PS: I use Java8 with Lambda exp and I can confirm it works.
Updating Intellij from version 2019.3 to 2022.2 solved the issue without changing anything else.
My project is in Java 8
I have a Java/Maven project (POM-based) which builds and launches fine when using java -jar on the uber JAR produced by my Maven build on the command line, using the spring-boot-maven-plugin:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.0.3.RELEASE</version>
<configuration>
<mainClass>com.company.Application</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
The JAR is created (~100MB), and launches as expected.
However, I'm unable to launch this same application in Eclipse using the right-click -> Run As -> Java Application configuration on the main class I've defined in my POM. It's a Maven project, and M2E is up-to-date/refreshed, etc.
The error is:
java.lang.NoClassDefFoundError: Could not initialize class org.slf4j.LoggerFactory
So clearly some dependency issues with the logging frameworks. However: My first head-scratcher was, why does this work in Maven using the CLI, and fail in Eclipse using M2E?
So I went and looked at the classpaths, and they seem identical. (Looking at the Maven Dependencies list in Eclipse, and the BOOT-INF directory contained in my uber JAR.) The interesting bits are:
slf4j-api 1.7.25
log4j-over-slf4j 1.7.25
logback-core 1.2.3
logback-classic 1.2.3
commons-logging 1.1.3
So, I debugged. I placed a breakpoint on NoClassDefFoundError, and captured this. Note that the debugger is paused on the thrown exception, and the watch expression in the upper-right is getClass().getClassLoader().classes, which is a Vector.
How is it possible that we're throwing on LoggerFactory, even though this very class is present in the current ClassLoader? Where should I look next?
Edit: Since it's causing some confusion, the class in which Eclipse has caught this error (Category.java) is not one of my classes. It's inside a dependency (see Eclipse titlebar) and as a result cannot be modified.
I am developing a Java maven project with Eclipse and want to export a jar that includes all referenced libraries. These referenced libraries fall into one of these two categories:
They are explicit (or implicit) dependencies in the pom.xml
I have some libraries not available as maven artifacts and have put them in /lib (and added them to the build path in Eclipse)
There's the maven-assembly-plugin, which works fine for 1). However, I'm unable to find a maven plugin that also includes non-maven-dependencies, e.g. "all jars in /lib".
Then there's the Eclipse FatJar plugin, which sort of works, but hasn't been updated since 2009, so it seems unmaintained. Also I prefer an export method that I can directly specify in the pom.xml.
Can anyone point me to a maven plugin or the like to export all referenced libraries, including those from case 2) ? That only needs to involve putting them in the jar and referencing them in the manifest's classpath.
Thanks!
I think the best way to handle this is to include your custom libs into a local maven repository. Now you can inlcude your libraries as maven dependencies and you can export all your dependencies specified in your pom with the maven-assembly-plugin.
Here is a tutorial, how to put your libs into a local repository in maven to use it in your pom. http://www.mkyong.com/maven/how-to-include-library-manully-into-maven-local-repository/
And in your pom.xml:
<!-- setup jar manifest to executable with dependencies -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>your.main.class</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
This looks like a task for Tycho. It is a set of maven plugins that allows to create eclipse plugins with maven. Tycho considers manifest entries as build dependencies.
However I'm not aware of how to package all those dependencies in a single jar. This may also be conflicting with the osgi spec. But if you wish to ignore osgi you could just try the jar-with-dependencies assembly.
So my maven project depends on a jar that is NOT in any maven repository. Therefore I need to use the system scope to include this local file in my maven classpath. Question is: When I build my final jar to distribute my library, I do need to somehow include that dependency with it. The classes can be extracted and then bundled with my library classes OR the jar can be included somehow inside my library jar. I am not even sure the latter (jar inside jar) is possible in Java.
So how should I approach this problem? Will Maven take my system scope dependency and take care of that for me? What should I do?
Thanks!
No, it will not. These dependencies are only for compilation and transitive dependency resolution. Your library consumers should have the jar too.
However, you could use the Assembly Plugin to repackage the jar's classes into your artifact.
Or, the standard approach: then you will publish your artifact, you will create a public repository for deployment. You also could deploy the jar in it.
UDPATE: adding example for the shade plugin (instead of the Assembly)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>legacy-jar.groupId:legacyJar</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
There is a second option. Put the jar into your repository as described here:
http://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html
and to your online repository
http://maven.apache.org/guides/mini/guide-3rd-party-jars-remote.html
give your client access to your repository and use your legacy.jar as normal dependency.
It depends a little bit what kind of library do you have. With this way you don't have problems with version conflicts of your legacy.jar in the environment of your customer.
Could this be what you are looking for, http://maven.40175.n5.nabble.com/How-to-specify-local-dependency-in-maven2-td103415.html.