How to create a simple Restful Web Service using Jersey JAX RS API

25 June 2012 By Praveen Macherla 70,892 views 49 Comments
49 Flares Twitter 6 Facebook 27 Google+ 16 49 Flares ×

RESTful web services are based on the way how our web works. Our very own world wide web (www) – the largest distributed application – is based on an architectural style called REST – Representational State Transfer. REST is neither a standard nor a protocol. It is just an architectural style like say for example client-server architecture (client-server is neither a standard nor a protocol). Web services following this architectural style are said to be RESTful Web services.

RESTful web services are based on HTTP protocol and its methods PUT, GET, POST, and DELETE. These web services are better integrated with HTTP than SOAP-based services are, and as such do not require XML SOAP messages or WSDL service definitions.

Java provides support for Restful web services through Java API for RESTful Web Services JAX-RS. The complete specification is available as JSR 311. JAX-RS is an annotation-based API for implementing RESTful web services, based on HTTP, in Java. Essentially, classes and methods are annotated with information that enables a runtime to expose them as resources – an approach that is very different from the one exposed by the servlet programming model. A runtime that implements JAX-RS mediates between the HTTP protocol and the Java classes, taking into account URIs, requested and accepted content types, and HTTP methods. Jersey is a production quality reference implementation of JAX-RS API.

Project Description

  • In this example, we create a simple Java Calculator class with operations ‘add’ and ‘subtract’.
  • We expose these as restful web services which accepts HTTP GET Requests and sends the response as XML or Plain Text.
  • The restful web service is made available at http://localhost:9999/calcrest/calc/add/ and http://localhost:9999/calcrest/calc/sub/
  • We send the parameters in the URI itself. For example, to add 20 and 30, the URI is, http://localhost:9999/calcrest/calc/add/20/30
  • We then create a web service client which sends a HTTP GET Request to the mentioned URI and the response (result of the invoked web service) is displayed.

Environment Used

Creating and Publishing Restful Web Service

  1. Create a Java Project ‘CalcJAXRS’.
  2. In the Project Build Path add the following jars from the downloaded Jersey zip file.
    • Jersey core
    • Jersey server
    • Jersey client
    • JSR 311 API
    • asm 3.x
  3. Create a package ‘com.theopentutorials.jaxrs.calc’
  4. Create a Java class ‘CalcREST’ and type the following code.
    package com.theopentutorials.jaxrs.calc;
    
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
    
    @Path("/calc")
    public class CalcREST {
    
    	@GET
    	@Path("/add/{a}/{b}")
    	@Produces(MediaType.TEXT_PLAIN)
    	public String addPlainText(@PathParam("a") double a, @PathParam("b") double b) {
    		return (a + b) + "";
    	}
    	
    @GET
    	@Path("/sub/{a}/{b}")
    	@Produces(MediaType.TEXT_PLAIN)
    	public String subPlainText(@PathParam("a") double a, @PathParam("b") double b) {
    		return (a - b) + "";
    	}
    
    	@GET
    	@Path("/add/{a}/{b}")
    	@Produces(MediaType.TEXT_XML)
    	public String add(@PathParam("a") double a, @PathParam("b") double b) {
    		return "<?xml version=\"1.0\"?>" + "<result>" +  (a + b) + "</result>";
    	}
    	
    	@GET
    	@Path("/sub/{a}/{b}")
    	@Produces(MediaType.TEXT_XML)
    	public String sub(@PathParam("a") double a, @PathParam("b") double b) {
    		return "<?xml version=\"1.0\"?>" + "<result>" +  (a - b) + "</result>";
    	}
    }
    
  5. @Path may be used on classes and such classes are referred to as root resource classes. @PATH(“calc”) sets the path to the base URI + /calc. The base URI consists of the host, port and any context. We will set this base URI on creating the server.
  6. @Path may also be used on methods of root resource classes. This enables common functionality for a number of resources to be grouped together and potentially reused. So for example @PATH(“/add”) on the method signature indicates the URI path for this method to be invoked is base URI + /calc/add.
  7. To retrieve the parameters from the URI and get those values as variables, we use URI Path Templates which are variables enclosed within curly braces “{“ and “}” and are replaced at runtime to respond to a request based on the substituted URI. To obtain the value of the variable the @PathParam may be used on method parameter of a request method.
    • For example, for the relative URI /calc/add/20/30 with @Path(“/add/{a}/{b}”) and method signature String add(@PathParam(“a”) double a, @PathParam(“b”), the values 20 and 30 will be assigned to the variables a and b respectively.
  8. @GET annotation is used to indicate that the annotated method will be invoked in response to a HTTP GET request.
  9. @Produces annotation is used to specify the MIME media types of representations a resource can produce and send back to the client. In our example, our web service will produce representations identified by the MIME media type “text/plain” and “text/xml” which are specified using the static fields TEXT_PLAIN and TEXT_XML of MediaType class.
  10. Now we need to start a HTTP server to publish our web service and accept requests.
  11. Create a class “CalcRESTStartUp” and type the following code.
    package com.theopentutorials.jaxrs.calc;
    
    import java.io.IOException;
    import com.sun.jersey.api.container.httpserver.HttpServerFactory;
    import com.sun.net.httpserver.HttpServer;
    
    public class CalcRESTStartUp {
    
    	static final String BASE_URI = "http://localhost:9999/calcrest/";
    
    	public static void main(String[] args) {
    		try {
    			HttpServer server = HttpServerFactory.create(BASE_URI);
    			server.start();
    			System.out.println("Press Enter to stop the server. ");
    			System.in.read();
    			server.stop(0);
    		} catch (IllegalArgumentException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    }
    
  12. We use the Jersey’s HttpServerFactory to create a server at the mentioned BASE URI. Make sure that port number 9999 is not used by any other application. If so, use any other unused port.
  13. Run this class “CalcRESTStartup” as Java Application.
  14. Our class “CalcREST” should be automatically identified as root resource class and should be deployed.
  15. To test it, open a browser and type the following URL

    http://localhost:9999/calcrest/application.wadl

    . A Web Application Description Language (WADL) should be displayed. This is similar to WSDL. WADL is not standardized by W3C.

  16. To test the service we can type the following URLs in the browser
    http://localhost:9999/calcrest/calc/add/20/30/

    and

    http://localhost:9999/calcrest/calc/sub/20/30/

  17. The output on the browser will be in XML format even though we have our service produce plain text. This is because of the accept type HTTP header sent by the browser. By default the browser sends the text/html accept type and other xhtml and xml types. Since our service does not accept html and seeing that the browser accepts XML, it produces the output in XML.

Creating a Restful Web Service Client

Even though the web service is accessible via browser, the primary purpose of web service is for machines to communicate. So let us access this web service programmatically by creating a client.

  1. Create a new package “com.theopentutorials.jaxrs.calc.client”.
  2. Create a new class “CalcRESTClient” in that package and type the following code.
    package com.theopentutorials.jaxrs.calc.client;
    
    import javax.ws.rs.core.MediaType;
    import com.sun.jersey.api.client.Client;
    import com.sun.jersey.api.client.ClientResponse;
    import com.sun.jersey.api.client.WebResource;
    import com.sun.jersey.api.client.config.ClientConfig;
    import com.sun.jersey.api.client.config.DefaultClientConfig;
    
    public class CalcRESTClient {
    	static final String REST_URI = "http://localhost:9999/calcrest";
    	static final String ADD_PATH = "calc/add";
    	static final String SUB_PATH = "calc/sub";
    	
    	public static void main(String[] args) {
    		
    		int a = 122;
    		int b = 34;
    		
    		ClientConfig config = new DefaultClientConfig();
    		Client client = Client.create(config);
    		WebResource service = client.resource(REST_URI);
    		
    		WebResource addService = service.path(ADD_PATH).path(a + "/" + b);
    		System.out.println("Add Response: " + getResponse(addService));
    		System.out.println("Add Output as XML: " + getOutputAsXML(addService));
    		System.out.println("Add Output as Text: " + getOutputAsText(addService));
    		System.out.println("---------------------------------------------------");
    		
    		WebResource subService = service.path(SUB_PATH).path(a + "/" + b);
    		System.out.println("Sub Response: " + getResponse(subService));
    		System.out.println("Sub Output as XML: " + getOutputAsXML(subService));
    		System.out.println("---------------------------------------------------");
    
    	}
    	
    	private static String getResponse(WebResource service) {
    		return service.accept(MediaType.TEXT_XML).get(ClientResponse.class).toString();
    	}
    	
    	private static String getOutputAsXML(WebResource service) {
    		return service.accept(MediaType.TEXT_XML).get(String.class);
    	}
    	
    	private static String getOutputAsText(WebResource service) {
    		return service.accept(MediaType.TEXT_PLAIN).get(String.class);
    	}
    }
    
  3. In the client, we create a web resource object based on the provided URI and a default client config.
  4. We specify the “add” and “sub” resource paths and include parameters “a” and “b” to it.
  5. We also need to specify the accept type of the client request and HTTP method as GET by using the methods “accept” and “get”. The “get” method parameter specifies the format to convert the output.
  6. Run this client application.

Output

Add Response: GET http://localhost:9999/calcrest/calc/add/122/34 returned a response status of 200 OK
Add Output as XML: 156.0
Add Output as Text: 156.0
—————————————————
Sub Response: GET http://localhost:9999/calcrest/calc/sub/122/34 returned a response status of 200 OK
Sub Output as XML: 88.0
—————————————————

Project Structure

Tags: , , , , , , , , , ,

  • Pingback: Links for July 1st through July 5th

  • srinath

    Excellent tutorial. It is very easy to understand. Thank you so much.

  • Ankur Chauhan

    very nice tutorial……..

  • Ankur Chauhan

    EveryThing in this tutorial is good but one jar file must be added as–
    JAXB-API.jar

    If I am wrong then plz correct me…

    Thanks

    • http://theopentutorials.com Praveen Macherla

      You only need Jersey jars. If you use Java 6 and above you do not need jaxb jar as JAXB is part of Java.

  • sanjeev

    When server and client are running in windows ,there are no problems at all.

    Problem is—–>

    Hosted Rest server program in linux box.
    Tried running client program from windows PC.

    Client is giving connection refused exception.why?

    • http://theopentutorials.com Praveen Macherla

      Open the port in linux firewall.

      • sanjeev

        Thanks a ton Praveen. I made the necessary changes in linux box.But ,it is still showing exception as:

        Exception in thread “main” com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused: connect
        at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:151)
        at com.sun.jersey.api.client.Client.handle(Client.java:648)
        at com.sun.jersey.api.client.WebResource.handle(WebResource.java:680)
        at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
        at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:507)
        at com.poc.jaxrsApproach.client.RESTClient.getResponse(RESTClient.java:58)
        at com.poc.jaxrsApproach.client.RESTClient.callApproveService(RESTClient.java:52)
        at com.poc.jaxrsApproach.client.RESTClient.main(RESTClient.java:26)
        Caused by: java.net.ConnectException: Connection refused: connect
        at java.net.PlainSocketImpl.socketConnect(Native Method)
        at java.net.PlainSocketImpl.doConnect(Unknown Source)
        :
        :

        Can you help me on this?

        • http://theopentutorials.com Praveen Macherla

          From the client machine’s browser check the wsdl is accessible and also see whether any response is shown in the browser for REST urls. If not then there is a firewall issue.

          • sanjeev

            ok..thanks.It seems to be a firewall problem although ‘iptables’ in linux box is not denying my IP explicitly…Curious,why the prblem persists?…However,as you suggested,url is not accessible to see the wsdl file.

            Is there is anything beyond these common troubleshooting?…

          • http://theopentutorials.com Praveen Macherla

            Disable the firewall. See the linux documentation for the appropriate command.

        • Lakhan

          First start the server and then run client program..

  • sanjeev

    thanks praveen…We are working on a linux hardware which is designed by our hardware team…Probably,they made the OS a bit headless to tackle so many other priorities to suit their hardware needs…I told abt the firewall problem and they are working on it…

    By the way,can you provide a simple tutorial to implement REST Websrvces using Apache axis?..Is it mandatory to use Jersey..?

    Can you provide a simple tutorial of REST using Axis (without jersey)..?It would be of great help .

  • sanjeev

    Can you provide a simple tutorial of JAX-RS using apache CXF?

  • Venkat

    Hi Praveen
    I got the below error in console when run this URL: http://localhost:9999/calcrest/calc/add/20/30

    Exception in thread “pool-1-thread-4″ java.lang.IncompatibleClassChangeError: Class javax.ws.rs.core.Response$Status does not implement the requested interface javax.ws.rs.core.Response$StatusType
    at com.sun.jersey.spi.container.ContainerResponse.getStatus(ContainerResponse.java:564)
    at com.sun.jersey.spi.container.ContainerResponse$CommittingOutputStream.commitWrite(ContainerResponse.java:156)
    at com.sun.jersey.spi.container.ContainerResponse$CommittingOutputStream.write(ContainerResponse.java:133)
    at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)

    pls help

  • Venkat

    Hi Praveen,
    I am pasting the full stack trace below…

    Exception in thread “pool-1-thread-1″ java.lang.IncompatibleClassChangeError: Class javax.ws.rs.core.Response$Status does not implement the requested interface javax.ws.rs.core.Response$StatusType
    at com.sun.jersey.spi.container.ContainerResponse.getStatus(ContainerResponse.java:564)
    at com.sun.jersey.spi.container.ContainerResponse$CommittingOutputStream.commitWrite(ContainerResponse.java:156)
    at com.sun.jersey.spi.container.ContainerResponse$CommittingOutputStream.write(ContainerResponse.java:133)
    at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
    at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
    at sun.nio.cs.StreamEncoder.implFlush(Unknown Source)
    at sun.nio.cs.StreamEncoder.flush(Unknown Source)
    at java.io.OutputStreamWriter.flush(Unknown Source)
    at java.io.BufferedWriter.flush(Unknown Source)
    at com.sun.jersey.core.util.ReaderWriter.writeToAsString(ReaderWriter.java:191)
    at com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider.writeToAsString(AbstractMessageReaderWriterProvider.java:128)
    at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:88)
    at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:58)
    at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:306)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1437)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339)
    at com.sun.jersey.server.impl.container.httpserver.HttpHandlerContainer.handle(HttpHandlerContainer.java:191)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Unknown Source)
    at sun.net.httpserver.AuthFilter.doFilter(Unknown Source)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Unknown Source)
    at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(Unknown Source)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Unknown Source)
    at sun.net.httpserver.ServerImpl$Exchange.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

    • http://theopentutorials.com Praveen Macherla

      Use proper jar files as mentioned in the post.

      • Venkat

        Hi Praveen
        Thnx a ton..it got resolved, the problem was I was using jersey 1.8 jars
        Thnx again for the most lucid example for RESTful WS.

  • sanjeev

    Hi praveen,
    Can you provide a simple tutorial of JAX-RS using apache CXF?
    It would be of great help…

  • swati

    Hi Praveen,

    Thanks for this great tutorial.Its working like charm.

    But I am facing little problem.When I try to access “http://localhost:9998/testServer/sample/get” behind proxy it is accessible all time even after stopping the server,or closing eclipse or system completely.I have tried doing it when I am not behind proxy and it works perfectly.I can start and even stop the server.Can you please help with it?

    • http://theopentutorials.com Praveen Macherla

      Possibly the proxy or your browser may be caching the requests. Try to disable it.

  • sanjeev

    How to use @QueryParam annotation and @MatrixParam annotation in JAX-RS?what exactly are these semantically?Can you explain me?

  • Pingback: Starting with Apache Jersey :) « Rohit Tambat

  • Azahrudhin

    Thank you very much , Your examples are simple and easy to grasp.
    I have configured the webservice, it is working fine for PLAIN_TEXT,
    and in other cases getting the error.

    returned a response status of 406 Not Acceptable
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:686)
    at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
    at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:507)

    • Pradnya Lele

      For TEXT_XML, you get this error if the response XML being sent or received is not in proper format. I added encoding attribute to the above XML response and it worked as expected.

  • praveen d

    @sanjeev goto mkyong site u ll get @QueryParam and @MatrixParam examples for jax-rs

  • Daniel

    Thanks, works fine in ubuntu 12.04 with Oracle JDK 7.

  • darshan

    Thanks for the tutorial and it is working fine but when iam giving my ip instead of localhost I am getting “Connection refused error” .Please tell me why this is happening. I have changed the server setting localhost to my ip

    • http://theopentutorials.com Praveen Macherla

      Turn off firewall. That could be the issue.

  • vitaliy

    it is the best description which i find. Thanks a lot! Could you please help me? How can i use it, if server use authorization?

  • Danny

    Hi Praveen, I copied/pasted your codes and I keep getting red error lines in CalcRESTStartup class in lines 5, 13, and 17 saying it’s “restricted”. It wouldn’t even let me run it as a java application or any other as a matter of fact. Could you please tell me what I’m doing wrong here? I am using the latest jersey archive 1.17

    • http://theopentutorials.com Praveen Macherla

      Go to the Build Path settings in the project properties. Remove the JRE System Library. Add it back. Select “Add Library” and select the JRE System Library.

  • vj

    Hi Pravin , I am getting below error while hitting the service…m kindaa new to web services…..please let me know what needs to be done…..thanks, in advance
    ——————————————————————————–

    type Status report

    message /calcrest/application.wadl

    description The requested resource (/calcrest/application.wadl) is not available.

    ——————————————————————————–

    JBoss Web/2.1.3.GA

  • Gary Fehr

    I like tutorials that manually go through the steps instead of throwing you into a complicated container environment where it’s not clear to a beginner what all is taking place. This was at the perfect level for what I needed to know about RESTful services. Thanks for a great tutorial!

  • Anand Murugan

    I have used your code. This is really helpful. And I am creating simple REST Client Server through this. I am in need of the information how to transfer one ZIP file from client to Server and get that file in the server. Could you please tell me how to do this?

  • http://poolofjava.blogspont.in ishwar

    hi…
    This example is excellent for Rest in java..

  • zahmoul

    thaaaank you soo much :D

  • Nadeem

    Sorry to say, the url for the jar files is not working and I have hard time to find them individually and work it with my java version.. can you update the link and necessary sources needed…. I am using jdk 7

  • Kiran

    Wonderful Tutorial. Thanks a lot.

  • Prakash

    Nicely explained and good job Praveen.

    As a side note, what is powering your website ? Is it wordpress ?

    • http://theopentutorials.com Praveen Macherla

      Yes

  • marcel

    Can you pls make a tutorial with put and post method?

  • Balamurugan

    i got the following error while running:

    Jul 25, 2013 5:09:38 PM com.sun.jersey.api.core.ScanningResourceConfig logClasse
    s
    INFO: Root resource classes found:
    class com.firstrest.HelloREST
    Jul 25, 2013 5:09:38 PM com.sun.jersey.api.core.ScanningResourceConfig logClasse
    s
    INFO: Provider classes found:
    class org.codehaus.jackson.jaxrs.JsonMappingExceptionMapper
    class org.codehaus.jackson.jaxrs.JsonParseExceptionMapper
    class org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider
    class org.codehaus.jackson.jaxrs.JacksonJsonProvider
    Exception in thread “main” com.sun.jersey.api.container.ContainerException: No W
    ebApplication provider is present
    at com.sun.jersey.spi.container.WebApplicationFactory.createWebApplicati
    on(WebApplicationFactory.java:69)
    at com.sun.jersey.api.container.ContainerFactory.createContainer(Contain
    erFactory.java:160)
    at com.sun.jersey.api.container.ContainerFactory.createContainer(Contain
    erFactory.java:264)
    at com.sun.jersey.api.container.ContainerFactory.createContainer(Contain
    erFactory.java:246)
    at com.sun.jersey.api.container.httpserver.HttpServerFactory.create(Http
    ServerFactory.java:117)
    at com.sun.jersey.api.container.httpserver.HttpServerFactory.create(Http
    ServerFactory.java:92)

    Please help me to resolve this

  • Naveen Babu

    Hi,

    I am using JDK 1.5. Could you let me know which version of Jersey is compatible with JDK 1.5.

    Regards,
    Naveen Babu Gorantla

  • Bhanu

    Thanks a million. I was stuck with this over 3 days. Any idea about how to use OAauth within this framework.

  • maruti kutre

    Nice article…

  • Thirumala Reddy

    Hi,
    i got this error How to i resolve this can plz help me….

    com.sun.jersey.api.core.ScanningResourceConfig init
    INFO: No provider classes found.
    Exception in thread “main” com.sun.jersey.api.container.ContainerException: No WebApplication provider is present
    at com.sun.jersey.spi.container.WebApplicationFactory.createWebApplication(WebApplicationFactory.java:69)
    at com.sun.jersey.api.container.ContainerFactory.createContainer(ContainerFactory.java:160)
    at com.sun.jersey.api.container.ContainerFactory.createContainer(ContainerFactory.java:264)
    at com.sun.jersey.api.container.ContainerFactory.createContainer(ContainerFactory.java:246)
    at com.sun.jersey.api.container.httpserver.HttpServerFactory.create(HttpServerFactory.java:117)
    at com.sun.jersey.api.container.httpserver.HttpServerFactory.create(HttpServerFactory.java:92)
    at com.thiru.jaxrs.calc.ServerStart.main(ServerStart.java:11)

  • byenare

    Very nice tutorial, thank you very much.

  • javabinder.blogspot.in

    thnks..nice post !!!!