Enterprise Java

Creating Web Services and a Rest Server with JAX-RS and Jetty

Creating a WebService in Java is remarkably easy. To add it to a ServletContainer and deploy it to an embedded WebServer is only a few more lines of code.

Let’s create a simple calculator with a couple of functions as an example of a WebService. The calculator will compute the squareRoot and square of any number.  It will return a simple JSON response with the name of the action, the input and the output.

Before we start this is the Gradle configuration you will need:
 
 

apply plugin: 'java'

version = '1.0'

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.glassfish.jersey.core', name: 'jersey-server', version: '2.7'
    compile group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet-core', version: '2.7'
    compile group: 'org.glassfish.jersey.containers', name: 'jersey-container-jetty-http', version: '2.7'
    compile group: 'org.glassfish.jersey.media', name: 'jersey-media-moxy', version: '2.7'
    compile group: 'org.eclipse.jetty.aggregate', name: 'jetty-all', version: '9.3.0.M1'
    testCompile group: 'junit', name: 'junit', version: '4.11'
}

This is the code for the Calculator:

package example;


import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

@Path("calculator")
public class Calculator {
    @GET
    @Path("squareRoot")
    @Produces(MediaType.APPLICATION_JSON)
    public Result squareRoot(@QueryParam("input") double input){
        Result result = new Result("Square Root");
        result.setInput(input);
        result.setOutput(Math.sqrt(result.getInput()));
        return result;
    }

    @GET
    @Path("square")
    @Produces(MediaType.APPLICATION_JSON)
    public Result square(@QueryParam("input") double input){
        Result result = new Result("Square");
        result.setInput(input);
        result.setOutput(result.getInput()*result.getInput());
        return result;
    }

    static class Result{
        double input;
        double output;
        String action;

        public Result(){}

        public Result(String action) {
            this.action = action;
        }

        public String getAction() {
            return action;
        }

        public void setAction(String action) {
            this.action = action;
        }

        public double getInput() {
            return input;
        }

        public void setInput(double input) {
            this.input = input;
        }

        public double getOutput() {
            return output;
        }

        public void setOutput(double output) {
            this.output = output;
        }
    }
}

The annotations determine the type of REST action to be applied to the method @GET, @PUT etc. The @Path annotation determines the URI of the request and the @Produces annotation determines how the response will be returned.  In our case we choose JSON, the conversion of which is all handled seamlessly.

In order to deploy our WebService we need a ServletContainer for which we will use Jersey and a WebServer into which we can drop the container for which we will use Jetty.

This is the code for the RestServer:

package example;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;


public class RestServer {
    public static void main(String[] args) throws Exception {
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.setContextPath("/");

        Server jettyServer = new Server(8080);
        jettyServer.setHandler(context);

        ServletHolder jerseyServlet = context.addServlet(
                org.glassfish.jersey.servlet.ServletContainer.class, "/*");
        jerseyServlet.setInitOrder(0);

        jerseyServlet.setInitParameter(
                "jersey.config.server.provider.classnames",
                Calculator.class.getCanonicalName());

        try {
            jettyServer.start();
            jettyServer.join();
        } finally {
            jettyServer.destroy();
        }
    }
}

Once you have run the RestServer you will be able to test it with this URL.

  • http://localhost:8080/calculator/squareRoot?input=16

A really nice way to run queries from IntelliJ is to use the inbuilt REST Client which can be found under the tools menu.

Screen Shot 2015-03-09 at 15.40.00

When you run the REST Client you will get this Response:

Screen Shot 2015-03-09 at 15.41.33

It’s a really easy way to test a RESTful server.

Daniel Shaya

Daniel has been programming in Java since it was in beta. Working predominantly in the finance industry he has created real time trading and margin risk applications. He is currently a director at OpenHFT where we are building next generation Java low latency products.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

9 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Himanshu
Himanshu
8 years ago

Hi,

When i am compiling RestServer.java, its giving me error.

example/RestServer.java:21: error: cannot find symbol
Calulator.class.getCanonicalName());

How do you acesssing class name Calculator ?

Please help.

Geff Chang
8 years ago
Reply to  Himanshu

Shouldn’t “Calulator.class” be “Calculator.class”?

Nick
Nick
7 years ago

Thanks! Great post!

Gagandeep Singh
Gagandeep Singh
7 years ago

Thank you, one of the only tutorials that actually worked

crossfire
crossfire
7 years ago

Thank man for the great tutorial, works perfect on Android OS :)

Andre Guariento
Andre Guariento
6 years ago

Hi, good idea but when i’m need import multiple class?

Matthew Campbell
Matthew Campbell
5 years ago

Alas, not working for me:

Mar 01, 2019 9:14:14 PM org.glassfish.jersey.server.ApplicationHandler initialize
INFO: Initiating Jersey application, version Jersey: 2.7 2014-03-12 18:11:31…
2019-03-01 21:14:15.088:WARN:oejuc.AbstractLifeCycle:main: FAILED o.e.j.s.ServletContextHandler@176b3f44{/,null,STARTING}: java.lang.NoClassDefFoundError: javax/xml/bind/UnmarshalException
java.lang.NoClassDefFoundError: javax/xml/bind/UnmarshalException
at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3167)

Akash
Akash
3 years ago

Great Explanation, Worked for me.

Ted
Ted
1 year ago
Reply to  Akash

there is any example that we can use a MySQL database and apply CRUD operations

Back to top button