REST
 
  | 
Annotation | 
Description | 
  | 
@PATH(your_path) | 
Sets the path to base URL + /your_path. The
  base URL is based on your application name, the servlet and the URL pattern
  from the web.xmlconfiguration file. | 
  | 
@POST, @GET, @PUT, @DELETE | 
Indicates that the following method will answer
  to an HTTP POST/GET/PUT/DELETE request, respectively. | 
  | 
@Produces(MediaType.TEXT_PLAIN[, more-types]) | 
@Produces defines which MIME type is delivered
  by a method annotated with @GET. | 
  | 
@Consumes(type[, more-types]) | 
@Consumes defines which MIME type is consumed
  by this method. | 
  | 
@PathParam | 
Used to inject values from the URL into a
  method parameter. This way you inject, for example, the ID of a resource into
  the method to get the correct object. | 
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
//Plain old Java Object it does not extend as class or implements
//an interface
//The class registers its methods for the HTTP GET request using the @GET annotation.
//Using the @Produces annotation, it defines that it can deliver several MIME types,
//text, XML and HTML.
//The browser requests per default the HTML MIME type.
//Sets the path to base URL + /hello
@Path("/hello")
public class Hello {
 // This method is called if TEXT_PLAIN is request
   @GET
   @Produces(MediaType.TEXT_PLAIN)
   public String sayPlainTextHello() {
     return "Hello Jersey";
   }
   // This method is called if XML is request
   @GET
   @Produces(MediaType.TEXT_XML)
   public String sayXMLHello() {
     return "<?xml version=\"1.0\"?>" + "<hello> Hello Jersey" + "</hello>";
   }
   // This method is called if HTML is request
   @GET
   @Produces(MediaType.TEXT_HTML)
   public String sayHtmlHello() {
     return "<html> " + "<title>" + "Hello Jersey" + "</title>"
         + "<body><h1>" + "Hello Jersey" + "</body></h1>" + "</html> ";
   }
}
 
  | 
import static org.junit.Assert.assertEquals; 
 
import java.net.URI; 
 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.core.UriBuilder; 
 
import org.junit.BeforeClass; 
import org.junit.Test; 
 
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 HelloTest { 
 
          private static WebResource service; 
 
          @BeforeClass 
          public static void setUpBeforeClass() throws Exception { 
                   ClientConfig
  config = new DefaultClientConfig(); 
                   Client
  client = Client.create(config); 
                   service = client.resource(getBaseURI()); 
          } 
 
          @Test 
          public void testSayPlainTextHello() { 
                   String
  msg = service.path("rest").path("hello") 
                                      .accept(MediaType.TEXT_PLAIN).get(ClientResponse.class) 
                                      .toString(); 
                   System.out.println(msg); 
                   assertEquals(true, msg.contains("200")); 
          } 
 
          private static URI getBaseURI() { 
                   return UriBuilder.fromUri("http://localhost:8080/rest").build(); 
          } 
 
} | 
A more complete example will be a todo service:
package rest.todo;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
// JAX-RS supports an automatic mapping from JAXB annotated class to XML and
// JSON
public class Todo {
 private String id;
 private String summary;
 private String description;
 public Todo() {
 }
 public Todo(String id, String summary) {
  this.id = id;
  this.summary = summary;
 }
 public String getSummary() {
  return summary;
 }
 public void setSummary(String summary) {
  this.summary = summary;
 }
 public String getDescription() {
  return description;
 }
 public void setDescription(String description) {
  this.description = description;
 }
 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
}
package rest.todo;
import java.util.HashMap;
import java.util.Map;
public enum TodoDao {
 instance;
 private Map
 contentProvider = new HashMap();
 private TodoDao() {
  Todo todo = new Todo("1", "Learn REST");
  todo.setDescription("Read http://www.vogella.com/tutorials/REST/article.html");
  contentProvider.put("1", todo);
  todo = new Todo("2", "Do something");
  todo.setDescription("Read complete http://www.vogella.com");
  contentProvider.put("2", todo);
 }
 public Map
 getModel() {
  return contentProvider;
 }
}
package rest.todo;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBElement;
public class TodoResource {
 @Context
 UriInfo uriInfo;
 @Context
 Request request;
 String id;
 public TodoResource(UriInfo uriInfo, Request request, String id) {
  this.uriInfo = uriInfo;
  this.request = request;
  this.id = id;
 }
 // Application integration
 @GET
 @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
 public Todo getTodo() {
  Todo todo = TodoDao.instance.getModel().get(id);
  if (todo == null)
   throw new RuntimeException("Get: Todo with " + id + " not found");
  return todo;
 }
 // for the browser
 @GET
 @Produces(MediaType.TEXT_XML)
 public Todo getTodoHTML() {
  Todo todo = TodoDao.instance.getModel().get(id);
  if (todo == null)
   throw new RuntimeException("Get: Todo with " + id + " not found");
  return todo;
 }
 @PUT
 @Consumes(MediaType.APPLICATION_XML)
 public Response putTodo(JAXBElement
 todo) {
  Todo c = todo.getValue();
  return putAndGetResponse(c);
 }
 @DELETE
 public void deleteTodo() {
  Todo c = TodoDao.instance.getModel().remove(id);
  if (c == null)
   throw new RuntimeException("Delete: Todo with " + id + " not found");
 }
 private Response putAndGetResponse(Todo todo) {
  Response res;
  if (TodoDao.instance.getModel().containsKey(todo.getId())) {
   res = Response.noContent().build();
  } else {
   res = Response.created(uriInfo.getAbsolutePath()).build();
  }
  TodoDao.instance.getModel().put(todo.getId(), todo);
  return res;
 }
}
package rest.todo;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;
//Will map the resource to the URL todos
@Path("/todos")
public class TodosResource {
 // Allows to insert contextual objects into the class,
 // e.g. ServletContext, Request, Response, UriInfo
 @Context
 UriInfo uriInfo;
 @Context
 Request request;
 // Return the list of todos to the user in the browser
 @GET
 @Produces(MediaType.TEXT_XML)
 public List getTodosBrowser() {
  List todos = new ArrayList();
  todos.addAll(TodoDao.instance.getModel().values());
  return todos;
 }
 // Return the list of todos for applications
 @GET
 @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
 public List getTodos() {
  List todos = new ArrayList();
  todos.addAll(TodoDao.instance.getModel().values());
  return todos;
 }
 // to get the total number of records
 @GET
 @Path("count")
 @Produces(MediaType.TEXT_PLAIN)
 public String getCount() {
  int count = TodoDao.instance.getModel().size();
  return String.valueOf(count);
 }
 @POST
 @Produces(MediaType.TEXT_HTML)
 @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
 public void newTodo(@FormParam("id") String id,
   @FormParam("summary") String summary,
   @FormParam("description") String description,
   @Context HttpServletResponse servletResponse) throws IOException {
  Todo todo = new Todo(id, summary);
  if (description != null) {
   todo.setDescription(description);
  }
  TodoDao.instance.getModel().put(id, todo);
  servletResponse.sendRedirect("../create_todo.html");
 }
 // Defines that the next path parameter after todos is
 // treated as a parameter and passed to the TodoResources
 // Allows to type http://localhost:8080/de.vogella.jersey.todo/rest/todos/1
 // 1 will be treaded as parameter todo and passed to TodoResource
 @Path("{todo}")
 public TodoResource getTodo(@PathParam("todo") String id) {
  return new TodoResource(uriInfo, request, id);
 }
}
 
And finally a test client:
package rest.todo;
import java.net.URI;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import org.junit.BeforeClass;
import org.junit.Test;
import com.sun.jersey.api.client.Client;
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 TodoTest {
 private static WebResource service;
 @BeforeClass
 public static void setUpBeforeClass() throws Exception {
  ClientConfig config = new DefaultClientConfig();
  Client client = Client.create(config);
  service = client.resource(getBaseURI());
 }
 @Test
 public void test() {
  // Get XML
  System.out.println(service.path("rest").path("todo")
    .accept(MediaType.TEXT_XML).get(String.class));
  // Get XML for application
  System.out.println(service.path("rest").path("todo")
    .accept(MediaType.APPLICATION_JSON).get(String.class));
  // Get JSON for application
  System.out.println(service.path("rest").path("todo")
    .accept(MediaType.APPLICATION_XML).get(String.class));
 }
 private static URI getBaseURI() {
  return UriBuilder.fromUri(
    "http://localhost:8080/rest").build();
 }
}