You are previewing RESTful Web Services.

RESTful Web Services

Cover of RESTful Web Services by Leonard Richardson... Published by O'Reilly Media, Inc.
  1. RESTful Web Services
    1. SPECIAL OFFER: Upgrade this ebook with O’Reilly
    2. A Note Regarding Supplemental Files
    3. Foreword
    4. Preface
      1. The Web Is Simple
      2. Big Web Services Are Not Simple
      3. The Story of the REST
      4. Reuniting the Webs
      5. What’s in This Book?
      6. Administrative Notes
      7. Conventions Used in This Book
      8. Using Code Examples
      9. Safari® Enabled
      10. How to Contact Us
      11. Acknowledgments
    5. 1. The Programmable Web and Its Inhabitants
      1. Kinds of Things on the Programmable Web
      2. HTTP: Documents in Envelopes
      3. Method Information
      4. Scoping Information
      5. The Competing Architectures
      6. Technologies on the Programmable Web
      7. Leftover Terminology
    6. 2. Writing Web Service Clients
      1. Web Services Are Web Sites
      2. del.icio.us: The Sample Application
      3. Making the Request: HTTP Libraries
      4. Processing the Response: XML Parsers
      5. JSON Parsers: Handling Serialized Data
      6. Clients Made Easy with WADL
    7. 3. What Makes RESTful Services Different?
      1. Introducing the Simple Storage Service
      2. Object-Oriented Design of S3
      3. Resources
      4. HTTP Response Codes
      5. An S3 Client
      6. Request Signing and Access Control
      7. Using the S3 Client Library
      8. Clients Made Transparent with ActiveResource
      9. Parting Words
    8. 4. The Resource-Oriented Architecture
      1. Resource-Oriented What Now?
      2. What’s a Resource?
      3. URIs
      4. Addressability
      5. Statelessness
      6. Representations
      7. Links and Connectedness
      8. The Uniform Interface
      9. That’s It!
    9. 5. Designing Read-Only Resource-Oriented Services
      1. Resource Design
      2. Turning Requirements Into Read-Only Resources
      3. Figure Out the Data Set
      4. Split the Data Set into Resources
      5. Name the Resources
      6. Design Your Representations
      7. Link the Resources to Each Other
      8. The HTTP Response
      9. Conclusion
    10. 6. Designing Read/Write Resource-Oriented Services
      1. User Accounts as Resources
      2. Custom Places
      3. A Look Back at the Map Service
    11. 7. A Service Implementation
      1. A Social Bookmarking Web Service
      2. Figuring Out the Data Set
      3. Resource Design
      4. Design the Representation(s) Accepted from the Client
      5. Design the Representation(s) Served to the Client
      6. Connect Resources to Each Other
      7. What’s Supposed to Happen?
      8. What Might Go Wrong?
      9. Controller Code
      10. Model Code
      11. What Does the Client Need to Know?
    12. 8. REST and ROA Best Practices
      1. Resource-Oriented Basics
      2. The Generic ROA Procedure
      3. Addressability
      4. State and Statelessness
      5. Connectedness
      6. The Uniform Interface
      7. This Stuff Matters
      8. Resource Design
      9. URI Design
      10. Outgoing Representations
      11. Incoming Representations
      12. Service Versioning
      13. Permanent URIs Versus Readable URIs
      14. Standard Features of HTTP
      15. Faking PUT and DELETE
      16. The Trouble with Cookies
      17. Why Should a User Trust the HTTP Client?
    13. 9. The Building Blocks of Services
      1. Representation Formats
      2. Prepackaged Control Flows
      3. Hypermedia Technologies
    14. 10. The Resource-Oriented Architecture Versus Big Web Services
      1. What Problems Are Big Web Services Trying to Solve?
      2. SOAP
      3. WSDL
      4. UDDI
      5. Security
      6. Reliable Messaging
      7. Transactions
      8. BPEL, ESB, and SOA
      9. Conclusion
    15. 11. Ajax Applications as REST Clients
      1. From AJAX to Ajax
      2. The Ajax Architecture
      3. A del.icio.us Example
      4. The Advantages of Ajax
      5. The Disadvantages of Ajax
      6. REST Goes Better
      7. Making the Request
      8. Handling the Response
      9. JSON
      10. Don’t Bogart the Benefits of REST
      11. Cross-Browser Issues and Ajax Libraries
      12. Subverting the Browser Security Model
    16. 12. Frameworks for RESTful Services
      1. Ruby on Rails
      2. Restlet
      3. Django
    17. A. Some Resources for REST and Some RESTful Resources
      1. Standards and Guides
      2. Services You Can Use
    18. B. The HTTP Response Code Top 42
      1. Three to Seven Status Codes: The Bare Minimum
      2. 1xx: Meta
      3. 2xx: Success
      4. 3xx: Redirection
      5. 4xx: Client-Side Error
      6. 5xx: Server-Side Error
    19. C. The HTTP Header Top Infinity
      1. Standard Headers
      2. Nonstandard Headers
    20. Index
    21. About the Authors
    22. Colophon
    23. SPECIAL OFFER: Upgrade this ebook with O’Reilly
O'Reilly logo

Restlet

by Jerome Louvel and Dave Pawson

The Restlet project provides a lightweight but comprehensive framework for mapping REST concepts to Java classes. It can be used to implement any kind of RESTful system, not just RESTful web services, and it’s proven a reliable piece of software since its inception in 2005.

The Restlet project was influenced by the other major Java technologies for developing Web applications: the Servlet API, Java Server Pages, HttpURLConnection, and Struts. The primary goal of the project is to provide the same level of functionality while sticking closer to the goals of REST as expounded in the Fielding thesis. Another key goal is to present a unified view of the Web, suitable for use in both client- and server-side applications.

The Restlet philosophy is that the distinction between HTTP client and HTTP server is architecturally unimportant. A single piece of software should be able to act as a web client, then as a web server, without using two completely different APIs.[32]

An early development was the split of the software into the Restlet API and Noelios Restlet Engine (NRE), a reference implementation. This separation allows other implementations to be compatible with the same API. The NRE includes several HTTP server connectors based on popular HTTP open source Java projects: Mortbay’s Jetty, Codehaus’s AsyncWeb, and the Simple framework. There’s even an adapter that lets you deploy a Restlet application inside standard Servlet containers like Apache Tomcat.

Restlet also provides two HTTP client connectors, one based on the official HttpURLConnection class and the other on Apache’s popular HTTP client library. Another connector allows you to easily manipulate a JDBC source via XML documents in a RESTful way, while an SMTP connector, based on the JavaMail API, lets you send email with an XML document.

The Restlet API includes classes that can build representations based on strings, files, streams, channels, and XML documents: it supports SAX and DOM for parsing, and XSLT for transformation. It’s easy to build JSP-style template-based representations, using the FreeMarker or Apache Velocity template engines. You can even serve static files and directories, like an ordinary web server, using a Directory class, which supports content negotiation.

Throughout the framework, the design principles are simplicity and flexibility. The API aims to abstract the concepts of HTTP, URIs, and REST into a consistent set of classes, without fully hiding low-level information such as the raw HTTP headers.

Basic Concepts

The Restlet terminology matches the terminology of REST as described in the Fielding thesis: resource, representation, connector, component, media type, language, and so on. A lot of this terminology should be familiar to you from elsewhere in the book. Restlet adds some specialized classes like Application, Filter, Finder, Router, and Route, to make it easier to combine restlets with each other, and to map incoming requests to the resources that ought to handle them.

The central concept of Restlet is the abstract Uniform class, and its concrete subclass Restlet. As the name implies, Uniform exposes a uniform interface as defined by REST. This interface is inspired by HTTP’s uniform interface but can be used with other protocols like FTP and SMTP.

The main method is handle, which takes two arguments: Request and Response. As you can see from Figure 12-1, every call handler that is exposed over the network (whether as client or server) is a subclass of Restlet—is a restlet—and respects this uniform interface. Because of this uniform interface, restlets can be combined in very sophisticated ways.

The Restlet class hierarchy

Figure 12-1. The Restlet class hierarchy

Every protocol that Restlet supports is exposed through the handle method. This means HTTP (server and client), HTTPS, and SMTP, as well as JDBC, the file system, and even the class loaders all go through handle. This reduces the number of APIs the developer must learn.

Filtering, security, data transformation, and routing are handled by chaining together subclasses of Restlet. Filters can provide processing before or after the handling of a call by the next restlet. Filter instances work like Rails filters, but they respond to the same handle method as the other Restlet classes, not to a filter-specific API.

A Router restlet has a number of Restlet objects attached to it, and routes each incoming protocol call to the appropriate Restlet handler. Routing is typically done on some aspect of the target URI, as in Rails. Unlike Rails, Restlet imposes no URI conventions on your resource hierarchies. You can set up your URIs however you want, so long as you program your Routers appropriately.

Routers can stretch beyond this common usage. You can use a Router to proxy calls with dynamic load balancing between several remote machines! Even a setup as complex as this still responds to Restlet’s uniform interface, and can be used as a component in a larger routing system. The VirtualHost class (a subclass of Router) makes it possible to host several applications under several domain names on the same physical machine. Traditionally, to get this kind of feature you’ve had to bring in a front-end web server like Apache’s httpd. With Restlet, it’s just another Router that responds to the uniform interface.

An Application object can manage a portable set of restlets and provide common services. A “service” might be the transparent decoding of compressed requests, or tunnelling methods like PUT and DELETE over overloaded POST using the method query parameter. Finally, Component objects can contain and orchestrate a set of Connectors, VirtualHosts, and Applications that can be run as a standalone Java application, or embedded in a larger system such as a J2EE environment.

In Chapter 6 you saw a sequence of steps for breaking a problem down into a set of resources that respond to HTTP’s uniform interface. This procedure was modified in Chapter 7 to deal with the simplifying assumptions imposed by Ruby on Rails. There’s no need to modify the procedure when working with Restlet, because Restlet makes no simplifying assumptions. It can implement any RESTful system. If you happen to be implementing a RESTful resource-oriented web service, you can arrange and implement the resources however you like. Restlet does provide some classes that make it easy to create resource-oriented applications. Most notably, there’s a Resource class that can be used as the basis for all of your application resources.

Throughout this book, URI Templates are used as shorthand to designate whole classes of URIs (see Chapter 9”). Restlet uses URI Templates to map URIs onto resources. A Restlet implementation of the Chapter 7 social bookmarking application might specify the path to a particular bookmark like so:

/users/{username}/bookmarks/{URI}

You can use this exact syntax when attaching a Resource subclass to a Router. If it sounds too good to be true, just wait for the next section where I actually implement part of the bookmarking service covered in Chapter 7.

Writing Restlet Clients

In Example 2-1 you saw a Ruby client that retrieved XML search results from Yahoo!’s web search service. The code in Example 12-3 is a Java implementation of the same client, written against version 1.0 of Restlet. In order to compile and run the upcoming examples, you’ll need to make sure that the following JARs are in your classpath:

  • org.restlet.jar (Restlet API)

  • com.noelios.restlet.jar (Noelios Restlet Engine core)

  • com.noelios.restlet.ext.net.jar (HTTP client connector based on JDK’s HttpURLConnection)

All these are available in the lib directory of the Restlet distribution. Make sure that your Java environment supports Java SE version 5.0 or higher. If you really need to, you can easily backport the Restlet code to Java SE version 4.0 with Retrotranslator.

Example 12-3. A Restlet client for Yahoo!’s search service

// YahooSearch.java
import org.restlet.Client;
import org.restlet.data.Protocol;
import org.restlet.data.Reference;
import org.restlet.data.Response;
import org.restlet.resource.DomRepresentation;
import org.w3c.dom.Node;

/**
 * Searching the web with Yahoo!'s web service using XML.
 */
public class YahooSearch {
    static final String BASE_URI = 
	"http://api.search.yahoo.com/WebSearchService/V1/webSearch";

    public static void main(String[] args) throws Exception {
        if (args.length != 1) {
            System.err.println("You need to pass a term to search");
        } else {
            // Fetch a resource: an XML document full of search results
            String term = Reference.encode(args[0]);
            String uri = BASE_URI + "?appid=restbook&query=" + term;
            Response response = new Client(Protocol.HTTP).get(uri);
            DomRepresentation document = response.getEntityAsDom();

            // Use XPath to find the interesting parts of the data structure
            String expr = "/ResultSet/Result/Title";
            for (Node node : document.getNodes(expr)) {
                System.out.println(node.getTextContent());
            }
        }
    }
}

You can run this class by passing a search term as a command-line argument, just like with the Ruby example in Example 2-1. Here’s a sample run:

$ java YahooSearch xslt
	XSL Transformations (XSLT)
	The Extensible Stylesheet Language Family (XSL)
	XSLT Tutorial
        ...

This example demonstrates how easy it is with Restlet to retrieve XML data from a web service and process it with standard tools. The URI to the Yahoo! resource is built from a constant and the user-provided search term. A client connector is instantiated using the HTTP protocol. The XML document is retrieved with a method (get) whose name mirrors the method of HTTP’s uniform interface. When the call returns, the program has the response entity as a DOM representation. As in the Ruby example, XPath is the simplest way to search the XML I retrieved.

Also as in the earlier Ruby example, this program ignores the XML namespaces used in the result document. Yahoo! puts the entire document into the namespace urn:yahoo:srch, but I access the tags as, say, ResultSet instead of urn:yahoo:srch:ResultSet. The Ruby example ignores namespaces because Ruby’s default XML parsers aren’t namespace-aware. Java’s XML parsers are namespace-aware, and the Restlet API makes it easy to deal with namespaces correctly. It doesn’t make much difference in a simple case like this, but you can avoid some subtle problems by handling documents in a namespace-aware way.

Of course, saying urn:yahoo.srch:ResultSet all the time would get old pretty fast. The Restlet API makes it easy to associate a short prefix with a namespace, and then use the prefix in an XPath expression instead of the full name. Example 12-4 shows a variant of the document-handling code from the end of Example 12-3. This version uses namespace-aware XPath, so that Yahoo’s ResultSet tag will never be confused with the ResultSet tag from some other namespace.

Example 12-4. Namespace-aware version of the document handling code from Example 12-3

            DomRepresentation document = response.getEntityAsDom();

            // Associate the namespace with the prefix 'y'
            document.setNamespaceAware(true);
            document.putNamespace("y", "urn:yahoo:srch");

            // Use XPath to find the interesting parts of the data structure
            String expr = "/y:ResultSet/y:Result/y:Title/text()";
            for (Node node : document.getNodes(expr)) {
                System.out.println(node.getTextContent());
            }

Example 2-15 showed a second Ruby client for Yahoo!’s search service. That one requested a JSON representation of the search data, instead of an XML representation. Example 12-5 is the equivalent program for Restlet. It gets its JSON support from two additional JAR files, both included with Restlet:

  • org.restlet.ext.json_2.0.jar (Restlet extension for JSON)

  • org.json_2.0/org.json.jar (JSON official library)

Example 12-5. A Restlet client for Yahoo!’s JSON search service

// YahooSearchJSON.java
import org.json.JSONArray;
import org.json.JSONObject;
import org.restlet.Client;
import org.restlet.data.Protocol;
import org.restlet.data.Reference;
import org.restlet.data.Response;
import org.restlet.ext.json.JsonRepresentation;

/**
 * Searching the web with Yahoo!'s web service using JSON.
 */
public class YahooSearchJSON {
    static final String BASE_URI =
	"http://api.search.yahoo.com/WebSearchService/V1/webSearch";

    public static void main(String[] args) throws Exception {
        if (args.length != 1) {
            System.err.println("You need to pass a term to search");
        } else {
            // Fetch a resource: a JSON document full of search results
            String term = Reference.encode(args[0]);
            String uri = BASE_URI + "?appid=restbook&output=json&query=" + term;
            Response response = new Client(Protocol.HTTP).get(uri);
            JSONObject json = new JsonRepresentation(response.getEntity())
                    .toJsonObject();

            // Navigate within the JSON document to display the titles
            JSONObject resultSet = json.getJSONObject("ResultSet");
            JSONArray results = resultSet.getJSONArray("Result");
            for (int i = 0; i < results.length(); i++) {
                System.out.println(results.getJSONObject(i).getString("Title"));
            }
        }
    }
}

When you write a client against Yahoo!’s service, you can choose the representation. Restlet supports both XML in the core API and JSON with an extension. As you’d expect, the only difference between the two programs is in processing the response. The JsonRepresentation class allows you to convert the response entity-body into an instance of JSONObject (contrast with Ruby’s JSON library, which converted the JSON data structure into a native data structure). The data structure is navigated manually, since there’s not yet any XPath-like query language for JSON.

Writing Restlet Services

The next set of examples is a little more complex. I’ll show you how to design and implement a server-side application. I’ve implemented a subset of the bookmark management application originally implemented with Ruby on Rails in Chapter 7. To keep things relatively simple, the only features this application supports are the secure manipulation of users and their bookmarks.

The Java package structure looks like this:

org
 restlet
  example
   book
    rest
     ch7
    	-Application
    	-ApplicationTest
    	-Bookmark
    	-BookmarkResource
	 	-BookmarksResource
	 	-User
	 	-UserResource

That is, the class Bookmark is in the package org.restlet.example.book.rest.ch7, and so on.

Rather than include all the code here, I’d like you to download it from the archive (http://www.oreilly.com/catalog/9780596529260), which contains all examples from this book. It’s also available on restlet.org. If you’ve already downloaded Restlet, you don’t have to do anything, since the examples for this section are shipped with Restlet, see src/org.restlet.example/org/restlet/example/book/rest.

I’ll start you off with some simple code in Example 12-6: the Application.main, which sets up the web server and starts serving requests.

Example 12-6. The Application.main method: setting up the application

public static void main(String... args) throws Exception {
    // Create a component with an HTTP server connector
    Component comp = new Component();
    comp.getServers().add(Protocol.HTTP, 3000);

    // Attach the application to the default host and start it
    comp.getDefaultHost().attach("/v1", new Application());
    comp.start();
}

Resource and URI design

Since Restlets impose no restrictions on resource design, the resource classes and the URIs they expose flow naturally from considerations of ROA design. There’s no need to design around the Restlet architecture, the way the resources in Chapter 7 were designed around Rails’s controller-based architecture. Figure 12-2 shows how incoming URIs are mapped to resources with a Router, and how resources are mapped onto the underlying restlet classes.

Restlet architecture of the social bookmarking application

Figure 12-2. Restlet architecture of the social bookmarking application

To understand how these mappings are coded in Java, let’s take a look at the Application class and its createRoot method (see Example 12-7). This is the equivalent of the Rails routes.rb file shown in Example 7-3.

Example 12-7. The Application.createRoot method: mapping URI Templates to restlets

public Restlet createRoot() {
    Router router = new Router(getContext());

    // Add a route for user resources
    router.attach("/users/{username}", UserResource.class);

    // Add a route for user's bookmarks resources
    router.attach("/users/{username}/bookmarks", BookmarksResource.class);

    // Add a route for bookmark resources
    Route uriRoute = router.attach("/users/{username}/bookmarks/{URI}",
                                   BookmarkResource.class);
    uriRoute.getTemplate().getVariables()
      .put("URI", new Variable(Variable.TYPE_URI_ALL));
}

This code runs when I create an Application object, as I do back in Example 12-6. It creates a clean and intuitive relationship between the resource class UserResource and the URI Template "/users/{username}". The Router matches incoming URIs against the templates, and forwards each request to a new instance of the appropriate resource class. The value of the template variables are stored in the request’s attributes map (similar to the params map in the Rails example), for easy usage in the Resource code. This is both powerful and simple to understand, which is very helpful when you haven’t seen the code for a few months!

Request handling and representations

Suppose a client makes a GET request for the URI http://localhost:3000/v1/users/jerome. I’ve got a Component listening on port 3000 of localhost, and an Application object attached to /v1. The Application has a Router and a bunch of Route objects waiting for requests that match various URI Templates. The URI path fragment "/users/jerome" matches the template "/users/{username}", and that template’s Route is associated with the UserResource class: a rough equivalent to the Rails UsersController class.

Restlet handles the request by instantiating a new UserResource object and calling its handleGet method. The UserResource constructor is reproduced in Example 12-8.

Example 12-8. The UserResource constructor

/**
 * Constructor.
 *
 * @param context
 *            The parent context.
 * @param request
 *            The request to handle.
 * @param response
 *            The response to return.
 */
 public UserResource(Context context, Request request, Response response) {
    super(context, request, response);
    this.userName = (String) request.getAttributes().get("username");
    ChallengeResponse cr = request.getChallengeResponse();
    this.login = (cr != null) ? cr.getIdentifier() : null;
    this.password = (cr != null) ? cr.getSecret() : null;
    this.user = findUser();

    if (user != null) {
        getVariants().add(new Variant(MediaType.TEXT_PLAIN));
    }
}

By this time, the framework has set up a Request object, which contains all the information I need about the request. The username attribute comes from the URI, and the authentication credentials from the request’s Authorization header. I also call findUser to look up a user in the database based on the authentication credentials (to save space, I won’t show the findUser method here). These are the jobs done by Rails filters in Chapter 7.

After the framework instantiates a UserResource, it invokes the appropriate handle method on the resource object. There’s one handle method for every method of HTTP’s uniform interface. In this case, the last act of the Restlet framework is to call UserResource.handleGet.

I don’t actually define UserResource.handleGet, so the inherited behavior (defined in Restlet’s Resource.handleGet) takes over. The default behavior of handleGet is to find the representation of the resource that best fits the client’s needs. The client expresses its needs through content-negotiation. Restlet looks at the values of the Accept headers and figures out which “variant” representation is the most appropriate. In this case, there’s only one representation format, so it doesn’t matter what the client asks for. This is handled by the getVariants and getRepresentation methods. Back in the constructor, I defined text/plain as the only supported representation format, so my implementation of the getRepresentation method is pretty simple (see Example 12-9).

Example 12-9. UserResource.getRepresentation: building a representation of a user

@Override
public Representation getRepresentation(Variant variant) {
    Representation result = null;

    if (variant.getMediaType().equals(MediaType.TEXT_PLAIN)) {
        // Creates a text representation
        StringBuilder sb = new StringBuilder();
        sb.append("------------\n");
	       sb.append("User details\n");
	       sb.append("------------\n\n");
	       sb.append("Name:  ").append(this.user.getFullName()).append('\n');
	       sb.append("Email: ").append(this.user.getEmail()).append('\n');
	       result = new StringRepresentation(sb);
    }

    return result;
}

That’s just one method of one resource, but the other resources, and the other HTTP methods of UserResource, work the same way. A PUT request for a user gets routed to UserResource.handlePut, and so on. As I mentioned earlier, this code is part of a complete bookmarking application, so there’s much more example code available if you’re interested in learning more.

You should now understand how the Restlet framework routes incoming HTTP requests to specific Resource classes, and to specific methods on those classes. You should also see how representations are built up from resource state. You’ll probably only have to worry about the Application and the Router code once, since a single router can work for all of your resources.

Compiling, running, and testing

The Application class implements the HTTP server that runs the social bookmarking service. It requires a classpath that contains the following JAR files:

  • org.restlet.jar

  • com.noelios.restlet.jar

  • com.noelios.restlet.ext.net.jar

  • org.simpleframework_3.1/org.simpleframework.jar

  • com.noelios.restlet.ext.simple_3.1.jar

  • com.db4o_6.1/com.db4o.jar

All of these JAR files are included with the Restlet distribution, and we’ve listed them relative to the lib directory in your Restlet installation. Two things to notice: the actual web server work is handled by a very compact HTTP server connector based on the Simple Framework. Second, instead of making you set up a relational database, we persist our domain objects (users and bookmarks) with the powerful db4o object database. Once all the example files have been compiled, run org.restlet.example.book.rest.ch7.Application, which acts as the server endpoint.

The ApplicationTest class provides a client interface to the service. It uses the Restlet client classes described in the previous section to add and delete users and bookmarks. It does this through HTTP’s uniform interface: users and bookmarks are created with PUT and deleted with DELETE.

Run ApplicationTest.class from the command line and you’ll get a message like this:

  Usage depends on the number of arguments:
 - Deletes a user     : userName, password
 - Deletes a bookmark : userName, password, URI
 - Adds a new user    : userName, password, "full name", email
 - Adds a new bookmark: userName, password, URI, shortDescription, 
                        longDescription, restrict[true / false]

You can use this program to add some users and give them bookmarks. Then you can view an HTML representation of the users’ bookmarks by visiting the appropriate URIs in a standard web browser, such as http://localhost:3000/v1/users/jerome and so on.

Conclusion

The Restlet project delivered its final 1.0 version in early 2007. It took just more than 12 months to develop, and the project now has a thriving development and user community. The mailing list is friendly and welcoming to both new and experienced developers. Noelios Consulting, the founder and main developing force behind the project, offers professional support plans and training.

As of the time of writing, the 1.0 release is under maintenance, and a new 1.1 branch has been started. Future plans include submission of the Restlet API to the Java Community Process (JCP) for standardization. There’s also a higher-level API for RESTful web services in development, submitted by Sun Microsystems to the JCP and known as JSR 311. This higher-level API should make it easy to expose Java domain objects as RESTful resources. This will nicely complement the Restlet API, especially its Resource class. Noelios Consulting is part of the initial expert group and will directly support the future annotations in its Restlet engine.



[32] Here Restlet follows Benjamin Carlyle’s sound advice. Carlyle points out a flaw in the standard Java API: that “the HttpURLConnection class itself looks nothing like a servlet.”

The best content for your career. Discover unlimited learning on demand for around $1/day.