Saturday, February 5, 2011

RESTful webservices using JAX-RS

This tutorial demonstrates how RESTful services are created using JAX-RS. We'll be using Glassfish as our primary application server. This tutorial is limited to reading representational objects. For implementation information about CRUD-operations and REST, I recommend the following online book.

The tutorial consists of the following steps:

1. Define URLs
2. Define data format
3. Configure JAX-RS in web.xml
4. Create REST POJO's
5. Test application with URLs


1. Define URLs

The first step is define the URLs we'll be using in accessing the REST objects. For this example, we define four relative URLs:

1. All departments: /departments/
2. Department by ID: /departments/{id}
3. All employees: /employees/
4. Employee by ID: /employees/{id}

The {id} is the ID parameter, which should be an integer number.


2. Define data format

In this step we have to choose how we want to format the object for the client. Commonly, this will be either XML or JSON. The latter one is definitely preferred if AJAX is handling the output. But for this tutorial, we'll be using XML.


<department id="12345">
<link rel="self" href="/departments/12345" />
<name>Solutions Development</name>
</department>



<employee id="1580">
<link rel="self" href="/employees/1580" />
<firstName>Gin Lung</firstName>
<lastName>Cheng</lastName>
<department id="12345">
<link rel="self" href="/departments/12345" />
</department>
</employee>



3. Configure JAX-RS in web.xml

Now, we need to configure the application server to support RESTful services by putting the following XML-code in the web.xml file inside the <web-app>-element:


<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/rs/*</url-pattern>
</servlet-mapping>


This tells our application server that we want URLs that start with /rs/ are handled by the JAX-RS Servlet.


4. Create REST POJO's

Create the POJO's that contain the methods behind the URLs. For demonstration purposes, the output is hardcoded. Normally, content is retrieved from a database, and converted to XML with JAX-B.

DepartmentService.java

package com.javaeenotes;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

@Path("/departments")
public class DepartmentService {

@GET
@Produces("application/xml")
public String showDepartments() {
// Return all departments.
return "<department id=\"12345\">"
+ "<link rel=\"self\" href=\"/departments/12345\" />"
+ "<name>Solutions Development</name>"
+ "</department>";
}

@Path("{id}")
@GET
@Produces("application/xml")
public String showDepartment(@PathParam("id") int id) {
// Return department by ID.
return "<department id=\"" + id + "\">"
+ "<link rel=\"self\" href=\"/departments/" + id + "\" />"
+ "<name>Solutions Development</name>"
+ "</department>";
}
}



EmployeeService.java

package com.javaeenotes;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

@Path("/employees")
public class EmployeeService {

@GET
@Produces("application/xml")
public String showEmployees() {
// Return all employees.
return "<employee id=\"1580\">"
+ "<link rel=\"self\" href=\"/employees/1580\" />"
+ "<firstName>Gin Lung</firstName>"
+ "<lastName>Cheng</lastName>"
+ "<department id=\"12345\">"
+ "<link rel=\"self\" href=\"/departments/12345\" />"
+ "</department>"
+ "</employee>";
}

@Path("{id}")
@GET
@Produces("application/xml")
public String showEmployee(@PathParam("id") int id) {
// Return employee by ID.
return "<employee id=\"" + id + "\">"
+ "<link rel=\"self\" href=\"/employees/" + id + "\" />"
+ "<firstName>Gin Lung</firstName>"
+ "<lastName>Cheng</lastName>"
+ "<department id=\"12345\">"
+ "<link rel=\"self\" href=\"/departments/12345\" />"
+ "</department>"
+ "</employee>";
}
}



5. Test application with URLs
If you deployed your application on a default install of Glassfish on your computer, the objects can be retrieved using the following URLs:

http://localhost:8080/restfulservices/rs/departments
http://localhost:8080/restfulservices/rs/departments/12345
http://localhost:8080/restfulservices/rs/employees
http://localhost:8080/restfulservices/rs/employees/1580

If you use Firefox to do this, remember that Firefox will render XML-tags invisible. Try to view the source of the page.

11 comments:

  1. Hello,
    Pretty good post. I just stumbled upon your blog and wanted to say that I have really enjoyed reading your blog posts. Any way I'll be subscribing to your feed and I hope you post again soon.
    shane

    ReplyDelete
  2. Thank you for your comment. More is definitely coming!

    ReplyDelete
  3. Good post. What is your recommendation if we want to not use the default access URLs ? For example, if I want to use
    http://localhost:8080//departments, how would I do it ?

    Thanks.

    ReplyDelete
  4. The solution is not JAX-RS specific. It also applies to normal web applications. You can read about it here: http://javaeenotes.blogspot.com/2011/02/configuring-your-java-web-application.html

    ReplyDelete
  5. Thanks for the link. I am using NetBeans 6.8 to build my web services. I find that I need to include the string "resources" in the HTTP access URL in order to hit the web service. I do not explicitly specify "resources" in either my "context-path" or in the @Path settings.
    For example, if my context path was "/" and @Path is "/departments", I need to say
    http:///resources/departments from the browser. I would prefer to access my web service as "http:///departments".

    ReplyDelete
  6. Sorry, my "<" and ">" got eaten up.
    I meant to say
    http://hostname/resources/departments
    is the URL that works.
    http://hostname/departments is that URL that I would prefer to use.

    ReplyDelete
  7. Thanks for nice JAX-RS example.I am looking for such a nice example very long time.

    ReplyDelete
  8. I'm very happy cause i'm looking for this tutorial very long time. But i still have problem how to get data from database. And this is do it otomatically. Maybe like search data in google using my specific word like. In your example i wanna search data that have connect with keyword Cheng. Thank You

    ReplyDelete
  9. I just found it interesting that there's neither javax package for the JAX-WS runtime, nor automatic mapping of the POJOs without defining a mapping nor capability of exposing an EJB as a RESTful service without a web container.

    ReplyDelete
  10. This is first time i read your article.It is helpful.It is good information.I really appreciate you did very great work.Thanks for sharing a wonderful information.
    Ecommerce developer

    ReplyDelete
  11. Thank you for the info. It sounds pretty user friendly. I guess I’ll pick one up for fun. thank u


    Web Services Chennai

    ReplyDelete