URI Extensions in Jersey

Jersey provides an excellent system for easily supporting multiple representations of resources. You use the @Produces annotation to define which formats a resource method supports:

@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Thing getThing()
{
    Thing thing = ...;
    return thing;
}

In this case clients can obtain the representation of the thing resource in either XML or JSON format (assuming you’ve registered corresponding MessageBodyWriters for the Thing class).  Just by including the @Produces annotation, Jersey handles sending the response back in the proper format and will even send a 415 Unsupported Media Type response automatically if the client requests the resource in an unsupported format.

By default Jersey uses the Accept request header to determine which response format to use.  Setting request headers in client apps can be cumbersome though, so a more convenient approach is to use URI extensions.  So if you want the http://site.com/thing resource as XML you GET http://site.com/thing.xml, or GET http://site.com/thing.json if you want its JSON representation.

To tell Jersey to use URI extensions, you create a cusom PackagesResourceConfig implementation and set up the mappings between extensions and media types:

import java.util.*;
import javax.ws.rs.core.*;
import com.sun.jersey.api.core.*;

/** Registers URI extensions for some common media types.  This lets clients specify the desired 
 * response format right in the URI like http://site.com/whatever.xml instead of 
 * http://site.com/whatever with an Accept:application/xml header. */
public class UriExtensionsConfig extends PackagesResourceConfig
{
    private Map<String, MediaType> mediaTypeMap;

    public UriExtensionsConfig()
    {
        super();
    }

    public UriExtensionsConfig(Map<String, Object> props)
    {
        super(props);
    }

    public UriExtensionsConfig(String[] paths)
    {
        super(paths);
    }

    @Override
    public Map<String, MediaType> getMediaTypeMappings()
    {
        if (mediaTypeMap == null)
        {
            mediaTypeMap = new HashMap<String, MediaType>();
            mediaTypeMap.put("json", MediaType.APPLICATION_JSON_TYPE);
            mediaTypeMap.put("xml", MediaType.APPLICATION_XML_TYPE);
            mediaTypeMap.put("txt", MediaType.TEXT_PLAIN_TYPE);
            mediaTypeMap.put("html", MediaType.TEXT_HTML_TYPE);
            mediaTypeMap.put("xhtml", MediaType.APPLICATION_XHTML_XML_TYPE);
            MediaType jpeg = new MediaType("image", "jpeg");
            mediaTypeMap.put("jpg", jpeg);
            mediaTypeMap.put("jpeg", jpeg);
            mediaTypeMap.put("zip", new MediaType("application", "x-zip-compressed"));
        }
        return mediaTypeMap;
    }
}

You register the UriExtensionsConfig in web.xml like this:

    <servlet>
        ...
        <init-param>
            <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
            <param-value>com.pongr.rest.config.UriExtensionsConfig</param-value>
        </init-param>
    </servlet>

This provides yet another way to make your web services more user-friendly. Clients can still use the Accept header but can also use standard URI extensions to specify the desired response format.

Advertisements

2 thoughts on “URI Extensions in Jersey

  1. Pingback: Dynamically Generating Zip Files in Jersey « Zach's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s