Intellij Java 2016 & Maven : how to embed dependencies in JAR? - java

I'm using Intellij Java 2016.2.2 and Maven to create a very simple Java console application.
I want to add an external library, so I add my dependency in Maven like this:
<dependency>
<groupId>jline</groupId>
<artifactId>jline</artifactId>
<version>2.12</version>
</dependency>
It works fine when I run it in the IDE, but not in an external console (I have the following error: java.lang.NoClassDefFoundError).
I checked and for some reason, the external JAR is not added in the JAR I just generated. I also tried many things in "File -> Project Structure", but still not working...
I just want to build my JAR with my dependencies in it, so I can simply run my application in a console using:
java -jar myproject.jar
How can I do that? Thanks for your help!

I finally managed to generate this JAR with Intellij Java, here is how I do:
add the dependencies in the pom.xml file
go to File -> Project Structure -> Artifacts -> New -> JAR -> From module with dependencies
choose the Main class and click OK
in your project, in src/main, create the "resources" folder
move the "META-INF" (with MANIFEST.MF in it) folder in this "resources" folder
go to Build -> build artifacts to build the JAR
EDIT
A better (and easier way) to do it is adding the following lines in the pom.xml file :
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>your.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
then use the "clean" and "package" maven commands.
The last 3 steps above (about MANIFEST.MF) still seem to be mandatory.

Okay, so you basically want to create a "fat jar" (sometimes called assembly), that contains all its own dependencies (usually, the dependencies are external).
You need to use a Maven plugin for that. Below is a sample assembly plugin configuration jar-with-dependencies:
<project>
...
<build>
...
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
...
</project>
then, simply run
mvn package

Related

No suitable driver found for jdbc:postgresql://localhost:5432/gis

I've spent the last 3 hours trying to get my Java program to interface with my Postgres server. I cannot get past the error message "No suitable driver found for jdbc:postgresql://localhost:5432/gis". It is a Bukkit plugin, and I am using IntelliJ IDEA.
The code:
try
{
//Class.forName("org.postgresql.Driver");
c = DriverManager.getConnection("jdbc:postgresql://localhost:5432/gis");
}
catch(Exception e)
{
getLogger().info(e.getMessage());
}
Things I have tried:
java -cp ./path/to/postgresjdbc.jar -jar spigot-1.15.2.jar
adding the jdbc file internals directly to my jar file
adding the jdbc file as a dependency within the IntelliJ project
switching to maven, and putting the following in pom.xml:
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.1</version>
</dependency>
</dependencies>
I am unable to get past the error I posted. At this point, it has taken over my entire evening.
I've stumbled with this issue several times when developing Bukkit/Spigot plugins that make use of MySQL databases. The process for Postgres should be the same.
Usually, this error happens when your plugin can't find the PostgresqlJDBC driver. You have two workarounds:
Option 1. Adding the .jar to the plugin's classpath:
It's recommended that you set the libraries inside plugins/lib as then your server won't try to load the libraries as a Bukkit plugin. Add the prefix lib/ to your classpath by adding this configuration in your pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath> <-- don't know if this is needed -->
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
Then make sure to put your postgresjdbc.jar inside a folder called lib inside your plugin's folder.
Option 2. Add dependencies directly in your jar:
Note that this option will increase your plugin's jar size.
This can be done via Maven's assembly plugin:
<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>
<archive>
<manifest>
<mainClass>your.main.class</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
If you open your plugin's jar with a file compressor like 7-zip you should there should the driver's classes in it apart from your plugin ones.
Let me know if this solved your issue.

How to have a final jar with the dependency inside that jar in the jar format?

I need a configuration for Maven where all the libraries inside the project are in the final jar in the jar format... So i need to have jars inside the final jar. For that i can only use maven. I already tried without success with plugins like one-jar.
Thanks
To make a fat jar that includes all you jar files, add the following code to your pom.xml. When you clean and build the project this will automatically make a fat jar file. You need to give your main class inside <mainClass> tag. That's it.
<project>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>your.main.class</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>final-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Not sure for nested jar because I haven't tried yet.
But I have created .jar file with all project dependencies(specified in pom file)
Try following mvn command in terminal...
mvn org.apache.maven.plugins:maven-assembly-plugin:2.6:assembly -DdescriptorId=jar-with-dependencies package

Eclipse maven build path issue in case of custom sourceDirectory

I have converted an existing Java project to a Maven project and Maven builds everything perfectly when using the command line.
When I import the same project into Eclipse and compile (by right-clicking the project -> runs as Maven build, it still compiles without any issue.
However, I am not able to see the source folder. When I check the build path it gives warning - build path entry is missing.
I am not using standard src/main/java since I had a pre-existing folder structure for the project which could not be changed.
Here's my pom (notice the sourceDirectory tag):
<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.mycom</groupId>
<artifactId>maven</artifactId>
<version>17.4</version>
<name>maven</name>
<properties>
<projecrt.rootDir>../../java</projecrt.rootDir>
</properties>
<build>
<finalName>re</finalName>
<sourceDirectory>${projecrt.rootDir}</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifestEntries>
<Build-Version>${buildversion}</Build-Version>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
and here's my directory structure:
Src/java
----maven/pom.xml
----com/mycom/<...> // application code
You can use this build-helper-maven-plugin
And configure it in your pom file this way
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>some directory</source>
...
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
and now when you do mvn eclipse:eclipse the custom source folders will get added to the classpath entries in the .project file.
So, you wont need to do any manual configuration, your configuration will simply get build at run-time.
You can do the same for your test sources as well, if you have your tests in a custom source folder.
Hope this helps.
Once your Java project is imported in the Eclipse workspace, you can specify the actual src folder:
Click Open Java perspective Window > Open Perspective > Other... > Java to change to the Java perspective.
In Project layout group, change selection to Create separate source and output folders and edit Configure default... to modify Source folder name from "src" to "sources".
In the settings of your project (project => property => java build path), you can also change/add src folders:

How do I create an executable jar file including dependencies where the main class is in Test, using Maven

I am new to Maven and have a project with the following directory structure
project
-src
-main
-java
-org
-core
-starter.java
-test
-java
-org
-core
-testStarter.java
Both starter.java and testStarter.java are Main classes. However I wish to create an executable jar file (including dependencies) where testStarter.java is executed.
I added the following to my pom file:
<groupId>org</groupId>
<artifactId>proj</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>project</name>
<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>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>org.core.testStarter</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
<plugins>
</build>
However everytime I run mvn clean package, it creates a package with only the compiled classes in the main directory and not the test directory. Hence everytime I run the jar file, it does not run, since the testStarter.class does not exist in the created jar file.
Is there a way I can create either
1) One big jar file containing test and main classes while it executes only the test class
2) Only the test classes but all dependencies are included.
According to you pom.xml you have already had a big jar with all dependencies and correct classname in manifest.
All you need now is to include your test classes into artifact.
One big jar file containing test and main classes while it executes only the test class. You can specify you /src/test directory as another source directory (see Maven compile with multiple src directories).
Only the test classes but all dependencies are included. You can mark your test directory as the only source directory by using sourceDirectory tag in build section. But I guess, your tests depend on code in main, so this configuration could fail on compile time.
p.s. I strongly recommend you to create separate build-profile for such case, because it seems strange for me to have main method for jar in test class.
Well, this seems kinda strange, but what you can do is to put testStarter under main (I suppose this won't work because it has references to other classes under the testfolder, am I right?). Btw, use CapitalCamelCase class names, that's more Java-ish.
Alternatively, you can use test-jar to create a jar for the tests (this might work if you add the original jar to the Class-Path manifest property), or you can start hacking the whole assembly of your project, but I wouldn't recommend that.
What I'd suggest is rethinking your project layout and clarifying your requirements. Probably you won't need this process.
I'd recommend using the Maven OneJar Plugin,
look here: https://code.google.com/p/onejar-maven-plugin/
"Lets you build an executable jar with Maven2, containing all dependencies"
As for you scoping issue-- You need to move that Main class to the src folder so that it can be in the compile scope.
Cheers!
We do this in our project by using a assembly.xml with the maven-assembly-plugin.
In the POM we have:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptors>
<descriptor>src/main/resources/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>package-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
Then there is a assembly.xml in src/main/resources which tells how to build that assembly:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>bin</id>
<formats>
<format>jar</format>
</formats>
<!-- Adds dependencies to jar package under lib directory -->
<dependencySets>
<dependencySet>
<useProjectArtifact>true</useProjectArtifact>
<outputDirectory></outputDirectory>
<unpack>true</unpack>
</dependencySet>
</dependencySets>
</assembly>

Why Maven Assembly Plugin does not include my project files in the jar with dependencies ?

I am using maven assembly plug in to package my project with all its dependency so i can run a simple java -jar myproject.jar and be able to run the project. However when I ran the jar it told me
Error: Could not find or load main class com.project.ServerStart
Then I unzipped the .jar file and found that the assembly does not include my project files, which is ridiculous !
When packaging the project I receive this warning
[WARNING] Cannot include project artifact: Amjar:amjar:pom:0.2; it doesn't have an associated file or directory.
This is my plugin config
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<finalName>amjar-${project.version}</finalName>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.project.ServerStart</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
What am I doing wrong ?
From the warning you've included in your question:
[WARNING] Cannot include project artifact: Amjar:amjar:pom:0.2; it doesn't have an associated
I'd guess that you've got the packaging in your pom.xml set to pom.
This is fine if your module is simply packaging a set of dependencies or resource files, however, if you also want Maven to create a jar containing the classes in you module you will need to set the packaging to jar.

Categories