LAB-5542: Project Jersey: Building RESTful Web Services in Java

Expected Duration: 120 minutes

Exercise 2: Advanced JAX-RS/Jersey features (60 minutes)

 

In this exercise we are going to turn the project we developed in the last exercise into a web application for manipulating system properties. This will allow us to show some of the more advanced JAX-RS and Jersey features. We will do this by adding a new resource class that will contain methods for handling updates to the system properties as well as returning their representations in the form of plain text, XML and even JSON.

Before we start coding, it is important to think about the structure of the URLs we want to expose. Choosing the right URL structure is quite important for RESTful web services.

For this exercise, we will use the following URL structure:

URL template Operation Description
/properties GET List of all system properties
/properties/{property} GET Returns a representation of a property named {property}
PUT Adds/updates a property named {property}
DELETE Removes a property named {property}

Steps to Follow

 

Step 1: Creating a New Resource

Make sure you have the project from the last exercise open in NetBeans. If not, follow these steps to open it:

  1. In NetBeans, select File->Open Project and browse to the jerseyservice directory.

  2. Click Open Project.

Let's create a new resource for system properties:

  1. In NetBeans, create a new class named PropertyResource by right-clicking on Source Packages->com.mycompany.jerseyservice and choosing New->Java Class from the pop-up menu.
  2. In the New Java Class dialog, set the name to PropertyResource and click finish.
  3. Attach @Path("/properties") annotation to the class.
  4. NetBeans will indicate there is an error on that line. That is because the Path annotation needs to be imported. Click on the lightbulb next to that line and click on "Add import for javax.ws.rs.Path".
  5. Here is how the code should look like so far:
    package com.mycompany.jerseyservice;
    
    import javax.ws.rs.Path;
    
    @Path("/properties")
    public class PropertyResource {
    
    }
  6. Now it will get a bit more interesting. We will add a new method that will handle HTTP GET requests and return plain text response containing the name-value pair for the given system property specified in the last part of the URL. I.e. we want to be able to get this method invoked for any URL of the following form:
    http://localhost:8080/jerseyservice/webresources/properties/{property}
    where {property} is the name of the property we want to retrieve. Here is how such method looks like:
        @GET
        @Path("/{property}")
        @Produces("text/plain")
        public String getProperty(@PathParam("property") String propertyName) {
            return propertyName + " = " + System.getProperty(propertyName);
        }
    
    Add this method to the PropertyResource class and fix all imports by clicking on the lightbulbs and following the hints.

    As you can see from the code above, you can have variables surrounded by curly braces as part of the path template specified in the @Path annotation. These are then accessible by annotating any method parameter using the @PathParam annotation. Jersey then automatically passes the value of that variable into such annotated method parameter.

  7. The whole class should now look like this:
    package com.mycompany.jerseyservice;
    
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    
    @Path("/properties")
    public class PropertyResource {
        @GET
        @Path("/{property}")
        @Produces("text/plain")
        public String getProperty(@PathParam("property") String propertyName) {
            return propertyName + " = " + System.getProperty(propertyName);
        }
    }
    
  8. Run the project.
  9. The following URL should retrieve a value of "java.home" system property:
    http://localhost:8080/jerseyservice/webresources/properties/java.home
    Let's see if it works. Copy & Paste it into the browser's address bar and hit Enter. You should see your Java home directory path.
  10. Now, what if we enter a URL containing an invalid property name - i.e. a system property name that does not exist? Our method handles all requests conforming to the template. It does not check whether a given property exists. So, the result will be the same as if the system property did exist and its value was null. Try it for yourself by entering the following URL into the browser as an example:
    http://localhost:8080/jerseyservice/webresources/properties/invalid
    The resulting response will be:
    invalid = null
  11. Let's make the code more robust by checking if the property exists and returning an error if it doesn't. Jersey makes it easy to return errors by defining Java exceptions corresponding to the standard HTTP error codes your application can throw. One of those is com.sun.jersey.api.NotFoundException that we will be using in this case. We will add a new method to implement the check and call it from our GET method. The code will look like this (make sure you fix the imports after updating the code):
        private static void checkPropertyExists(String propertyName) {
            if (!System.getProperties().containsKey(propertyName)) {
                throw new NotFoundException("Error - Property Not Found: " + propertyName);
            }
        }
    
        @GET
        @Path("/{property}")
        @Produces("text/plain")
        public String getProperty(@PathParam("property") String propertyName) {
            checkPropertyExists(propertyName);
            return propertyName + " = " + System.getProperty(propertyName);
        }
    
  12. Run the application and try the "invalid" URL again. You will see the error message.
  13. To verify that the right status code is returned when the property is not found, we can use the Poster Add-on for Firefox. To bring up the Poster window, click on the Poster icon in the Firefox status bar.
  14. Let's first type in the valid URL (i.e. the URL for the java.home property) and click the GO button next to the GET action. This sends the HTTP GET request to a given URL (similarly to when you enter this URL into a browser.
  15. We can see the response as well as the HTTP status code. For this operation the status code is 200 = OK.
  16. Close the Response dialog and try to change the URL to the "invalid" one:
    http://localhost:8080/jerseyservice/webresources/properties/invalid
    After clicking GO, you can see that not only the error message gets returned, but as Poster shows also the status code has the right value - 404 = Not found.

Step 2: Supporting More MIME Types

Let's now try to extend our resource to be able to return several different representations of a system property, based on the requested MIME type. We want to support XML and JSON in addition to the currently supported plain text.

Jersey makes this very easy by providing a support for JAXB beans to represent resources using both XML and JSON formats. All you need to do is return a JAXB bean from the GET operation and Jersey takes care of translating it into the right MIME type the client expects.

So, let's add this functionality to our service:

  1. First we have to create a new JAXB bean to represent a single system property. To do this, create a new Java class named PropertyBean in the com.mycompany.jerseyservice package.
  2. Annotate the class with the JAXB annotation @XmlRootElement.
  3. Add two private String fields - name and value, and two public constructors - one with no arguments and the other one taking name and value as arguments and setting the private fields.
  4. Add setters and getters for the two private fields.
  5. The resulting class should look like this:
    package com.mycompany.jerseyservice;
    
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement
    public class PropertyBean {
        private String name;
        private String value;
    
        public PropertyBean() {
        }
    
        public PropertyBean(String name, String value) {
            this.name = name;
            this.value = value;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getValue() {
            return value;
        }
    
        public void setValue(String value) {
            this.value = value;
        }
    }
    
  6. Now that we have the JAXB bean representing a system property, let's add another GET method - named getJAXBProperty() to our resource. This method will make use of the PropertyBean we've created to support text/xml, application/xml and application/json MIME types:
    package com.mycompany.jerseyservice;
    
    import com.sun.jersey.api.NotFoundException;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    
    @Path("/properties")
    public class PropertyResource {
        private static void checkPropertyExists(String propertyName) {
            if (!System.getProperties().containsKey(propertyName)) {
                throw new NotFoundException("Error - Property Not Found: " + propertyName);
            }
        }
    
        @GET
        @Path("/{property}")
        @Produces("text/plain")
        public String getProperty(@PathParam("property") String propertyName) {
            checkPropertyExists(propertyName);
            return propertyName + " = " + System.getProperty(propertyName);
        }
    
        @GET
        @Path("/{property}")
        @Produces({"text/xml", "application/xml", "application/json"})
        public PropertyBean getJAXBProperty(@PathParam("property") String propertyName) {
            checkPropertyExists(propertyName);
            return new PropertyBean(propertyName, System.getProperty(propertyName));
        }
    }
    
  7. Let's run the project and test it using the Poster Firefox Add-on. In the poster, enter the URL of java.home property.
  8. Besides this, we will also need to configure the Poster to accept only a certain MIME type. To do that, click on the GO button next to the Headers field. This will allow us to add additional attributes to the HTTP request header.
  9. In the Request Header dialog put "Accept" into the Name field, "text/plain" into the Value field, click Add/Change and close the dialog. This will cause the Poster to specifically request a response of the text/plain MIME type.
  10. Now click the GO button next to the GET action. You will see the Poster will get the standard response produced by the getProperty() method of our resource we already saw in the previous steps.
  11. Let's see what happens if we change the MIME type to some of the new ones we added by the way of adding the getJAXBProperty() method. Close the Response window and click GO next to the Headers field again.
  12. This time we will set the Accept attribute to application/xml. To do this, click on the Accept attribute in the Request Header dialog, modify its value by typing application/xml into the Value field and clicking the Add/Change button.
  13. Close the Request Header dialog and send the request by clicking the GO button next to the GET action. Now you see the response contains an XML representation of the system property
  14. Similarly, you can modify the Accept header attribute to retrieve the JSON representation of the property (by setting the value to application/json).

Step 3: Implementing a Message Body Writer

To further improve our code, it would be nice if we could have just one method handling the GET requests, instead of having the two separate ones as we are having currently (one for the plain text and the other one for XML and JSON).

By default, Jersey does not know how to generate a plain text representation of a JAXB bean - i.e. our PropertyBean class in this case. However, we can plug this in using the SPI Jersey provides. What we need to do is to create a "Provider" class implementing MessageBodyWriter interface and handling the serialization of PropertyBean plain text representation.

Here is how to do this:

  1. Create a new Java class in the com.mycompany.jerseyservice package and name it PropertyWriter.
  2. Copy the following code into the Java file:
    package com.mycompany.jerseyservice;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Type;
    import javax.ws.rs.WebApplicationException;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.MultivaluedMap;
    import javax.ws.rs.ext.MessageBodyWriter;
    import javax.ws.rs.ext.Provider;
    
    @Provider
    public class PropertyWriter implements MessageBodyWriter<PropertyBean> {
        public boolean isWriteable(Class<?> type, Type genericType,
                Annotation[] annotations, MediaType mediaType) {
            return MediaType.TEXT_PLAIN_TYPE.equals(mediaType) &&
                    PropertyBean.class.isAssignableFrom(type);
        }
    
        public long getSize(PropertyBean t, Class<?> type, Type genericType,
                Annotation[] annotations, MediaType mediaType) {
            return -1;
        }
    
        public void writeTo(PropertyBean t, Class<?> type, Type genericType,
                Annotation[] annotations, MediaType mediaType,
                MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
                throws IOException, WebApplicationException {
            entityStream.write(t.toString().getBytes());
        }
    }
    
    This class will automatically be picked up by the Jersey framework, since it is annotated by the @Provider annotation. When creating a reponse, Jersey will call the isWritable() method of this provider to see if it can convert a given type of object into a stream of a given MIME type. The writeTo() method is then called by the framework to perform the conversion.
  3. As you can see, the writter we have created in the last step makes use of the toString() method to convert the PropertyBean to text. Let's override the toString() method in the PropertyBean to make sure we get the desired output. Add the following code to the PropertyBean class:
        @Override
        public String toString() {
            return name + " = " + value;
        }
    
  4. Finally, we can remove getProperty() method from the PropertyResource class and add "text/plain" MIME type to the list of MIME types getJAXBProperty() method produces. The whole class should now look as follows:
    package com.mycompany.jerseyservice;
    
    import com.sun.jersey.api.NotFoundException;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    
    @Path("/properties")
    public class PropertyResource {
        private static void checkPropertyExists(String propertyName) {
            if (!System.getProperties().containsKey(propertyName)) {
                throw new NotFoundException("Error - Property Not Found: " + propertyName);
            }
        }
    
        @GET
        @Path("/{property}")
        @Produces({"text/plain", "text/xml", "application/xml", "application/json"})
        public PropertyBean getJAXBProperty(@PathParam("property") String propertyName) {
            checkPropertyExists(propertyName);
            return new PropertyBean(propertyName, System.getProperty(propertyName));
        }
    }
    
  5. Run the application and use Poster to send a GET request with Accept:text/plain in the header - similarly to how we did it for other MIME types previously. Observe the reception of the correct reponse.

Step 4: List of Properties

Now that we are able to retrieve various representations (text, XML, JSON) of a single property, let's see how to return a list of all properties:

  1. Add another GET method to the PropertyResource class. Let's name this method getProperties(). This time we won't add the @Path annotation, since we want this method to be invoked for the path /properties itself (this path is already attached to the whole class so no need to put it on the method). The method will return a list of properties (sorted by property names - using TreeSet) - i.e. List<PropertyBean> and take no parameters:
        @GET
        public List<PropertyBean> getProperties() {
            List<PropertyBean> result = new ArrayList<PropertyBean>(System.getProperties().size());
    
            for (Object name : new TreeSet(System.getProperties().keySet())) {
                result.add(new PropertyBean((String) name, System.getProperty((String) name)));
            }
    
            return result;
        }
    
  2. Note the method is not even annotated by the @Produces annotation. This is because instead of duplicating this annotation on both GET methods, we will simply move the annotation to the class level - i.e. remove it even from the first GET method and attach it to the class instead.
  3. The updated PropertyResource class should look as follows:
    package com.mycompany.jerseyservice;
    
    import com.sun.jersey.api.NotFoundException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.TreeSet;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    
    @Path("/properties")
    @Produces({"text/plain", "text/xml", "application/xml", "application/json"})
    public class PropertyResource {
        private static void checkPropertyExists(String propertyName) {
            if (!System.getProperties().containsKey(propertyName)) {
                throw new NotFoundException("Error - Property Not Found: " + propertyName);
            }
        }
    
        @GET
        @Path("/{property}")
        public PropertyBean getJAXBProperty(@PathParam("property") String propertyName) {
            checkPropertyExists(propertyName);
            return new PropertyBean(propertyName, System.getProperty(propertyName));
        }
    
        @GET
        public List<PropertyBean> getProperties() {
            List<PropertyBean> result = new ArrayList<PropertyBean>(System.getProperties().size());
    
            for (Object name : new TreeSet(System.getProperties().keySet())) {
                result.add(new PropertyBean((String) name, System.getProperty((String) name)));
            }
    
            return result;
        }
    }
    
  4. Jersey framework is able to transform a list of JAXB beans to XML and JSON, however not to text/plain. So, we need to implement another message body writer - this time for a list of properties. To do this, create a new Java class named PropertyListWriter and copy & paste the following code into it:
    package com.mycompany.jerseyservice;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Type;
    import java.util.List;
    import javax.ws.rs.WebApplicationException;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.MultivaluedMap;
    import javax.ws.rs.ext.MessageBodyWriter;
    import javax.ws.rs.ext.Provider;
    
    @Provider
    public class PropertyListWriter implements MessageBodyWriter<List<PropertyBean>>{
        public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations,
                MediaType mediaType) {
            return MediaType.TEXT_PLAIN_TYPE.equals(mediaType) && List.class.isAssignableFrom(type);
        }
    
        public long getSize(List<PropertyBean> t, Class<?> type, Type genericType,
                Annotation[] annotations, MediaType mediaType) {
            return -1;
        }
    
        public void writeTo(List<PropertyBean> t, Class<?> type, Type genericType,
                Annotation[] annotations, MediaType mediaType,
                MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
                throws IOException, WebApplicationException {
            StringBuffer result = new StringBuffer();
            for(PropertyBean propertyBean : t) {
                result.append(propertyBean.toString()).append('\n');
            }
            entityStream.write(result.toString().getBytes());
        }
    }
    
  5. Let's run the application again and browse to the following URL to see the list of all system properties:

    http://localhost:8080/jerseyservice/webresources/properties

  6. You can also use Poster to try other MIME types.

Step 5: Using the MVC Feature of Jersey

The resource we've developed so far is quite hard to play with in a web browser. It would be nice to return an HTML representation as well and do that in such a way that the list of properties would provide direct links to the individual property resources. We can nicely achieve this by the MVC feature of Jersey.

First we will create two simple JSP pages - one for representing the list of properties and the other one for representing a single property:

  1. Right-click on Web Pages folder of the project and choose New->JSP.
  2. Name it "properties" and click Finish.
  3. This new JSP will be used to represent the list of properties. Jersey automatically makes the "model" (i.e. data to be rendered by this JSP) accessible as a variable named it. In this case it will contain the list of system properties. Let's update this new JSP to render the list of properties properly. First, right under the line with <%@page> tag, we will declare a usage of the core JSP tag library as follows:
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    
    This will enable us to use tags from this library prefixed by "c" namespace (as defined in the prefix attribute in the above tag). The tag we are interested in is forEach that will enable us to iterate through the elements of the property list.
    TROUBLESHOOTING: The taglib declaration will be underlined as an error in NetBeans. Please ignore this, it has no effect on the lab. It is a minor issue in NetBeans 6.5 handling maven projects. The problem is resolved in NetBeans 6.7.
  4. Let's change the title of the JSP to "System Properties":
            <title>System Properties</title>
    
  5. Update the heading with the same:
            <h1>System Properties</h1>
    
  6. Finally, here is how we can iterate throught the list of properties (passed in by Jersey in the above mentioned variable named it) and add links to the individual property resources.
            <ul>
                <c:forEach var="p" items="${it}">
                    <li><a href="properties/${p.name}">${p.name}</a></li>
                </c:forEach>
            </ul>
    
  7. The whole page should now look like this:
    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
       "http://www.w3.org/TR/html4/loose.dtd">
    
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <title>System Properties</title>
        </head>
        <body>
            <h1>System Properties</h1>
    
            <ul>
                <c:forEach var="p" items="${it}">
                    <li><a href="properties/${p.name}">${p.name}</a></li>
                </c:forEach>
            </ul>
        </body>
    </html>
    
  8. Create another new JSP page and name it "property" (this one will be used to represent a single property).
  9. Model for this page will be the PropertyBean (representing the property) itself. Change the title of the page to "System Property - ${it.name}":
            <title>System Properties - ${it.name}</title>
    
  10. Change the heading to the property name itself - i.e. ${it.name}.
  11. Under the heading the only text we will put in is the property value - i.e. ${it.value}
  12. The whole JSP should look as follows:
    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
       "http://www.w3.org/TR/html4/loose.dtd">
    
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <title>System Properties - ${it.name}</title>
        </head>
        <body>
            <h1>${it.name}</h1>
            ${it.value}
        </body>
    </html>
    
  13. Now we need to add GET methods to our PropertyResource to return the HTML representations of the list of properties and an individual property. Open PropertyResource class by double-clicking on it in the Project Explorer in NetBeans.
  14. Right after getJAXBProperty() method, add another GET method named getHTMLProperty() with the same parameter as the getJAXBProperty() method plus annotated with @Produces("text/html") and returning Viewable from com.sun.jersey.api.view package.
  15. All we need to do in this method is to return a new instance of Viewable, passing the name of the JSP template for representing a single property as the first parameter, and the data/model itself (i.e. the PropertyBean object representing the requested property as the second parameter (to get this we will simply reuse the getJAXBProperty() method):
        @GET
        @Path("/{property}")
        @Produces("text/html")
        public Viewable getHTMLProperty(@PathParam("property") String propertyName) {
            return new Viewable("/property", getJAXBProperty(propertyName));
        }
    

    Make sure you fix imports (to import Viewable class).

  16. Now add another GET method (this time for the list of properties) named getHTMLProperties(). Same as the previous one, annotate it with @Produces("text/html") and make it return Viewable.
  17. In the body of the method we need to return a new instance of Viewable similarly to the previous method:
        @GET
        @Produces("text/html")
        public Viewable getHTMLProperties() {
            return new Viewable("/properties", getProperties());
        }
    
  18. To make running the exercise more conveniently, we will make NetBeans open the browser at the right URL when running the project. To do this, Right-click on the project, choose Properties (at the end of the pop-up menu).
  19. In the Project Properties dialog select the Run category and set Relative URL to /webresources/properties - this will ensure that each time we run the application it will open the page with the list of properties.
  20. Let's run the project.
  21. You can see that the properties are now rendered into HTML - you can see a list of properties with the proper links.
  22. By clicking on a link you can see the HTML page for the individual property.

Step 6: Operations for Making Updates

Finally we will add operations to make updates to the system properties.

  1. Add the following method to the PropertyResource class:
        @PUT
        @Path("/{property}")
        public Response setProperty(@Context UriInfo uriInfo,
                @PathParam("property") String name, String value) {
            boolean isNew = !System.getProperties().containsKey(name);
    
            System.setProperty(name, value);
            PropertyBean result = new PropertyBean(name, value);
            if (isNew) {
                return Response.created(uriInfo.getAbsolutePath()).entity(result).build();
            } else {
                return Response.ok(result).build();
            }
        }
    

    Fix imports and make sure the Context class is imported from javax.ws.rs.core package.

    As you can see, this is a PUT method. The method receives the property name and value as parameters and adds/sets the system property. In this example you can see another way of building the response - instead of returning the entity directly, or throwing exceptions, you can directly build and return the Response object. We are using this to return the right status code based on whether a new property was added (results in status code 201 = Created), or an existing property was set (results in status code 200 = OK). The property itself gets returned in the body of the response. Also, when returning the "Created" status code, we need to pass in the URI of the newly created property. That URI is the same as the request URI, so we can retrieve that from the UriInfo object the method takes as a parameter.

    Now, let's look at the parameters more closely:

    • The first parameter is annotated by the @Context annotation - that causes the value of this parameter to be automatically injected by the Jersey framework. The value will contain information on the URI of the request that triggered this method.
    • The second parameter should look familiar - it is the one the value of which will automatically be extracted from the URI.
    • The last parameter - value will be populated by the body of the request.
    The parameter values injection makes the implementation of the PUT method quite simple.

  2. Another method we are going to add is the DELETE method. Copy & paste the following into the PropertyResource class:
        @DELETE
        @Path("/{property}")
        public void deleteProperty(@PathParam("property") String propertyName) {
            checkPropertyExists(propertyName);
            System.getProperties().remove(propertyName);
        }
    
    This method is very simple. It has no return value, so Jersey will automatically generate a response with the status code set to 204 = No content. Otherwise the code should be straightforward.
  3. That's it - let's run the application again.
  4. Open the following URL in the web browser to retrieve the list of properties:

    http://localhost:8080/jerseyservice/webresources/properties

  5. Now use Poster to add a new property named "aaa" with the value of "This is a property value". To do this, fill in the following into the URL field of the Poster window:
    http://localhost:8080/jerseyservice/webresources/properties/aaa
    Enter "This is a property value" into the "Content to Send" field, in the Actions dropdown box select PUT, and click GO next to it.
  6. In the response dialog observe that the right status code got returned, (i.e. 201) and also the Location header attribute contains the URI of the new property.
  7. Refresh the browser window containing the list of all system properties and you should see our new property "aaa" added to the beginning of the list.
  8. In the Poster, change the value in the "Context to Send" field to "This is an updated property value" and send another PUT request. Now you should see status code 200.
  9. Refresh the brower window and observe that the value of the property "aaa" got updated.
  10. Finally, let's send a DELETE request to the same URI by setting the Action in the Poster window to DELETE and clicking GO next to it.
  11. Observe that the right status code got returned - 204.
  12. You can see another identical DELETE request using Poster (by clicking the GO button again) and see this time we get 404 (i.e. Not Found) status code back.
  13. Refresh the browser window containing the list of all properties and see our "aaa" property is no longer appears listed.

This concludes the second exercise.

Summary

 

In this exercise, you saw how to create a RESTful web service using the features provided by JAX-RS and Jersey. You saw how a resource could produce data in more than one representation. You also saw how to map the resource methods to the HTTP methods of GET, PUT and DELETE.

For the development purpose we saw how we could use the web browser, or Poster to send various HTTP methods and see what the response would be.

In the following exercise, we will see how we can use the Jersey Client API to consume the services we've created so far..

 

Back to top
Next exercise