Jersey application with embedded Jetty
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.
RESTFul application
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.
Code example
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.
<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.
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.
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.
Building and running application
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
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.
<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.