Reputation: 869
I want to create simple Jersey 2 Client app with Maven (Server app is also implemented and runs).
My pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.client</groupId>
<artifactId>RestClient</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>RestClient</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.13</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
java code
package com.client;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
import javax.ws.rs.client.Invocation.Builder;
public class App
{
public static void main( String[] args )
{
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:8080").path("simple-service-webapp/rest/myresource");
Builder builder = target.request();
//Response response = builder.get();
String result = builder.get(String.class);
System.out.println(target.getUri().toString());
System.out.println("Result=" + result);
}
}
I build app by command mvn package and everything pass. Then, I run app by java -cp target/RestClient-1.0-SNAPSHOT.jar com.client.App and then error occurs:
Exception in thread "main" java.lang.NoClassDefFoundError: javax/ws/rs/client/ClientBuilder
at com.client.App.main(App.java:20)
Caused by: java.lang.ClassNotFoundException: javax.ws.rs.client.ClientBuilder
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
... 1 more
It seems that libraries are not included, because files tree of projeckt looks:
.
├── pom.xml
├── src
│ ├── main
│ │ └── java
│ │ └── com
│ │ └── client
│ │ └── App.java
│ └── test
│ └── java
│ └── com
│ └── client
│ └── AppTest.java
└── target
├── classes
│ └── com
│ └── client
│ └── App.class
├── generated-sources
│ ├── annotations
│ └── test-annotations
├── maven-archiver
│ └── pom.properties
├── RestClient-1.0-SNAPSHOT.jar
├── surefire
├── surefire-reports
│ ├── com.client.AppTest.txt
│ └── TEST-com.client.AppTest.xml
└── test-classes
└── com
└── client
└── AppTest.class
Where did I mistake? Thanks.
Upvotes: 4
Views: 15570
Reputation: 773
The other thing you can do is package your dependencies into a fat jar. The maven-assembly-plugin will do this for you automatically.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>YOUR MAIN CLASS HERE</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>
You can create a custom assembly specification if you need anything more sophisticated that this basic mode in which all dependencies are included in the jar.
There is also the maven-shade-plugin, which is also more configurable.
Another useful tool is:
mvn dependency:tree -Dverbose
to see exactly what your dependencies are.
Upvotes: 0
Reputation: 209142
You need to copy the dependencies to from your local repo into you project (or anywhere really, wherever you want to -cp to). For this, you can use the maven-dependency-plugin. Just add this to the <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.9</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>
What the above plugin configuration will do is copy all the dependencies to target/lib
.
The easiest way to run the jar as an executable is to also set the Class-Path
in the MANIFEST.MF
, through Maven. For that we can use the maven-jar-plugin. So add this to the <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<configuration>
<archive>
<index>true</index>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.client.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Also you will need to get rid of the <scope>provided</scope>
for the Jersey client dependency. With this scope, Maven will not add the jars to the classpath.
After doing this, you can simply run java -jar your-jar.jar
, without the need to -cp anything, as all the jars are specified in the Manifest. It should look something like
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: XxxxXxxxx
Class-Path: lib/jersey-client-2.13.jar lib/jersey-common-2.13.jar lib/
javax.annotation-api-1.2.jar lib/jersey-guava-2.13.jar lib/osgi-resou
rce-locator-1.0.1.jar lib/javax.ws.rs-api-2.0.1.jar lib/hk2-api-2.3.0
-b10.jar lib/hk2-utils-2.3.0-b10.jar lib/aopalliance-repackaged-2.3.0
-b10.jar lib/javax.inject-2.3.0-b10.jar lib/hk2-locator-2.3.0-b10.jar
lib/javassist-3.18.1-GA.jar
Created-By: Apache Maven 3.0.5
Build-Jdk: 1.8.0_20
Main-Class: com.client.App
Upvotes: 3
Reputation: 34856
You marked your jersey dependency as provided, therefore it won't be included in the output, because when the dependency is provided, it is assumed that it is available in the environment (for example by application server).
Try removing the <scope>provided</scope>
from your Maven dependency or include the jersey jar on the classpath using the -cp
parameter when you run your program.
Upvotes: 1