In this tutorial, we create a simple Java REST application with Jersey and embedded Jetty. We show how to create an uber JAR.
last modified July 13, 2020
In this tutorial, we create a simple Java REST application with Jersey and embedded Jetty. We also show how to pack the application into an executable uber JAR.
Jersey is an open source framework for developing RESTful Web Services in Java. It is a reference implementation of the Java API for RESTful Web Services (JAX-RS) specification.
Jetty is a Java HTTP (Web) server and Java Servlet container. It can be easily embedded in devices, tools, frameworks, application servers, and clusters.
A RESTFul application creates a system (API) that follows the REST architectural style, which is used for designing networked applications. RESTful applications use HTTP requests perform CRUD (Create/Read/Update/Delete) operations on resources.
The following is a very simple Java RESTful application created with Jersey and embedded Jetty server.
$ tree . ├── pom.xml └── src ├── main │ ├── java │ │ └── com │ │ └── zetcode │ │ ├── app │ │ │ └── Main.java │ │ └── res │ │ └── MyMessage.java │ └── resources └── test └── java
This is our project structure.
The project consists of two Java source files and the Maven POM file.
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.zetcode</groupId>
<artifactId>JerseyJettyEx</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>JerseyJettyEx</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jetty-http</artifactId>
<version>2.25</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>9.4.0.v20161208</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.25</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>2.25</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.4.0.v20161208</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.0.v20161208</version>
</dependency>
</dependencies>
<build>
<finalName>JerseyJettyEx</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.zetcode.app.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
In the pom.xml file, we have necessary Jersey and Jetty dependencies. We also use the exec-maven-plugin, which is used for executing Java programs.
MyMessage
package com.zetcode.res;
import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType;
@Path(“msg”) public class MyMessage {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getMessage() {
return "My message\n";
}
}
We define a resource. It responds to a HTTP GET request and returns plain text.
@Path(“msg”) public class MyMessage {
The @Path annotation identifies the URL path to which the resource responds.
com/zetcode/Main.java
package com.zetcode.app;
import java.util.logging.Level; import java.util.logging.Logger; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.glassfish.jersey.servlet.ServletContainer;
public class Main {
public static void main(String[] args) {
Server server = new Server(8080);
ServletContextHandler ctx =
new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
ctx.setContextPath("/");
server.setHandler(ctx);
ServletHolder serHol = ctx.addServlet(ServletContainer.class, "/rest/*");
serHol.setInitOrder(1);
serHol.setInitParameter("jersey.config.server.provider.packages",
"com.zetcode.res");
try {
server.start();
server.join();
} catch (Exception ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} finally {
server.destroy();
}
}
}
In Main.java, we set up and start Jetty.
Server server = new Server(8080);
Jetty server is started listening on 8080 port.
ServletContextHandler ctx = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
The next step is to create a ServletContextHandler object.
ctx.setContextPath(”/”);
With the setContextPath method we set the path to which the application is mapped.
ServletHolder serHol = ctx.addServlet(ServletContainer.class, “/rest/*”);
We add the Jersey ServletContainer to the Jetty servlet holder. This essentially joins Jersey with Jetty.
serHol.setInitParameter(“jersey.config.server.provider.packages”, “com.zetcode.res”);
Here we tell Jersey where to look for resources.
In the following steps, we build and run the application.
$ mvn package
We build the application with mvn package command.
$ mvn exec:java
The application is started with mvn exec:java command.
$ curl localhost:8080/rest/msg My message
We use curl tool to issue a HTTP GET request to our resource.
Uber JAR is a JAR that contains both our package and all its dependencies in one single JAR file. Such JAR is also called a fat JAR.
maven-shade-plugin
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.4.3</version> <configuration> <createDependencyReducedPom>true</createDependencyReducedPom> <filters> <filter> <artifact>:</artifact> <excludes> <exclude>META-INF/.SF</exclude> <exclude>META-INF/.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> </configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>com.zetcode.app.Main</Main-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
With the maven-shade-plugin we can create one executable JAR containing all dependencies.
<transformer implementation=“org.apache.maven.plugins.shade.resource.ManifestResourceTransformer”> <manifestEntries> <Main-Class>com.zetcode.app.Main</Main-Class> </manifestEntries> </transformer>
In order to make the JAR executable, it must have a main class in the manifest. This is achieved with the ManifestResourceTransformer.
$ mvn clean package
We clean and build the application.
$ java -jar target/JerseyJettyEx-1.0-SNAPSHOT.jar
We use this command to start the application.
In this tutorial, we have created a simple Java REST application with Jersey and embedded Jetty. We have shown how to create an uber JAR.