Restlet User Guide - Version 1.1
Book Index

Restlet User Guide - Version 1.1

Table of Contents

1 Introduction

1.1 Welcome to the Restlet Team !

We are very happy to have you as a new user. We hope you will have as much fun learning and using this technology as we had designing and developing it. Be ready to radically change the way you think and build Web applications. With Restlet in our backpack, we are certain that you will enter the REST world with the best toolkit available!

As a truly open source project, we not only consider you as a user but as a potential contributor. You will soon find ways to contribute back to the project, by filing a bug or enhancement reports, by submitting documentation or code improvements or by helping other users or developers in the mailing lists. Every contribution is valuable to the community and we give credit back to our team by listing all the contributors on our team page.

1.2 Overview

Restlet is a lightweight REST framework for Java that lets you embrace the architecture of the Web and benefit from its simplicity and scalability. By leveraging our innovative REST engine, you can start blending your Web Sites and Web Services into uniform Web Applications!

Restlet has a light core but thanks to its pluggable extension, it is also a comprehensive REST framework for Java. It supports all REST concepts (Resource, Representation, Connector, Component, etc.) and is suitable for both client and server Web applications.

It supports major Web standards like HTTP, SMTP, XML, JSON, WADL, and Atom. Many extensions are also available to integrate with Servlet, Spring, Jetty, Grizzly, Simple, JAXB, JAX-RS, JiBX, Velocity, or FreeMarker.

A GWT version is also available and is a direct port of the main Java version.

1.3 Additional information

From the Restlet.org web site

1.4 Usage scenarios

1.4.1 Introduction

Restlet is a very flexible framework that is suitable for most Web application developments.

1.4.2 Client and server side

Thanks for its unique design, it can be used for both client-side and server-side applications and of course for applications that act as both clients and servers. With the availability of a port for the GWT plateform, it can also works in your favorite Web browser!

1.4.3 Servlet compatible

Restlet was an attempt to build a better Servlet API, more inline with the true Web architecture (REST) and standards (HTTP, URI). Therefore the Restlet API has no dependency on the Servlet API, it only depends on the Java SE. However, it is perfectly possible to deploy a Restlet application into JEE application server and Servlet containers. This is possible using a simple adapter Servlet provided as an extension.

1.4.4 Complete Web server

Contrary to the Servlet API, the Restlet API gives you an extensive control on the URI mapping and on the virtual hosts configuration. It allows includes a powerful Directory class to server static files in a way comparable to what a Apache Web Server would do. For example, we run our Restlet.org web site directly with Restlet!

1.4.5 Technology agnostic

By staying open to all presentation technologies (HTML, Swing, Eclipse, GWT, AJAX, etc.), all persistence technologies (JDBC, Hibernate, db4o, iBatis, etc.) and all execution environments (standalone Java, JEE, Servlet, Spring, OSGi, Guice, SLEE, etc.), your investment in Restlet is secured. With very little care, your Restlet applications can even be fully portable from one environment to the other.

1.5 Other Sources

In addition to the current documentation, here is a list of additional sources of information that we recommend:

  1. Restlet.org (Javadocs, Mailing lists, Issue tracker, etc.)
  2. On REST.org (REST search engine and blog)
  3. Noelios.com (technical support, commercial licenses, services, etc.)
  4. More REST related resources

2 What's new

2.1 Introduction

After one year and half of development, the Restlet project has made tremendous progress. We will try to summarize here the main benefits that you can expect by migrating from Restlet 1.0 to the latest 1.1 version.

2.2 Uniform Development Environment

Truly boost the productivity of your team by leveraging our uniform Restlet API:

In order to deal with your largest development needs, support for application modularization has been added. It is now easy to split a large application into several ones, and still be able to efficiently communicate. There is a new internal protocol (RIAP) to do private RESTful calls between applications hosted in the same JVM.

2.3 Improved Deployment Flexibility

The Restlet project has always been open to other technologies and tries to give its developers the maximum freedom in term of deployment. We don't try to lock you down to a specific technology. Here is the current list of deployment environments that you can target:

Most of the time, your Restlet Applications code will be fully portable, requiring only simple deployment configuration adjustments.

Regarding configuration, we now support our own compact XML syntax. This can be very convenient, in addition to the usual programmatic way, to let administrators tweak the configuration of Restlet components, connectors and virtual hosts, without recompiling the source code. This is also possible to leverage Spring XML configuration mechanism to similar results.

2.4 Automatic REST API Documentation

Don't you think that having a comprehensive, fully customizable and always up-to-date documentation for your REST API is essential? We do and made some major enhancements on this front in collaboration with our customers and users.

In this new version, we think we have the most complete and useful support for WADL (Web Application Description Language), the equivalent of WSDL for RESTful applications. Thanks to our WADL extension, you can now have your whole application, or just each single resource self-described. The WADL documentation can be dynamically generated from your source code and exposed either as machine processable XML (WADL) or as human readable HTML (WADL) documents.

2.5 Significantly Improved Performance

Top notch performance has always been a core concern for us. This led to the implementation of a pluggable connector mechanism in Restlet 1.0, and the shipping of several HTTP connector options such as Jetty and Simple.

In Restlet 1.1, we continued on this path and added a brand new Grizzly HTTP server based on the very responsive and scalable NIO framework developped by the Sun Glassfish project. This connector fits perfectly with the NIO provisions in the Restlet API, resulting in direct disk-to-socket sending of static files and reduced memory and CPU usage!

We have also added very convenient internal HTTP client and server connectors that ensure that you can get started right away with your Restlet development needs. This is also a perfectly suitable option for compact or embedded deployment scenarios.

2.6 More Licensing Options

Led by the founder of the Restlet project, the Noelios Technologies company is now the main copyright holder of the Restlet source code. It funds most development efforts and incorporate contributions from the active Restlet community.

As a result, it can offers flexible licensing options to suit the needs of all users of the technology:

2.7 More Extensions

In order to keep our core library light and focused, we have proposed an extension mechanism in Restlet 1.0. This makes sure that we don't force technology choice, beside the RESTful design at the core of the project, onto our users. Instead, we prefer to give them open integration options with their favorite technologies such as JavaMail, FreeMarker, JSON or Velocity.

In Restlet 1.1, we have continued those efforts and added the following extensions:

2.8 API improvements

2.9 Connectors

2.10 Extensions

2.11 Misc

2.12 Migration guide from Restlet 1.0 to 1.1

2.12.1 Introduction

This guide intends to explain the main differences between the Restlet 1.0 and 1.1 releases and to help you migrate your existing applications.

It presents a set of important modifications related to:

2.12.2 Important breaking changes

2.12.2.1 Handling of context

The handling of Context has been significantly refactored in the 1.1 release due to security reasons. In release 1.0, a Component shared its context between all attached applications. It appeared that this design could lead to conflicts where an application would update the component's context and thus impact the behavior of the other applications.

Here are the main changes implemented in the 1.1 release:

Thus, we encourage you to override the default Application() constructor instead of the Application(Context) one which is only useful in a few cases where you need to immediately have access to the application's context.

Another consequence is that parameters or attributes are not copied from the component to the application by the default implementation of the Context#createChildContext() method which is typically used to prepare the Application's context based on the parent Component's context.

2.12.2.2 Sample code

When a component instantiate an Application, or any kind of Restlet, it is no more mandatory to specify the context. Taking a simple component that attaches an application, here is the ancient way to achieve this:

Component component = new Component();

// Add a new HTTP server listening on port 8182.
component.getServers().add(Protocol.HTTP, 8182);

// Attach the sample application.
component.getDefaultHost().attach(new FirstStepsApplication(component.getContext()));

And now, here is the new way:

Component component = new Component();

// Add a new HTTP server listening on port 8182.
component.getServers().add(Protocol.HTTP, 8182);

// Attach the sample application.
component.getDefaultHost().attach(new FirstStepsApplication());

If you still need to handle the context in the Application constructor, you must do as follow:

Component component = new Component();

// Add a new HTTP server listening on port 8182.
component.getServers().add(Protocol.HTTP, 8182);

// Attach the sample application.
component.getDefaultHost().attach(new FirstStepsApplication(component.getContext().createChildContext()));

The application is instantiated with a child context, not the component context. Otherwise, your application might not start properly and a log trace will warn you.

2.12.3 Handling of resources

Some new boolean attributes have been added on the resource class. They help to specify the state of a Resource instance.

2.12.4 Usage of the Servlet Adapter

2.12.5 Accessing current objects

Some recurrent need is to access current objects such as the current application, the current context, etc. Although, the API of some objects gives direct access to such properties (e.g. "Resource#getApplication"), it was generally not the case with Restlet 1.0, thus some static methods have been introduced in Restlet 1.1:

Method name

Description

Response.getCurrent()

The current Response object handled by the current thread.

Application.getCurrent()

The current Application object handled by the current thread.

Context.getCurrent()

The current Context handled by the current thread.

Context.getCurrentLogger()

Always returns a non-null logger, if possible the current context's logger.

These methods may help you to reduce the number of lines of code but, for proper object-oriented design, we recommend using them only under duress. Typical case is when you need to integrate Restlet code with a third-party library that doesn't let you pass in your Restlet context or objects. For example, you should by default prefer obtaining the current context using methods such as Restlet.getContext() or Handler.getContext().

2.12.6 Accessing the original resource's reference

New features have been added to the tunnel filter. Some of them allow you to automatically update the request according to some parameters specified in the query part of the target resource's reference. In this case, it happens that the resource's reference is updated. If you still want to access the original reference, a new attribute has been added to the Request object called "originalRef'".

2.12.7 Handling of statuses and exceptions

A new "ResourceException" class has been introduced. Basically, it encapsulates a status and the optional cause of a checked exception. This exception may be thrown by a Resource instance when handling GET, POST, PUT, etc requests. This exception can be handled by the status service when rendering error statuses.

2.12.8 Miscellaneous

This section lists several updates that may have an impact on your existing code

2.12.9 Deprecations

2.12.9.1 Resource class

List of renamed methods to prevent confusion with lower-level methods handleGet(), handletPost(), handlePut() and handleDelete() now part of the parent class of Resource, the Handler class.

Method

Replacement

getPreferredRepresentation()

represent()

getRepresentation(Variant)

represent(Variant)

post(Representation)

acceptRepresentation(Representation)

put(Representation)

storeRepresentation(Representation)

delete()

removeRepresentations()

2.12.9.2 Variant class

Some properties and methods have been moved to the Representation subclass

2.12.9.3 TunnelService

List of renamed methods.

Method

Replacement

getCharacterSetAttribute

getCharacterSetParameter

setCharacterSetAttribute

setCharacterSetParameter

getEncodingAttribute

getEncodingParameter

setEncodingAttribute

setEncodingParameter

getLanguageAttribute

getLanguageParameter

setLanguageAttribute

setLanguageParameter

getMediaTypeAttribute

getMediaTypeParameter

setMediaTypeAttribute

setMediaTypeParameter

2.12.9.4 MetadataService

This class allows to link a metadata with several extensions name. However, only the first one in the list will be returned by the getExtension(Metadata), it is considered as the preferred one. The "getMappings" and "setMappings" methods have been removed. Instead, use getExtension(Metadata), getMetadata(String) and the addExtension(String, Metadata), addExtension(String, Metadata, boolean preferred), clearExtension methods

2.12.9.5 ConverterService

Since 1.1 with no replacement as it doesn't fit well with content negotiation. Most users prefer to handle those conversion in Resource subclasses.

2.12.9.6 Request

As a consequence of the previous change, the following methods are not replaced: Request#getEntityAsObject, Request#setEntity(Object)

2.12.9.7 Response

List of renamed methods.

Method

Replacement

getChallengeRequest

getChallengeRequests

getRedirectRef

getLocationRef

setRedirectRef

setLocationRef

2.12.9.8 Finder

Method

Replacement

createResource(Request, Response)

 createTarget(Request, Response) and take care of the targetClass property.

2.12.9.9 Template

Removed the Logger parameter to all constructors. which still can be set with the setLogger(Logger) method.

2.12.9.10 Restlet

The init(Request, Response) method is removed. Instead, make sure that you call the {@link #handle(Request, Response)} method from your Restlet superclass.

2.12.9.11 Form

Removed the Logger parameter to all constructors.

2.12.9.12 Status

Method

Replacement

isInfo(int code)

isInformational(int)

isInfo()

isInformational()

2.12.9.13 ChallengeScheme

ChallengeScheme HTTP_AWS replaced by HTTP_AWS_S3

2.12.9.14 Protocol

The SMTP_STARTTLS protocol is removed. Use the "startTls" parameter on the JavaMail connector instead.

2.12.9.15 Response

Method

Replacement

getChallengeRequest

getChallengeRequests

getRedirectRef

getLocationRef

setRedirectRef

setLocationRef

2.12.9.16 Guard

List of renamed methods.

Method

Replacement

challenge(Response)

challenge(Response, boolean) The added boolean indicates if the new challenge is due to a stale response.

checkSecret(String, char[])

checkSecret(Request, String, char[]) Added the request parameter

2.12.9.17 Context

List of renamed method.

Method

Replacement

getDispatcher

getClientDispatcher NB: it exists a server dispatcher.

2.12.9.18 TransformRepresentation

List of renamed methods

Method

Replacement

getURIResolver

getUriResolver

3 Getting started

We recommend that you consult the documentation available on the Restlet Web site to get you started. You will find a screencast, first steps and more detailed tutorial.

3.1 Setting up your environment with Maven

Maven is a comprehensive project management system built around the concept of POM (Project Object Model). One of the main advantages is the automated handling of project dependencies, including their download. For more information on Maven, check the project home page.

It is easy to use Restlet in a Maven environment because all the Restlet artifacts are published in a dedicated Maven repository. For configuration details, you can read this page.

3.2 Setting up your environment with Eclipse

There are two ways to use Restlet within Eclipse. The first is to use the Restlet JARs as external project dependencies. This is very simple and works well in most cases.

The second is to install Restlet JARs as Eclipse/OSGi bundles. All Restlet JARs including dependencies are valid OSGi bundles, so this is very convenient if you work in an Eclipse plug-in environment, such as an Eclipse RCP application.

You can find more information in this FAQ entry: What is the best way to use Restlet in Eclipse?

4 Restlet API

This chapter presents the Restlet API. It is a small set of packages, with classes, interfaces and enumerations that together provide a framework. This framework will guide you on the path to RESTful design and development. But be aware that you still need to understand REST in order to fully take advantage of the Restlet features. For this purpose, we recommend the book "RESTful Web Services" from O'Reilly. We even wrote a part of it covering Restlet usage.

For a more detailed presentation of the API, we recommend that you have a close look at the Restlet Tutorial and at the Javadocs of the API, both available on the Restlet Web site.

4.1 Mapping HTTP semantics

4.1.1 Introduction

The Restlet API offers a higher level view of the HTTP protocol. It tries to abstract and present in a clean object model, the application-level semantics of HTTP. As a side feature, it is possible to map other protocols to the same semantics, such as FILE, FTP, SMTP, etc.

However, developers often know lower-level details of HTTP or need to understand them for debugging purpose. This is the reason for this document, explain the mapping between the HTTP semantics and the Restlet API.

Note that the headers that are not supported yet can still be overridden via the "org.restlet.http.headers" attribute of the request or the response. A warning message is  logged : "Addition of the standard header "XXX" is discouraged. Future versions of the Restlet API will directly support it".

See details in the Javadocs of the Message.getAttributes() method.

4.1.2 Mapping headers

HTTP header

Restlet property

Description

Accept

request.clientInfo.acceptedMediaTypes

The list of media-types accepted by the client. 

Accept-Charset

request.clientInfo.acceptedCharacterSets

The list of character sets accepted by the client.

Accept-Encoding

request.clientInfo.acceptedEncodings

The list of encodings accepted by the client.

Accept-Language

request.clientInfo.acceptedLanguages

The list of languages accepted by the client.

Accept-Ranges

[connector level]

Allows the server to indicate its support for range requests

Age

-

Support for caching planned for Restlet 1.2

Allow

response.allowedMethods

For "Handler" subclasses (such as Resource), a dynamic search is made that looks for the "allow*" methods declared on the class and that return "True".

Authentication-Info

-

Non standard HTTP header.

Authorization

request.challengeResponse

Credentials that contain the authentication information of the user agent for the realm of the resource being requested.

Cache-Control

-

Support for caching planned for Restlet 1.2

Connection

[connector level]

Set to "close" according to the server or client connector property (serverKeepAlive or clientKeepAlive).

Content-Disposition

message.entity.downloadName

If the download name is not null, the header value is "attachment; filename=<entity.downloadName>".

Content-Encoding

entity.encodings

Indicates what additional content codings have been applied to the entity-body.

Content-Language

entity.languages

Describes the natural language(s) of the intended audience for the enclosed entity.

Content-Length

entity.size

The size of the entity-body, in decimal number of OCTETs.

Content-Location

entity.identifier

Indicates the resource location for the entity enclosed in the message.

Content-MD5

representation.digest

Value and algorithm name of the digest associated to a representation.

Content-Range

entity.range

Indicates where in the full entity-body the partial body should be applied

Content-Type

entity.mediaType and entity.characterSet

Indicates the media type of the entity-body.

Cookie

request.cookies

List of one or more cookies sent by the client to the server.

Date

current date

The date and time at which the message was originated.

ETag

entity.tag

The current value of the entity tag for the requested variant.

Expect

-

Support for expect header planned for Restlet 1.2

Expires

entity.expirationDate

The date/time after which the response is considered stale.

From

-

Support for misc headers planned for later

Host

request.resourceRef (domain and port)

Specifies the Internet host and port number of the resource being requested.

If-Match

request.conditions.match

Used with a method to make it conditional.

If-Modified-Since

request.conditions.modifiedSince

Used with a method to make it conditional.

If-None-Match

request.conditions.noneMatch

Used with a method to make it conditional.

If-Range

-

Support planned for Restlet 1.2

If-Unmodified-Since

request.conditions.unmodifiedSince

Used with a method to make it conditional.

Last-Modified

entity.modificationDate

Indicates the date and time at which the origin server believes the variant was last modified.

Location

response.locationRef

Used to redirect the recipient to a location other than the Request-URI for completion of the request or identification of a new resource.

Max-Forwards

-

Support for proxies planned for later

Pragma

-

Support for caching planned for Restlet 1.2

Proxy-Authenticate

-

Support for proxies planned for later

Proxy-Authorization

-

Support for proxies planned for later

Range

request.ranges

List one or more ranges to return from the entity

Referer

request.refererRef

The address (URI) of the resource from which the Request-URI was obtained.

Retry-After

-

Support for misc headers planned for later

Server

response.serverInfo.agent

Information about the software used by the origin server to handle the request.

Set-Cookie

response.cookieSettings

List of one or more cookies sent by the server to the client.

Set-Cookie2

response.cookieSettings

List of one or more cookies sent by the server to the client.

TE

-

Not supported yet

Trailer

-

Support for misc headers planned for later

Transfer-Encoding

entity.size

Valuated to "chunked" if the entity is not null and its size is unknown (Representation.UNKNOWN_SIZE)

Upgrade

-

Support for misc headers planned for later

User-Agent

request.clientInfo.agent

Information about the user agent originating the request.

Vary

response.dimensions

Indicates the set of request-header fields that fully determines, while the response is fresh, whether a cache is permitted to use the response to reply to a subsequent request without revalidation.

Via

-

Support for proxies planned for later

Warning

-

Support for caching planned for Restlet 1.2

WWW-Authenticate

response.challengeRequests

Indicates the authentication scheme(s) and parameters applicable to the Request-URI.

X-Forwarded-For

request.clientInfo.addresses

The list of client IP addresses, including intermediary proxies.

X-HTTP-Method-Override

-

Support for method tunnelling via header planned for Restlet 1.2

4.1.3 Appendix

Registry of headers maintained by IANA.

Regsitry of HTTP status codes maintained by IANA.

4.2 Connectors

4.2.1 Introduction

A connector in the REST architecture style is a software element that manages network communication for a component, typically by implementing a network protocol (e.g. HTTP). A client connector initiates communication with a server (of any kind) by creating a request. A server connector listens for connections (from clients of any kind), transmits the request to the component that performs the request processing, creates the response and sends it to the client.

All connectors are provided as extensions of the Noelios Restlet Engine, the reference implementation of the Restlet API.

This document will describe how to add a connector to your application, how to configure it and will give you the list of available server and client connectors.

4.2.2 Add a connector to your application

All connectors and their dependencies are shipped with the Restlet distribution by the way of jar files. Adding a connector to your application is as simple as adding the archives of the chosen connector and its dependencies to the classpath.

You can also have a look to the FAQ #4 and FAQ #5 which completes this subject.

4.2.3 Configuration

Each connector looks for its configuration from its context. The latter provides a list of modifiable parameters, which is the right place to set up the connector's configuration. Some parameters are defined by the NRE engine and thus are shared by all clients (in the ClientHelper hierarchy) and server connectors (in the ServerHelper hierarchy), and most of them by the connector's ClientHelper or ServerHelper subclasses.

The list of all parameters are available in the javadocs. Pleaser refer to the rest of this document for references to these documentation.

4.2.3.1 Server connectors

Here are the commons parameters dedicated to HTTP server connectors.

Here is a sample code showing how to set such a parameter.

// Creating a minimal Restlet returning "Hello World"
Restlet restlet = new Restlet() {
    @Override
    public void handle(Request request, Response response) {
        response.setEntity("Hello World!", MediaType.TEXT_PLAIN);
    }
};

// Create the HTTP server and listen on port 8182
Server server = new Server(new Context(), Protocol.HTTP, 8182, restlet);
server.getContext().getParameters().add("useForwardedForHeader", "true");
server.start();

4.2.3.2 Client connectors

Here are the commons parameters dedicated to HTTP client connectors.

Here is a sample code showing how to set such a parameter.

Client client = new Client(new Context(), Protocol.HTTP);
client.getContext().getParameters().add("converter",
                       "com.noelios.restlet.http.HttpClientConverter");

4.2.4 List of available connectors

4.2.4.1 Server connectors

Extension

Version

Protocols

Internal

1.1

HTTP, RIAP

Grizzly

1.8

HTTP, HTTPS

Jetty

6.1

HTTP, HTTPS, AJP

Simple

3.1

HTTP, HTTPS

Servlet

2.5

HTTP, HTTPS, AJP

4.2.4.2 Client connectors

Extension

Version

Protocols

Internal

1.1

HTTP, CLAP, FILE, RIAP

Apache HTTP Client

3.1

HTTP, HTTPS

Net (JDK's HttpURLConnection)

1.5

HTTP, HTTPS

JavaMail

1.4

SMTP, SMTPS, POP, POPS

JDBC

3.0

JDBC

4.3 Securing applications

4.3.1 Introduction

As there are numerous protocols (like HTTP, SMTP, etc.) that we want to support and as each one has various ways to authenticate requests (HTTP Basic, HTTP Digest, SMTP Plain, etc.), the Restlet API provides a flexible mechanism to support authentication.

4.3.1.1 Confidentiality

SSL is typically used to ensure that requests and responses are exchanged confidentially between clients and a server. Configuring SSL requires the setting of several parameters on the HTTPS server connector instance used. You need to provide a key store containing the certificate for your server instance.  See connectors' documentation for more configuration details.

Note that SSL configuration is closely associated with an IP address and a listening port. This may cause issue with the usage of virtual hosting where several domains and applications share the same IP adress and listening port. It is not possible to associate a SSL certificate per virtual host because in order to determine a virtual host, we need to have read and parsed the HTTP request headers to get the "Host" header. You can only do that if you already use the certificate to read the incoming SSL stream.

In this case, the only solution is to have two listening server sockets (hence two IP addresses if you want to use the default HTTPS 443 port) and then two Restlet server connectors configured, each one pointing to a specific certificate. With some additional work, it is possible to use the same key store to provide both certificate. This requires usage of alias names and custom SSL context factories.

In addition to the parameters that are similar but specific to each type of HTTPS server connector, it is possible to configure the SSL connectors using an SslContextFactory, in a way that is common to all three types of HTTPS server connectors (Simple, Jetty and Grizzly). Configuring SSL is done in this order:

  1. An instance of SslContextFactory can be passed in the sslContextFactory attribute of the connector's context. This can be useful for cases that requires such an instance to be customized.
  2. When no sslContextFactory attribute is set, the full name of a concrete class extending SslContextFactory can be passed in the sslContextFactory parameter of the connector's context. Such a class must have a default constructor. The context's parameters are passed to its init method, so as to initialize the SslContextFactory instance via text parameters.
    The com.noelios.restlet.util.DefaultSslContextFactory is an SslContextFactory that supports a basic set of parameters, and will default to the values specified in the javax.net.ssl.* system properties (see JSSE Reference guide).
    There can in fact be several values of sslContextFactory (since there can be several values for parameters), in which case the first one constructed and initialized successfully will be used.
  3. If no sslContextFactory attribute or parameter is set, the configuration will fall back to the parameters that are specific to each type of connector.

SSL client authentication is not configured as part of the SSL context, although the trust store and which peer certificates to trust are.

4.3.1.2 Authentication

In Restlet, authentication and authorization are handled very differently than in the Servlet world. Here you have full control of the process, no external XML descriptor is necessary.

The default approach is to use the org.restlet.Guard class (a Restlet filter) or a subclass of it. By default, this class uses a map to store the login/password couples but this can be customized by overriding the "authenticate(Request)" method.

From an org.restlet.data.Request, the login/password can be retrieved using these methods:

 - Request.getChallengeResponse().getIdentifier() : String    // LOGIN
 - Request.getChallengeResponse().getSecret() : String        // PASSWORD

The HTTP server connectors currently only support HTTP BASIC authentication (the most widely used).

4.3.1.2.1 SSL client authentication

To enable client-side SSL authentication on an HTTPS server connector, set the wantClientAuthentication or needClientAuthentication parameters to true (in the first case, presenting a client certificate will be optional). The chain of client certificate is then accessible as List of X509Certificates in the org.restlet.https.clientCertificates Request attribute.

4.3.1.3 Coarsed grained authorization

For the authorizations that are common to a set of resources, a Guard subclass can also be used by overriding the "authorize(Request)" method. Note that this method accepts all authenticated requests by default. You can plugin in your own mechanism here, like an access to a LDAP repository.

4.3.1.4 Fine grained authorization

If the permissions are very fine grained, the authorizations should probably handled at the resource level directly instead of the Guard filter level (unless you want to put a filter in front of each resource). With the approach, you can make your permission depend on the value of the target resource on the resource and specific method invoked, etc.

4.3.2 Actors

4.3.2.1 Restlet API

4.3.2.1.1 ChallengeRequest

Contains information about the authentication challenge that is sent by an origin server to a client.

For server-side Restlet applications, this object will typically be created and set on the current Response by a Guard added to the request processing chain. Then, when the response goes back to the Restlet engine, the server connector and the matching authentication helper will format it into the proper protocol artifact such as a "WWW-Authenticate" header in HTTP.

For client-side Restlet applications, this object will typically be received in response to a request to a target resource requiring authentication. In HTTP, this is signalled by a 401 (Unauthorized) status. This means that a new request must be sent to the server with a valid challenge response set for the required challenge scheme. The client connector and matching AuthenticationHelper are responsible for parsing the protocol artifact such as the "WWW-Authenticate" header in HTTP.

4.3.2.1.2 ChallengeResponse

Contains information about the authentication challenge response sent by a client to an origin server.

For server-side Restlet applications, this object will typically be created by the server connector with the help from the matching AuthenticationHelper for parsing.

For client-side Restlet applications, this object must be manually created before invoking the context's client dispatcher for example.

4.3.2.1.3 ChallengeScheme

Indicates the challenge scheme used to authenticate remote clients. This only identifies the scheme used or to be used but doesn't contain the actual logic needed to handle the scheme. This is the role of the AuthenticatorHelper subclasses.

4.3.2.1.4 Guard

This is a Restlet Filter that guards the Restlets or Resources attached to it from unauthenticated and/or unauthorized requests.

  1. When a request reaches it, it first attempts to authenticate it, i.e. to make sure that the challenge scheme used is supported and that the credentials given by the client (such as a login and password) are valid. The actual implementation of the authentication is delegated to the matching authentication helper. The result of this authentication can be:
    1. Valid: the authentication credentials are valid, the right scheme was used and the credentials could be verified by calling back the checkSecret() method on Guard. Here are the next steps
      1. The authorize() method is called and if authorization is given the accept() method is invoked, which delegates to the attached Restlet or Resource by default. Otherwise, the forbid method is called, which sets the response status to CLIENT_ERROR_FORBIDDEN (403).
    2. Missing: no credentials could be found, the challenge() method is invoked which delegates to the matching authenticator helper.
    3. Invalid: bad credentials were given such as a wrong password or unsupported scheme was used. If the "rechallenge" property is true, the challenge() method is invoked otherwise, the forbid() method is invoked.
    4. Stale: the credentials expired and must be renew. Therefore, the challenge() method is invoked.

4.3.2.2 Noelios Restlet Engine

Most of the logic related to authentication is located in the package "com.noelios.restlet.authentication".

4.3.2.2.1 AuthenticationUtils

Static utilities methods to parse HTTP headers, find the matching authentication helper and misc methods.

4.3.2.2.2 AuthenticationHelper

Base class for authentication helpers.

There are also subclasses for the schemes internally supported by the NRE :  HTTP Basic, HTTP Digest, HTTP Amazon S3 (client) and SMTP Plain.

4.3.2.3 Extensions

In addition to the internal authentication helpers, additional schemes can be supported using pluggable extensions. Currently, there is an extension available for the HTTP OAuth scheme.

4.3.3 Authentication

4.3.3.1 Introduction

There are two commons ways to authenticate your users with your Restlet application. The first is to use is to leverage the standard HTTP authentication mechanism, either the Basic or the Digest authentication. The Basic mechanism is sending the password in clear and should only be used over a secure HTTPS channel. The second mechanism is to use a custom authentication form and some cookie set by the server.

4.3.3.2 HTTP Basic authentication

4.3.3.2.1 Introduction

Here is a very simple code illustrating a component that guards its applications with the BASIC authentication scheme.

The whole code can be downloaded here.

4.3.3.2.2 Description of the server side
4.3.3.2.2.1 Component

The sample component is composed of two parts. The first one is a very simple Restlet that answers to request with a "hello, word" text representation. Of course this Restlet is a very simple representation of your own complex application.

// Restlet that simply replies to requests with an "hello, world" text message
Restlet restlet = new Restlet() {
    @Override
    public void handle(Request request, Response response) {
        response.setEntity(new StringRepresentation("hello, world", MediaType.TEXT_PLAIN));
    }
};

Then, the component protects this Restlet with a Guard instance based on the BASIC authentication scheme. Once the instance is created, it is given the list of known (login/password) pairs via the "secrets" attibute.

// Guard the restlet with BASIC authentication.
// Use the basic guard
Guard guard = new Guard(component.getContext().createChildContext(), ChallengeScheme.HTTP_BASIC, "Sample application.");

// Load a single static login/secret pair.
guard.getSecrets().put("login", "secret".toCharArray());

guard.setNext(restlet);

component.getDefaultHost().attachDefault(guard);
4.3.3.2.2.2 Customization

The authentication and authorization decisions are fully customizable via the authenticate() and authorize() methods of the Guard class. Any custom mechanism can be used to check whether the given credentials are valid and whether the authenticated user is authorized to continue to the attached Restlet.

4.3.3.2.2.3 Description of the client side

The credentials are transmitted to the request via a ChallengeResponse object as follow:

Reference reference = new Reference("http://localhost:8182/");
Client client = new Client(Protocol.HTTP);
Request request = new Request(Method.GET, reference);

// Send an authenticated request using the Basic authentication scheme.
ChallengeResponse authentication = new ChallengeResponse(ChallengeScheme.HTTP_BASIC, "login", "secret");
request.setChallengeResponse(authentication);

// Send the request
Response response = client.handle(request);
// Should be 200
System.out.println(response.getStatus());

4.3.3.3 HTTP Digest authentication

4.3.3.3.1 Introduction

Here is a very simple code illustrating a component that guards its applications with the DIGEST authentication scheme.

The whole code can be downloaded here.

4.3.3.3.2 Description of the server side
4.3.3.3.2.1 Component

The sample component is composed of two parts. The first one is a very simple Restlet that answers to request with a "hello, word" text representation. Of course this Restlet is a very simple representation of your own complex application.

// Restlet that simply replies to requests with an "hello, world" text message
Restlet restlet = new Restlet() {
    @Override
    public void handle(Request request, Response response) {
        response.setEntity(new StringRepresentation("hello, world", MediaType.TEXT_PLAIN));
    }
};

Then, the component protects this Restlet with a Guard instance based on the DIGEST authentication scheme. A dedicated constructor of the Guard class of the Restlet API allows you to create such instance. Once the instance is created, it is given the list of known (login/password) pairs via the "secrets" attibute.

// Guard the restlet with DIGEST authentication.
Collection<String> baseUris = new ArrayList<String>();

// Use the basic guard
Guard guard = new Guard(component.getContext().createChildContext(), "realm", baseUris, "serverKey");

// Load a single static login/secret pair.
guard.getSecrets().put("login", "secret".toCharArray());

guard.setNext(restlet);

component.getDefaultHost().attachDefault(guard);
4.3.3.3.2.2 Customization

As you may have noticed earlier, the list of known login/password pairs are loaded by the basic Guard via the "secrets" attribute. This is useful when the list of pairs are known by advance and is not susceptible to change. In a more realistic case, the credentials are hosted in a database or a LDAP directory, etc. In this case, the responsibility to resolve the password according to the login is deported to a dedicated sub class of the org.restlet.util.Resolver. An instance of this sub class will be finally passed to the Guard as follow:

// Guard the restlet with DIGEST authentication.
Collection<String> baseUris = new ArrayList<String>();

// Use the basic guard
Guard guard = new Guard(component.getContext().createChildContext(), "realm", baseUris, "serverKey");

// Use the customized resolver
guard.setSecretResolver(new TestResolver());

guard.setNext(restlet);

component.getDefaultHost().attachDefault(guard);

The contract of the Resolver is a simple method which aims at returning the given password according to the given login:

import org.restlet.util.Resolver;

/**
 * Customized resolver.
 */
public class TestResolver extends Resolver<char[]> {

    /**
     * Returns the value that corresponds to the given name.
     */
    @Override
    public char[] resolve(String name) {
        // Could have a look into a database, LDAP directory, etc.
        if ("login".equals(name)) {
            return "secret".toCharArray();
        }

        return null;
    }
}
4.3.3.3.3 Description of the client side

The authentication with the DIGEST scheme is bit more difficult than the one for the BASIC scheme. The credentials provided by the client is the result of computation of data given by the client on one side (login and password) and by the server on the other side ("nonce" value, "realm" value, etc.). Unless these pieces of data are known in advance by the client, it appears that in general a first request is required in order to collect them.

Reference reference = new Reference("http://localhost:8182/");

Client client = new Client(Protocol.HTTP);
Request request = new Request(Method.GET, reference);

// Create the Challenge response used by the client to authenticate its requests.
ChallengeResponse challengeResponse = new ChallengeResponse(ChallengeScheme.HTTP_DIGEST, "login", "secret");
request.setChallengeResponse(challengeResponse);

// Send the first request
Response response = client.handle(request);
// Should be 401, since the client needs some data sent by the server in
// order to complete the ChallengeResponse.
System.out.println(response.getStatus());

Then, the second step allows to get the required data for the final computation:

// Complete the challengeResponse object according to the server's data
Form form = new Form();
form.add("username", "login");
form.add("uri", reference.getPath());

// Loop over the challengeRequest objects sent by the server.
for (ChallengeRequest challengeRequest : response.getChallengeRequests()) {
    // Get the data from the server's response.
    if (ChallengeScheme.HTTP_DIGEST.equals(challengeRequest.getScheme())) {
        Series<Parameter> params = challengeRequest.getParameters();
        form.add(params.getFirst("nonce"));
        form.add(params.getFirst("realm"));
        form.add(params.getFirst("domain"));
        form.add(params.getFirst("algorithm"));
        form.add(params.getFirst("qop"));
    }
}

Then, we compute the data into the final digested value:

// Compute the required data
String a1 = Engine.getInstance().toMd5("login" + ":" + form.getFirstValue("realm") + ":" + "secret");
String a2 = Engine.getInstance().toMd5(request.getMethod() + ":" + form.getFirstValue("uri"));
form.add("response", Engine.getInstance().toMd5(a1 + ":" + form.getFirstValue("nonce") + ":" + a2));
challengeResponse.setCredentialComponents(form);

Finally, the request is completed with the updated ChallengeResponse instance

// Send the completed request
request.setChallengeResponse(challengeResponse);
response = client.handle(request);

// Should be 200.
System.out.println(response.getStatus());

4.3.4 Authorization

4.3.4.1 Description

By default, the Guard class autorizes all the sucessfully authenticated requests to go to the next Restlet attached to it. However it is very easy to change this behavior to introduce any sort of authorization mechanism.

The method to override is Guard#authorize(Request request) which returns true by default.

4.3.5 Configuring HTTPS

Background

HTTPS is HTTP over SSL or TLS, that is, secure HTTP. SSL and TLS normally rely on Public Key Cryptography, which requires a pair of keys to encrypt and decrypt messages – one key is a private key and the other is a public key. As the names imply, a private key is only known to the person/computer that created it, while the public key is made available to everyone. The public key and the private key complement each other. There are two main operations that can be performed: encryption and signing. Encryption is used to make the content of a message secret and is done using the public key; decryption can then only be performed using the corresponding private key. Signing is used to assert the authenticity of a message and involves similar operations, but is done using the private key; then, validating the signature is done using the corresponding public key.

The distribution of the public keys and their binding to an identity is done by the Public Key Infrastructure (PKI), which uses certificates. A certificate (usually X.509) is essentially a signed statement that includes a public key and other information such as date of validity, subject distinguished name (which associates an identity with this) or the issuer distinguished name (which gives the identity of the signer). The signer of such a certificate is usually a certificate authority (CA), which may be a company such as Thawte or VeriSign, who may charge you for this service, or can be a local CA created within your institution or company. PKIs describe the relationships and trust models between the CAs and are associated with legal documents describing the intended use of various X.509 attributes (depending on CA policies).
However, certificates can also be self-signed, in which case the trust model has to be established by some other means (for example, someone you trust gives you this certificate). Self-certification is fine for testing in a limited and controlled environment, but is not generally suitable for production environments.

In HTTPS, HTTP lies on top of SSL (or TLS). The client first establishes the SSL connection (which is not aware of HTTP): the client initiates a conversation with a server. As part of the SSL handshake, the server first sends its certificate to the client as proof that the server is who/what it claims to be. This certificate is checked by the client against a list of certificates that it 'trusts'. How does a client know which certificates to trust? It depends on the client. A Java program uses a trust store (which is by default the 'cacerts' file within the JRE and which comes with a pre-populated list of trusted certificates/certification authorities); what the trust store is may be configured in Java. Similarly, browsers may maintain their own lists or – in the case of Windows or OSX – may use a feature of the operating system (e.g. Internet Options or Keychain). You can add your own certificates to these lists, or tell the Java VM, browser and/or your client operating system to trust the certificates you have created. If as part of this SSL handshake, the server certificate is not verified and trusted by the client, the SSL connection will be closed before any HTTP traffic.

When connecting to a server, not only the certificate should be verified, but the identity of the host name of the server should be checked against the certificate. Clients check that they are indeed communicating with the server they intend by checking that the common name (CN) field of the subject distinguished name in the server certificate is the host name intended. This host name can also be placed in the subject alternative name attribute in the certificate.

A Java container of keys and certificates is called a keystore. There are two usages for keystores: as a keystore (the name may be confusing indeed) and as a truststore. The keystore contains the material of the local entity, that is the private key and certificate that will be used to connect to the remote entity (necessary on a server, but can be used on a client for client-side authentication). Its counterpart, the truststore, contains the certificates that should be used to check the authenticity of the remote entity's certificates. There are various keystore types supported by the Sun JVM, mainly Java's own JKS format (default) or the PKCS#12 format which tends to be used by browsers and tools such as OpenSSL.

Step 1 : Creating Keys and a Self-Signed Certificate

Java comes with a command-line utility called keytool that can be used to handle keystores, in particular to create keys, certificate requests (CSR) and self-signed certificates (there are other utilities, such as OpenSSL and KeyMan from IBM). More precisely, keytool will create a keystore file that can contain one or more key pairs and certificates (we will only create one of each). By default, when you create a pair of keys, keytool will also create a self-signed certificate. The most important thing in this step is that you correctly specify the name of the machine where the certificate will be used as the common name, in the '-dname' option (see below). In the following example, the machine is called 'serverX' (the command-line options are put onto separate lines for readability only):

keytool -genkey
-v
-alias serverX
-dname "CN=serverX,OU=IT,O=JPC,C=GB"
-keypass password
-keystore serverX.jks
-storepass password
-keyalg "RSA"
-sigalg "SHA1withRSA"
-keysize 2048
-validity 3650

The output should be:

Generating 2,048 bit RSA key pair and self-signed certificate (MD5withRSA) with
a validity of 3,650 days
for: CN=serverX, OU=IT, O=JPC, C=GB
[Storing serverX.jks]

To explain each option:

-genkey

generate a pair of keys and a self-signed certificate

-v

display the output message

-alias

a unique name for the keys (does not need to be the name of the machine)

-dname

details of the machine where the keys and certificate will be used

-keypass

the password for the key pair identified by the '-alias' option

-keystore

the name of the operating system file where the keys/certificate will be saved

-storepass

the password for the keystore file

-keyalg

the encryption algorithm to use; “DSA” or “RSA”

-sigalg

the signature algorithm to use; “Sha1withDSA” and “MD5withRSA” are two

-keysize

the size of the key (larger = more secure; e.g. 512, 1024 or 2048)

-validity

the number of days before the certificate expires (3650 = approx. 10 years)

Keystore files can have different formats. The example above, the default format of “JKS” (Java Key Store) was used. The type for PKCS#12 files (.p12) is "PKCS12", which can be specified by adding the following options to the keytool command line:

-storetype “PKCS12”

Step 2: Exporting the Self-Signed Certificate

The file 'serverX.jks' now contains the keys and a self-signed certificate. To be useful, the certificate needs to be exported so that it can be imported into other keystores such as those used by the Java VM or Windows. To export the certificate, use keytool with the following options:

keytool -export
-v
-alias serverX
-file serverX.cer
-keystore serverX.jks
-storepass password

The output should be:

Certificate stored in file <serverX.cer>

To explain each option:

-export

export the certificate

-alias

the name of the public key/certificate to export

-file

the name of a file where the certificate is to be saved

-keystore

the name of the keystore file containing the certificate

-storepass

the password for the keystore file

Note that the name of the alias and the keystore/certificate files are not significant, but they are named 'serverX' for consistency and clarity.

Step 3: Importing the Self-Signed Certificate

You should now have a file called 'serverX.cer' that contains your server's self-signed certificate. The server will present this certificate whenever an HTTPS client sends a request. There are different ways of installing the certificate on the server; in the Restlet example server code below, the certificate is loaded from the keystore when the Restlet server is started.

There are different ways to get a HTTPS client to trust your certificate. If you are using a browser, there may be an option to add it to a list of trusted certificates. In Windows XP, the certificate can be added to the 'Trusted Root Certification Authorities' via Internet Options (in IE7 or Control Panel - Internet Options). On the 'Content' tab, click 'Certificates', then go to 'Trusted Root Certification Authorities' tab, click 'Import...' and follow the steps to import your certificate file ('serverX.cer'). It will give warnings about not being verified, which is ok for testing, but it must be properly signed by proper Certification Authority for production. Firefox 3 also has the ability to add exceptions to trust individual certificates (self-signed or issued by an unknown CA).

If you are using another Java program instead of a browser, then you need to let the Java VM know about the certificate. There are several ways to do this, but here are two:

1. Import the certificate to the Java VM trusted certificates file, which is called 'cacerts' by default and located in the lib/security directory of the Java home directory, for example C:\Program Files\Java\jre6\lib\security\cacerts

The keytool command to do this is:

keytool -import
-alias serverX
-file serverX.cer
-keystore "C:\Program Files\Java\jre6\lib\security\cacerts"
-storepass "changeit"

Note that the default password for the cacerts keystore file is 'changeit'.

2. Add the following Java VM arguments to your Java client command line:

-Djavax.net.ssl.trustStore=C:\\somedir\\serverX.jks
-Djavax.net.ssl.trustStoreType=JKS
-Djavax.net.ssl.trustStorePassword=password

These arguments tell the Java VM where to find your certificate. Please note that this approach should only be used in a test environment, not in production, as the password is shown in plain text.

Step 4: Sample Restlet Server Code

In addition to the standard Restlet jar files, you also need to reference jar files for HTTPS. The 'Simple' HTTPS connector uses these jar files:

lib/com.noelios.restlet.ext.simple_3.1.jar
lib/org.simpleframework_3.1/org.simpleframework.jar lib/com.noelios.restlet.ext.ssl.jar
lib/org.jsslutils_0.5/org.jsslutils.jar

The server code in this example will explicitly load the certificate from the keystore file (serverX.jks):

package com.jpc.samples;

import org.restlet.Component;
import org.restlet.Server;
import org.restlet.data.Parameter;
import org.restlet.data.Protocol;
import org.restlet.util.Series;

public class SampleServer { public static void main(String[] args) throws Exception {
// Create a new Component.
Component component = new Component();

// Add a new HTTPS server listening on port 8183
Server server = component.getServers().add(Protocol.HTTPS, 8183);
Series<Parameter> parameters = server.getContext().getParameters();

// Note refactoring in Restlet version 1.2:
// com.noelios.restlet.ext.ssl.PkixSslContextFactory moved to org.restlet.ext.ssl.PkixSslContextFactory
//and
// com.noelios.restlet.util.DefaultSslContextFactory moved to org.restlet.engine.security.DefaultSslContextFactory");
//
// DefaultSslContextFactory is another sslContextFactory that can be used if desired.

// Using Restlet version 1.1 package:
parameters.add("sslContextFactory", "com.noelios.restlet.ext.ssl.PkixSslContextFactory");
parameters.add("keystorePath", "<path>serverX.jks");
parameters.add("keystorePassword", "password");
parameters.add("keyPassword", "password");
parameters.add("keystoreType", "JKS");

// Attach the sample application.
component.getDefaultHost().attach("", new SampleApplication());

// Start the component.
component.start();
}
}

Step 5: Sample Restlet Client Code

package com.jpc.samples;
import java.io.IOException;
import org.restlet.Client;
import org.restlet.data.Form;
import org.restlet.data.Protocol;
import org.restlet.data.Reference;
import org.restlet.data.Response;
import org.restlet.resource.Representation;

public class SampleClient {

public static void main(String[] args) throws IOException {
// Define our Restlet HTTPS client.
Client client = new Client(Protocol.HTTPS);

// The URI of the resource "list of items".
Reference samplesUri = new Reference("https://serverX:8183/sample";);

// Create 9 new items
for (int i = 1; i < 10; i++)
{
Sample sample = new Sample(Integer.toString(i), "sample " + i, "this is sample " + i + ".");
Reference sampleUri = createSample(sample, client, samplesUri);
if (sampleUri != null) {
// Prints the representation of the newly created resource.
get(client, sampleUri);
}
}

// Prints the list of registered items.
get(client, samplesUri);
}

...other code not shown (similar to original HTTP Restlet example)...

Conclusion

That's it! Your client and server should now be communicating via HTTPS. Note that the information contained in this article is meant only as rudimentary starting point for using HTTPS with Restlet and not as a comprehensive guide to secure web applications. Comments and feedback welcome!

4.4 Persistence layer

4.4.1 Introduction

The Restlet framework is completely agnostic regarding the persistence technology that you want to use. Many alternatives having been used successfully and we are confident that you won't hit any special limitation in this area.

4.4.2 Description

The basic idea is that from a Restlet point of view, your application with be composed of resources, extending the org.restlet.resource.Resource class. Those subclassed will be in charge of handling the incoming requests. One instance of your resource subclass will be created for each request to handle, making sure that you don't have to care about concurrent access at this point of your application.

When you resource is instantiated, it will need to expose its representations (via HEAD, GET methods), to store (PUT method), accept (POST method) or remove (DELETE method) representations. During construction, based on the actual identity of your resource and other parameters or attributes of the request, you will be able to contact your persistence backend in order to support your processing logic or the representations of your resources returned.

4.5 Getting parameter values

4.5.1 Introduction

This is a common need to retrieve data, especially "key=value" pairs from the query, the entity, or the cookies.
Here are some sample lines of code wich illustrate this feature.

4.5.2 Getting values from a web form

The web form is in fact the entity of the POST request sent to the server, thus you have access to it via request.getEntity().
There is a shortcut which allows to have a list of all input fields :

Form form = request.getEntityAsForm();
for (Parameter parameter : form) {
  System.out.print("parameter " + parameter.getName());
  System.out.println("/" + parameter.getValue());
}

4.5.3 Getting values from a query

The query is a part of the identifier (the URI) of the request resource. Thus, you have access to it via request.getResourceRef().getQuery().
There is a shortcut which allows to have a list of all "key=value" pairs :
Form form = request.getResourceRef().getQueryAsForm();
for (Parameter parameter : form) {
  System.out.print("parameter " + parameter.getName());
  System.out.println("/" + parameter.getValue());
}

4.5.4 Getting values from the cookies

Cookies are directly available from the request via the request.getCookies() method. It returns a collection of "Cookie" objects which extends the Parameter class and contains additional attributes:

for (Cookie cookie : request.getCookies()) {
    System.out.println("name = " + cookie.getName());
    System.out.println("value = " + cookie.getValue());
    System.out.println("domain = " + cookie.getDomain());
    System.out.println("path = " + cookie.getPath());
    System.out.println("version = " + cookie.getVersion());
}

4.5.5 Extracting values from query, entity, cookies into the request's attributes

When routing URIs to Resource instances or Restlet, you can decide to transfer data from query, entity or cookies into the request's list of attributes.
This mechanism is declarative and has been implemented at the level of the "routes" (see the code below for more information). This mechanism transfers data from the query (method "extractQuery"), the entity (method "extractEntity") or the Cookies (method "extractCookies") to the request's list of parameters.

For example, when implementing your Application, assuming that the posted web form contains a select input field (called "selectField") and a text field ( called "textField"). If you want to transfer them respectively to attributes named "selectAttribute" and "textAttribute", just proceed as follow.

@Override
public Restlet createRoot() {
     Router router = new Router(getContext());
     Route route = router.attachDefault(MyResource.class);
     route.extractEntity("selectAttribute", "selectField", true);
     route.extractEntity("textAttribute", "textField", false);
     return router;
}

You will get a String value in the "selectAttribute" (the selected option), and a Form object which is a collection of key/value pairs (key="textField" in this case) with the "textAttribute" attribute.
Here is sample code which helps to retrieve some attributes:

// Get the map of request attributes
Map<String, Object> map = request.getAttributes();

// Retrieve the "selectAttribute" value
String stringValue = (String) map.get("selectAttribute");
System.out.println(" value => " + stringValue);

// Retrieve the "textAttribute" collection of parameters
Object object = map.get("textAttribute");
if(object != null){
    if(object instanceof Form){
        Form form = (Form) object;
        for (Parameter parameter : form) {
            System.out.print("parameter " + parameter.getName());
            System.out.println("/ " + parameter.getValue());
        }
    }
}

5 Restlet Engine

The engine is the set of classes that together supports or implements the Restlet API. Currently, there is a strict separation with the API, but this will change in Restlet 1.2 to facilitate the deployment and packaging of applications.

This seperation will however stay conceptually between the classes that are expected to be used by Restlet users while developping their applications and the classes that are expected to be used by the Restlet core developers.

Note that the engine is also extensible and can detect pluggable connectors available on the classpath as well as pluggable authentication helpers.

5.1 Internal connectors

Here is the list of connectors built-in the Restlet engine:

Note that those connectors available in the engine JAR but still need to be declared in your Restlet component, otherwise your applications won't be able to use them!

5.1.1 Local connectors

The "local" Reference instances can be easily created via the LocalReference class.
The list of supported parameters is available in the javadocs:

5.1.2 File system access

FILE is a standard scheme to access to representations stored in the file system (e.g.: "file:///d:/temp/fichier.txt", "file:///tmp/fichier.txt").

5.1.3 CLAP connector

CLAP (ClassLoader Access Protocol) is a custom scheme to access to representations via classloaders (e.g.: clap://thread/org/restlet/Restlet.class). This protocol accepts three kinds of authority :

CLAP client commons parameters

5.1.4 HTTP connector

5.1.5 The RIAP protocol

Background.

The riap protocol came to life as a solution for the issue 374 "Add support for pseudo protocols". Which in turn started of based from discussion on issue 371 "Optimize Internal Calls".

About riap.

The riap://... scheme identifies a so-called pseudo-protocol (terminologogy derived from Apache Cocoon pointing out the difference between 'real' or 'official'/ public protocols and this scheme which only relates to internal processing of the restlet system architecture.

RIAP is short for 'Restlet Internal Access Protocol'.

In short, it is just a mechanism that allows various applications to call upon each other to retrieve resources for further processing.

"Application" here refers to the strict restlet API notion. Same remark should be made on the usage of "Component" further down.

The riap:// scheme brings a URI-notation for these inter-application calls. With that URI-notation those calls fall naturally under appliance of the uniform interface. 

There are two blends of this riap protocol, that use distinct 'authorities' for different use cases.

The riap use case.

Think about some application X that needs a resource Y that is available on a configurable base-uri.
Whatever that baseUri is, the application-implementation should just use the context.getClientDispatcher() to get() that needed resource.

So basically the dependency from application X to "whatever service that will offer me resource Y" can be expressed in this base-URI.  Thinking about dependency injection solutions, the configuration of X is covered by calling some setResourceYBaseUri(...).  That will cover any of these 'service-providers' of this resource Y:

Next to this expression flexibility of dependencies, this riap:// approach ensures some extra

Bottom line: the basic idea behind this riap:// is one of flexibly decomposing your 'component' in smaller reusable/configurable/interchange-able 'applications' while assuring optimal efficiency when calling upon each other.

How to use.
Calling the riap:

To call a resource via the  riap:// scheme one can just use:

Context context;

context.getClientDispatcher().get("riap://component/some-path/Y");

There is no need to register a RIAP client, this is handled by built-in support.

Making resources available to the riap

Applications need just to be attached to the internalRouter property of the Component.

Component component;

component.getInternalRouter().attach("/path", someApplication);

Applications can be attached multiple times (at different paths) to both the internal-router as to several virtual hosts.
A 'pure internal' application should only be attached to the internal router.

Caution

Note that internal/dynamic resources that require protocol specific attributes of the URI where it is invoked (like hostname) might yield errors or unexpected results when called via the riap internal protocol.

Also beware that constructed URI's to secundary resources which are based on the 'own reference' can yield unexpected or at least different results when the resource is suddenly being called via the riap.

Give these cases some special attention during your design, specially when porting stuff from other environments (e.g. servlet app)

Feature Availability

This feature landed in svn-trunk end of November 2007 (rev 2251). It will be part of the 1.1 release.

TODO: check that last statement.

5.2 Pluggable authenticators

This feature allows to plug support for new authentication schemes into the engine in a way similar to Restlet connectors.

Currently, there is one example available with the OAuth extension.

5.3 Logging

5.3.1 Introduction

Restlet relies on JDK's logging API to log records about its activity. For a complete documentation on this standard API, you can check the related JDK documentation. For additional configuration details, you should also read the Javadocs of the LogManager class. For example, to indicate the location of your logging properties file, you should add the following parameter to your JVM:

-Djava.util.logging.config.file="/home/myApp/config/myLogging.properties"

When developing your Restlet code, you should always use the current context to get a logger. This will ensure the proper naming and filtering of your log records. Most classes like Restlet subclasses or Resource subclasses offer a "getLogger()" method. Otherwise, you can rely on the static "Context.getCurrentLogger()" method.

Note also that the are two main types of log record in Restlet:

5.3.2 Logger names

As a single JVM can contain several Restlet components at the same time and each component can also contain several applications, we need a way to filter the log records for each application if needed. For this purpose, we leverage the hierarchical nature of JDK loggers:

It can often be difficult to configure your logging properties file because you don't always know precisely the logger names. For Restlet code, everything is under the root "org.restlet" logger so it is relatively easy.

However, as the Restlet extensions rely on many third-party library, you need to understand how each one handles logging in order to consistently configure you logging. Many of them rely on Apache Commons Logging API as a neutral API that can plug implementations such as Log4J or JDK Logging. Other use the neutral SLF4J, but in most of the cases, it is possible to redirect those alternative logging mechanisms to the JDK logging one.

Here is an attempt to list the logger names used by those libraries. Please help us to complete this table.

Library

Package name

Logger name

Comment

db4o

com.db4o

Grizzly

com.sun.grizzly

Bloat

edu.purdue.cs.bloat

Java Activation

javax.activation

Java Mail

javax.mail

Java Servlet

javax.servlet

JAX-RS

javax.ws.rs

JAXB

javax.xml.bind

StAX

javax.xml.stream

JLine

jline

JXTA

net.jxta

OAuth

net.oauth

AntLR

org.antlr.runtime

Commons Codec

org.apache.commons.codec

Commons Collections

org.apache.commons.collections

Commons DBCP

org.apache.commons.dbcp

Commons FileUpload

org.apache.commons.fileupload

Commons HTTP Client

org.apache.commons.httpclient

org.apache.commons.httpclient.*
httpclient.wire.*

For more details, see the logging documentation page.

Commons IO

org.apache.commons.io

Commons Lang

org.apache.commons.lang

Commons Logging

org.apache.commons.logging

Commons Pool

org.apache.commons.pool

MINA

org.apache.mina

Velocity

org.apache.velocity

Bouncy Castle

org.bouncycastle

FreeMarker

freemarker

JiBX

org.jibx.runtime

JSON

org.json

JUnit

junit

Jetty

org.mortbay.jetty

org.mortbay.*

Jetty chooses its logger from the property
"org.mortbay.log.class", biased towards SLF4J but overrideable

Simple

simple

Spring

org.springframework

org.springframework.*

Commons logging

Tanuki Wrapper

org.tanukisoftware.wrapper

If the logger name you are looking for isn't listed, there is an easy way to detect it. You just have to call the static "com.noelios.restlet.util.TraceHandler.register()" method at the beginning of your program. It will replace the default console handler by a more compact one that will display the logger name for each log record received by the root logger (i.e. all the log records).

5.3.3 Sample configuration

As a starting point for your own logging properties file, here is the one we use on our Restlet base Web server. Feel free to copy and paste as needed.

# ================================
# ==                            ==
# ==   Web Logging Properties   ==
# ==                            ==
# ================================


# ------------------
# General properties
# ------------------


# This defines a whitespace separated list of class names for handler classes to load and register as handlers on 
# the root Logger (the Logger named ""). Each class name must be for a Handler class which has a default constructor. 
# Note that these Handlers may be created lazily, when they are first used.
handlers=java.util.logging.FileHandler

In this first section, we declare one default handler that will receive the log records. It is a file handler that will be configured below.

# ------------------
# Loggers properties
# ------------------

.level=WARNING
org.mortbay.level=WARNING
org.restlet.level=WARNING
com.noelios.level=WARNING

com.noelios.web.WebComponent.www.level=INFO
com.noelios.web.WebComponent.www.handlers=com.noelios.restlet.util.AccessLogFileHandler
com.noelios.web.WebComponent.www.useParentHandlers=false

In this second section, we indicate that by default we are only interested in log records with a WARNING level. We also configure the Mortbay's Jetty, Restlet API and NRE log levels to WARNING. This isn't necessary here but it can be useful when you need to lower the level of only one of them at some point, for debugging purpose for example.

We also configured a logger for the WWW access log of our Restlet component. For information, our Component subclass has this code in its constructor:

getLogService().setLoggerName("com.noelios.web.WebComponent.www");

Also note that we use a specific handler for this logger, the AccessLogFileHandler which is provided in the NRE. It can be easily configurer to produce Apache-style HTTP log files.

# -------------------------
# ConsoleHandler properties
# -------------------------

# Specifies the default level for the Handler  (defaults to Level.INFO).
# java.util.logging.ConsoleHandler.level=WARNING

# Specifies the name of a Filter class to use (defaults to no Filter).
# java.util.logging.ConsoleHandler.filter=

# Specifies the name of a Formatter class to use (defaults to java.util.logging.SimpleFormatter).
# java.util.logging.ConsoleHandler.formatter=

# The name of the character set encoding to use (defaults to the default platform encoding).
# java.util.logging.ConsoleHandler.encoding=

In the section above we have disabled the default ConsoleHandler configuration as we don't use it on our server-side application.

# ------------------------------
# General FileHandler properties
# ------------------------------

# Specifies the default level for the Handler  (defaults to Level.ALL).
# java.util.logging.FileHandler.level=ALL

# Specifies the name of a Filter class to use (defaults to no Filter).
# java.util.logging.FileHandler.filter= 

# Specifies the name of a Formatter class to use (defaults to java.util.logging.XMLFormatter)
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter

# The name of the character set encoding to use (defaults to the default platform encoding).
# java.util.logging.FileHandler.encoding=

# Specifies an approximate maximum amount to write (in bytes) to any one file. 
# If this is zero, then there is no limit. (Defaults to no limit).
java.util.logging.FileHandler.limit=10000000

# Specifies how many output files to cycle through (defaults to 1).
java.util.logging.FileHandler.count=100

# Specifies a pattern for generating the output file name. (Defaults to "%h/java%u.log").
# A pattern consists of a string that includes the following special components that will be replaced at runtime:
#    "/" the local pathname separator
#    "%t" the system temporary directory
#    "%h" the value of the "user.home" system property
#    "%g" the generation number to distinguish rotated logs
#    "%u" a unique number to resolve conflicts
#    "%%" translates to a single percent sign "%" 
java.util.logging.FileHandler.pattern=/home/prod/data/log/WebComponent-app-%u-%g.log

# Specifies whether the FileHandler should append onto any existing files (defaults to false).
# java.util.logging.FileHandler.append=

Here we specify the file size limit, the number of rotation files (100) and the file name template.

# -------------------------
# LogFileHandler properties
# -------------------------

# Specifies the default level for the Handler  (defaults to Level.ALL).
# com.noelios.restlet.util.AccessLogFileHandler.level=ALL

# Specifies the name of a Filter class to use (defaults to no Filter).
# com.noelios.restlet.util.AccessLogFileHandler.filter= 

# Specifies the name of a Formatter class to use (defaults to java.util.logging.XMLFormatter)
com.noelios.restlet.util.AccessLogFileHandler.formatter=com.noelios.restlet.util.AccessLogFormatter

# The name of the character set encoding to use (defaults to the default platform encoding).
# com.noelios.restlet.util.AccessLogFileHandler.encoding=

# Specifies an approximate maximum amount to write (in bytes) to any one file. 
# If this is zero, then there is no limit. (Defaults to no limit).
com.noelios.restlet.util.AccessLogFileHandler.limit=10000000

# Specifies how many output files to cycle through (defaults to 1).
com.noelios.restlet.util.AccessLogFileHandler.count=50

# Specifies a pattern for generating the output file name. (Defaults to "%h/java%u.log").
# A pattern consists of a string that includes the following special components that will be replaced at runtime:
#    "/" the local pathname separator
#    "%t" the system temporary directory
#    "%h" the value of the "user.home" system property
#    "%g" the generation number to distinguish rotated logs
#    "%u" a unique number to resolve conflicts
#    "%%" translates to a single percent sign "%" 
com.noelios.restlet.util.AccessLogFileHandler.pattern=/home/prod/data/log/WebComponent-www-%u-%g.log

# Specifies whether the FileHandler should append onto any existing files (defaults to false).
# com.noelios.restlet.util.AccessLogFileHandler.append=

This is similar to the previous section, but specific to our NRE AccessLogFileHandler log handler. This let's us use a specific log formatter called AccessLogFormatter, also provided by the NRE.

5.3.4 Replacing default JDK logging with log4j

Some users that prefer to use log4j instead of the java.util.logging API, especially because it has more features ready to be leveraged and what seems to bit a more flexible configuration language. Sometimes, Restlet has just to integrate into an existing loggin strategy.

In these cases, we recommand the usage of the JUL to log4j bridge. One possibility is to use the bridge provided by the SLF4J project. Once it is installed, you will just need to add these lines of code and configure log4j properly:

 import org.slf4j.bridge.SLF4JBridgeHandler;
 SLF4JBridgeHandler.install();

5.3.5 Additional resources

6 Restlet Extensions

6.1 Introduction

The Restlet framework is composed of three parts:

This chapter presents all the extensions available in the Restlet framework and describes how to add those extensions to your application.

6.2 Description

The NRE lets you build complete Web applications by itself and is cpable of leveraging other open source projects to facilitate tasks such as generation of dynamic representations, management of uploaded files, sending of mails, etc. There are two types of extensions.

The first one is for extensions built only on top of the Restlet API and typically provide new type of representations (JAXB, FreeMarker, JiBx, etc.) or support of important standards (Atom, WADL).

The second one covers extensions to the Restlet engine such as client connectors, server connectors and authentication helpers.

6.3 Distribution

All extensions and their dependencies are shipped with the Restlet distribution by the way of JAR files. Adding an extension to your application is as simple as adding the archives of the chosen extension and its dependencies to the classpath. 

You can also have a look to the FAQ #4 and FAQ #5 which completes this subject.

6.4 Atom extension

6.4.1 Introduction

This extension provides support for the Atom standard. Atom is an evolution of the RSS standard that was introduced to remove know limitations and enable new features and usages, especially in the light of the REST principles.

Its main purpose it to define a format to represent Web feeds such as news feed. This is called the Atom Syndication Format.

The second purpose is to support the publication and modification of those Web feeds, remotely on the Web and in an interoperable manner. This is called the Atom Publishing Protocol (APP).

6.4.2 Description

The Restlet extension for Atom provides a complete Atom API for both Web feeds and publication documents. This API is capable of both parsing and formatting Atom and APP XML documents compliants with the 1.0 specifications.

The two main classes you should use are Feed (an Atom XML feed) and Service (an AtomPub XML service descriptor) which are both subclasses of SaxRepresentation. As such instances of both classes can be directly returned as representation of your Restlet resources. They also support parsing via the constructors accepting a Representation parameter.

For an usage example, check the source code of the org.restlet.example.book.restlet.ch8.resources.FeedResource class.

6.5 FileUpload extension

6.5.1 Introduction

This extension leverages the Apache FileUpload library to provide a robust, high-performance, Web-based file upload in Restlet server-side applications.

6.5.2 Description

This extension lets you receive files sent by POST or PUT requests and to parse the posted entity (which is actually an instance of the "Representation" class) and to extract a list of FileItems from it, each item corresponding to one file uploaded in the posted request, typically from a Web form.

Please, refer to the FileUpload extension Javadocs and the FAQ #18 for more details.

Here is the list of dependencies for this extension:

6.5.3 Usage example

This sample code illustrates how to upload files with the FileUpload extension. It is composed of 3 classes:

Thus, each request to the following uri "http://localhost/testFileUpload" will be handled by a new instance of "MyResource".

The single representation of this resource is a web form with a file select control and a submit button. It allows to set up a request with an uploaded file that will be posted to the resource.

Every Resource instance handles the POST request in method "acceptRepresentation" which accepts the posted entity as single parameter. The aim of the MyResource instance is to parse the request, get the file, save it on disk and send back its content as plain text to the client.

Here is the content of the MyResource#acceptRepresentation method:

   /**
     * Accepts and processes a representation posted to the resource. As
     * response, the content of the uploaded file is sent back the client.
     */
    @Override
    public void acceptRepresentation(Representation entity) {
        if (entity != null) {
            if (MediaType.MULTIPART_FORM_DATA.equals(entity.getMediaType(),
                    true)) {

                // The Apache FileUpload project parses HTTP requests which
                // conform to RFC 1867, "Form-based File Upload in HTML". That
                // is, if an HTTP request is submitted using the POST method,
                // and with a content type of "multipart/form-data", then
                // FileUpload can parse that request, and get all uploaded files
                // as FileItem.

                // 1/ Create a factory for disk-based file items
                DiskFileItemFactory factory = new DiskFileItemFactory();
                factory.setSizeThreshold(1000240);

                // 2/ Create a new file upload handler based on the Restlet
                // FileUpload extension that will parse Restlet requests and
                // generates FileItems.
                RestletFileUpload upload = new RestletFileUpload(factory);
                List items;
                try {
                    // 3/ Request is parsed by the handler which generates a
                    // list of FileItems
                    items = upload.parseRequest(getRequest());

                    // Process only the uploaded item called "fileToUpload" and
                    // save it on disk
                    boolean found = false;
                    for (final Iterator it = items.iterator(); it
                            .hasNext()
                            && !found;) {
                        FileItem fi = (FileItem) it.next();
                        if (fi.getFieldName().equals("fileToUpload")) {
                            found = true;
                            File file = new File("c:\\temp\\file.txt");
                            fi.write(file);
                        }
                    }

                    // Once handled, the content of the uploaded file is sent
                    // back to the client.
                    Representation rep = null;
                    if (found) {
                        // Create a new representation based on disk file.
                        // The content is arbitrarily sent as plain text.
                        rep = new FileRepresentation(new File(
                                "c:\\temp\\file.txt"), MediaType.TEXT_PLAIN, 0);
                    } else {
                        // Some problem occurs, sent back a simple line of text.
                        rep = new StringRepresentation("no file uploaded",
                                MediaType.TEXT_PLAIN);
                    }
                    // Set the representation of the resource once the POST
                    // request has been handled.
                    getResponse().setEntity(rep);
                    // Set the status of the response.
                    getResponse().setStatus(Status.SUCCESS_OK);
                } catch (Exception e) {
                    // The message of all thrown exception is sent back to
                    // client as simple plain text
                    getResponse().setEntity(
                            new StringRepresentation(e.getMessage(),
                                    MediaType.TEXT_PLAIN));
                    getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
                    e.printStackTrace();
                }
            }
        } else {
            // POST request with no entity.
            getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
        }
    }

Before running this example, please add the following jars to the classpath:

6.6 FreeMarker extension

6.6.1 Introduction

This extension provides an integration with FreeMarker 2.3. FreeMarker is a template engine, a generic tool to generate text output (anything from HTML to autogenerated source code) based on templates. For details on FreeMarker, see the home page.

6.6.2 Description

When you need to generate a dynamic document based on a data model and a FreeMarker template (skeleton document similar to a JSP page or an XSLT stylesheet), you just need to create an instance of the TemplateRepresentation class with the matching parameters and to set it as the response entity.

Please, refer to the FreeMarker extension Javadocs and the FAQ #10 for more details.

Here is the list of dependencies for this extension:

6.7 Grizzly extension

6.7.1 Introduction

This connector is based on the Grizzly NIO framework developed at Sun. The Grizzly framework has been designed to help developers to take advantage of the Java® NIO API and build scalable and robust servers.

6.7.2 Description

This connector supports the following protocol: HTTP, HTTPS.

The list of supported specific parameters is available in the javadocs:

Here is the list of dependencies of this connector:

6.8 HTTP Client extension

6.8.1 Introduction

This connector is based on Apache Commons HTTP client. It provides an HTTP and HTTPS client connector with advanced multi-threading and connection reuse support.

6.8.2 Description

As pointed out by the Apache HTTPClient tutorial it is crucial to read entirely each response. It allows to release the underlying connection. Not doing so may cause future requests to block. See Apache HTTPClient 3.x tutorial.

This connector supports the following protocols: HTTP, HTTPS.

The list of supported specific parameters is available in the javadocs:

Here is the list of dependencies of this connector:

6.9 JavaMail extension

6.9.1 Introduction

This connector is based on JavaMail that provides a platform-independent and protocol-independent framework to build mail and messaging applications.

6.9.2 Description

This connector supports the following protocols: SMTP, SMTPS.

The list of supported specific parameters is available in the javadocs:

The mail and its properties (sender, recipient, subject, content, etc) have to be specified as an XML representation. Please refer to the JavaMail client javadocs for more details.

Here is the list of dependencies of this connector:

6.10 JAXB extension

6.10.1 Introduction

This extension provided an integration with JAXB 2.1. <a href="https://jaxb.dev.java.net/">JAXB</a> is a convenient way to process XML content using Java objects by binding XML schemas to Java
classes.

6.10.2 Description

The extension is composed of just one class, the JaxbRepresentation that extends the XmlRepresentation and is able to both serialize and deserialize a Java objects graph to/from an XML document.

6.11 JAX-RS extension

6.11.1 Introduction

This Restlet Extension implements the Java Specification JAX-RS: Java API for RESTful Web Services. Note that this specification is not final yet, and its implementation also, of course.

6.11.2 Description

To run this example, you need the Restlet libraries. Download a 1.1 milestone from www.restlet.org/downloads/. (For a general Restlet example take a look at http://www.restlet.org/documentation/1.1/firstSteps.)

Now create a new Java Project, and add the following jars (resp. projects) to the classpath (right click on project, Properties, Java Build Path, Libraries (resp.Projects), Add):

Depending of your needs you have to add the following:

Click "Ok" twice. Now you are ready to start. - First we will create an example root resource class and then show how to get it running by the Restlet JAX-RS extension.

6.11.3 Create JAX-RS example

Create a new package, e.g. test.restlet.jaxrs

6.11.3.1 Create a root resource class

First create an easy root resource class: Create a new java class named EasyRootResource in the previously created package and insert the following source  code:

package test.restlet.jaxrs;

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

@Path("easy")
public class EasyRootResource {

    @GET
    @Produces("text/html")
    public String getHtml() {
        return "<html><head></head><body>\n"
                + "This is an easy resource (as html text).\n"
                + "</body></html>";
    }

    @GET
    @Produces("text/plain")
    public String getPlain() {
        return "This is an easy resource (as plain text)";
    }
}

6.11.3.2 Create ApplicationConfig

To provide a collection of root resource classes (and others) for a JAX-RS runtime you integrate these classes to an ApplicationConfig. Create a new class ExampleAppConfig in the same package with the following content:

package test.restlet.jaxrs;

import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.ApplicationConfig;

public class ExampleApplication extends Application {

    public Set<Class<?>> getClasses() {
        Set<Class<?>> rrcs = new HashSet<Class<?>>();
        rrcs.add(EasyRootResource.class);
        return rrcs;
    }
}

The root resource class and the ApplicationConfig is specified by the JAX-RS specification. It can be used in any JAX-RS runtime environment.

Now create a runtime environment instance and pass the ApplicationConfig instance to it. This is runtime environment specfic. Below you see this for the Restlet JAX-RS environment:

6.11.4 Set up a JAX-RS server

A JAX-RS server using the Restlet JAX-RS extension is set up like any Restlet server. Create a third class in the same package, named ExampleServer:

package test.restlet.jaxrs;

import org.restlet.Component;
import org.restlet.Server;
import org.restlet.data.Protocol;
import org.restlet.ext.jaxrs.JaxRsApplication;

public class ExampleServer {

    public static void main(String[] args) throws Exception {
        // create Component (as ever for Restlet)
        Component comp = new Component();
        Server server = comp.getServers().add(Protocol.HTTP, 8182);

        // create JAX-RS runtime environment
        JaxRsApplication application = new JaxRsApplication(comp.getContext());

        // attach ApplicationConfig
        application.add(new ExampleAppConfig());

        // Attach the application to the component and start it
        comp.getDefaultHost().attach(application);
        comp.start();

        System.out.println("Server started on port " + server.getPort());
        System.out.println("Press key to stop server");
        System.in.read();
        System.out.println("Stopping server");
        comp.stop();
        System.out.println("Server stopped");
    }
}

Start this class, open a browser and request http://localhost:8182/easy. Now you see the HTML representation. If you request the same URI with accepted media type "text/plain", you get a plain text representation.

This example (a little bit extended) is available in the project org.restlet.example. See package org.restlet.test.jaxrs. There is another root resource class with a reacheable resource class and also an example with user authentication.

A lot of more resource classes are available in the test project (org.restlet.test, packages starting with org.restlet.test.jaxrs). They are implemented for testing, and most of them do not do intelligent things ... :-) But they show the actual status of development of this JAX-RS runtime environment.

This runtime environment is still under development, and I'm very busy continuing it ...

6.11.4.1 Run in a Servlet Container

If you want to run the JAX-RS Application in a Servlet Container, create a subclass of the JaxRsApplication. In the constructor you could attach the ApplicationConfigs and sets the Guard and the RoleChecker (if needed).

public class MyJaxRsApplication extends JaxRsApplication {

    public MyJaxRsApplication(Context context) {
        super(context);
        this.add(new MyAppConfig());
        this.setGuard(...); // if needed
        this.setRoleChecker(...); // if needed
    }
}

For details to run this Application in a Servet Container take a look at Restlet FAQ.

You could use this subclass also in the example above:

        // create JAX-RS runtime environment
        Application application = new MyJaxRsApplication(comp.getContext());
  
        // if you use this kind, you don't need to attach the ApplicationConfig again.

Comments are welcome to the Restlet mailing list or directly to Stephan.Koops<AT>web.de !

This extension is the result of a (german) master thesis.

6.12 JDBC extension

6.12.1 Introduction

This connector is a client to a JDBC database. It is based on the JDBC Api developed by Sun Microsystems and shipped with the JDK. Database connections are optionally pooled using Apache Commons DBCP. In this case, a different connection pool is created for each unique combination of JDBC URI and connection properties.

6.12.2 Description

This connector supports the following protocol: JDBC.

The SQL request and other kinds of parameters (such as pooling) are passed to the client connector via an XML representation. Please refer to the JDBC client javadocs for more details.
The Response provides the result of the SQL request as a RowSetRepresentation which is a kind of XML representation of the ResultSet instance wrapped either in a JdbcResult or in a WebRowSet instance. See the RowSetRepresentation for more details.

Here is the list of dependencies of this connector:

6.13 Jetty extension

6.13.1 Introduction

This connector is based on the Jetty open-source web server. Jetty is popular and has a nice separation between its HTTP protocol implementation and its support for the Servlet API which led it to be the first HTTP server connector developed for the Restlet.

6.13.2 Description

This connector supports the following protocols: HTTP, HTTPS, AJP.

The list of supported specific parameters is available in the javadocs:

Here is the list of dependencies of this connector:

6.13.3 Usage example

6.13.3.1 HTTPS

For general information on Jetty HTTPS/SSL configuration, please read this document. For configuration of the connector in a Restlet component, you will need to set some of the HTTPS parameters listed above, for example:

Server server = myComponent.getServers().add(Protocol.HTTPS, 8183);
server.getContext().getParameters().add("keystorePath", "<your-path>");
server.getContext().getParameters().add("keystorePassword", "<your-password>");
server.getContext().getParameters().add("keyPassword", "<your-password>");

6.13.4 Embedding Jetty & AJP

6.13.4.1 Introduction

Here are a few links that will get you started:

6.13.4.2 Description

6.13.4.2.1 Embedding Jetty
6.13.4.2.1.1 JettyAJPApplication.Class
package com.bjinfotech.restlet.practice.demo.microblog;

import org.restlet.Application;
import org.restlet.Component;
import org.restlet.Directory;
import org.restlet.Restlet;
import org.restlet.Router;
import org.restlet.Server;
import org.restlet.data.Protocol;
import com.noelios.restlet.ext.jetty.AjpServerHelper;
import com.noelios.restlet.ext.jetty.HttpServerHelper;
import com.noelios.restlet.ext.jetty.JettyServerHelper;

public class JettyAJPApplication extends Application {
    public static void main(String[] argv) throws Exception{
        Component component=new Component();

        Application application=new Application(component.getContext()){
            @Override
            public Restlet createRoot(){
                final String DIR_ROOT_URI="file:///E:/eclipse3.1RC3/workspace/RestletPractice/static_files/";

                Router router=new Router(getContext());
                Directory dir=new Directory(getContext(),DIR_ROOT_URI);
                dir.setListingAllowed(true);
                dir.setDeeplyAccessible(true);
                dir.setNegotiateContent(true);
                router.attach("/www/",dir);
                return router;
            }
        };

        ...
        //create embedding jetty server
        Server embedingJettyServer=new Server(
                component.getContext(),
                Protocol.HTTP,
                8182,
                component
            );
        //construct and start JettyServerHelper
        JettyServerHelper jettyServerHelper=new HttpServerHelper(embedingJettyServer);
        jettyServerHelper.start();

        //create embedding AJP Server
        Server embedingJettyAJPServer=new Server(
                component.getContext(),
                Protocol.HTTP,
                8183,
                component
            );

        //construct and start AjpServerHelper
        AjpServerHelper ajpServerHelper=new AjpServerHelper(embedingJettyAJPServer);
        ajpServerHelper.start();

    }
}
6.13.4.2.1.2 Running JettyAJPApplication

2008-02-13 15:33:54.890::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
2008-02-13 15:33:54.953::INFO:  jetty-6.1.x
2008-02-13 15:33:55.140::INFO:  Started SelectChannelConnector @ 0.0.0.0:8182
2008-02-13 15:33:55.140::INFO:  jetty-6.1.x
2008-02-13 15:33:55.140::INFO:  AJP13 is not a secure protocol. Please protect port 8183
2008-02-13 15:33:55.140::INFO:  Started Ajp13SocketConnector @ 0.0.0.0:8183

6.13.4.2.2 Configuring Apache HTTPD server with mod_jk

After adding the mod_jk configuration you may add a VirtualHost Entry in the same file (httpd.conf) as long as its located below your mod_jk configuration entry:

    <VirtualHost host:*>

        ServerName yourserver

         ServerAdmin user@yourserver

         ## you may add further entries concerning log-files, log-level, URL-rewriting, ...

         ## pass requests through to jetty worker

    JkMount /* jetty

    </VirtualHost>

worker.list=jetty

worker.jetty.port=8009

worker.jetty.host=<server name or ip where your jetty will be running>

worker.jetty.type=ajp13

6.13.4.2.3 mod_jk Compatibilities

Apache

mod_jk

Win32

Linux(ubuntu)

Apache 1.3

No HTTPD Binary Available

mod_jk-1.2.14

Not yet tested

mod_jk-1.2.15

Not yet tested

mod_jk-1.2.18

Not yet tested

mod_jk-1.2.19

Not yet tested

Apache 2.0 (2.0.59)

mod_jk-1.2.14

mod_jk-1.2.15

mod_jk-1.2.18

mod_jk-1.2.19

Apache 2.2

mod_jk-1.2.14

No Binary Available

mod_jk-1.2.15

No Binary Available

mod_jk-1.2.18

mod_jk-1.2.19

6.13.4.2.4 Running Apache Httpd and test your application

[To be detailled]

6.13.4.2.5 More Resource

Jetty doc:Configuring+AJP13+Using+mod_jk
Apache Httpd Document
HttpServerHelper Class API
Server Class API
AjpServerHelper Class API

6.14 JiBX extension

6.14.1 Introduction

This extension provides an integration with JiBX 1.1. JiBX  is a very flexible framework for binding XML data to Java objects.

6.14.2 Description

The extension is composed of just one class, the JibxRepresentation that extends the XmlRepresentation and is able to both serialize and deserialize a Java objects graph to/from an XML document.

6.15 JSON extension

6.15.1 Introduction

JSON (JavaScript Object Notation) is a compact format for representing structured data. It became a popular alternative to XML in AJAX applications due to its native support by Web browser. JSON is indeed based on the JavaScript syntax. See JSON project for more details.

6.15.2 Description

This extension adds support for JSON representations. It enables you to create JsonRepresentation instances from the two kinds of structure defined by JSON: objects and arrays, and to make the reverse conversion. JsonRepresentations can also be generated from String and any kind of Representation.

Please, refer to the JSON extension Javadocs and the FAQ #10 for more details and have a look to the Restlet wiki for some sample code.

Here is the list of dependencies for this extension:

6.16 Net extension

6.16.1 Introduction

This connector is fully based on the JDK and more precisely on java.net.HttpURLConnection class.

6.16.2 Description

This connector supports the following protocols: HTTP, HTTPS.

The list of supported specific parameters is available in the javadocs:

6.17 OAuth extension

6.17.1 Introduction

This extension provides a support for the OAuth authentication protocol.

6.17.2 Description

Currently the extension is considered experimental and is under-documented. If anyone interested could help document this feature that would be very appreciated.

6.17.3 References

Some links to start with:

"OAuth Core 1.0"
http://oauth.net/core/1.0/

"Getting Started - Part I"
http://oauth.net/documentation/getting-started

"Explaining OAuth"
http://www.hueniverse.com/hueniverse/2007/09/explaining-oaut.html

Beginner’s Guide to OAuth

6.18 Servlet extension

6.18.1 Introduction

This extension is an adapter between the Servlet API and the Restlet API. It allows you to nearly transparently deploy a Restlet application in your preferred Servlet container such as Apache Tomcat.

6.18.2 Description

It enables you to run a Restlet based application inside any Servlet container such as Tomcat.

Please, refer to the ServerServlet extension Javadocs and the FAQ #2 for more details.

Here is the list of dependencies for this extension:

6.19 Simple extension

6.19.1 Introduction

This connector is based on Simple framework 3.1 which is an open source embeddable Java based HTTP engine capable of handling high loads.

6.19.2 Description

This connector supports the following protocols: HTTP, HTTPS.

The list of supported specific parameters is available in the javadocs:

Here is the list of dependencies of this connector:

6.20 Spring extension

6.20.1 Table of contents

  1. Introduction
  2. Description
  3. Integration modes
  4. Configuring Restlet beans
  5. A complete example
  6. Configuration of Restlet Resources in Spring

6.20.2 Introduction

This extension provides various modes of integration between the Restlet framework and the popular Spring framework. Historically, this extension emerged from the needs of Spring users, stuck between the Spring's mechanism of Dependency Injection mostly based on JavaBean setters (Setter Injection) and constructor arguments (Constructor Injection), and the conceptual choices of the Restlet framework that didn't systematize the use of simple POJOs. 

6.20.3 Description

This extension aims at providing a better and more natural integration. It comes in two part, one extension for the Restlet API (org.restlet.ext.spring) and another for the Restlet engine (com.noelios.restlet.ext.spring). Please, refer to the Spring extension Javadocs and the FAQ #23 for more details and have a look the Restlet wiki for several sample codes.

Here is the list of dependencies for this extension:

6.20.4 Spring extension - Integration modes

6.20.4.1 Introduction

During the development of the 1.0 version of the API, several users attempted to integrate Restlet with Spring. They were especially trying to use the XML-based bean wiring feature of Spring. This resulted in several examples available on the community Wiki.

In order to facilitate this integration, two dedicated Spring extension were added to the Restlet. It allows us to provide several integration modes.

6.20.4.2 Restlet as main container

In the first mode, the goal is to leverage the concept of Restlet Application and all the associated services, as well as the transparent deployment to either a Servlet container (using the adapter ServerServlet extension class) or using a standalone HTTP server connector. For this, you can leverage the SpringContext class which is a Spring's GenericApplicationContext subclass. You can associate a list of XML or property configuration URIs (file:/// or war:/// URIs) in order to have Spring auto-instantiate and wire your Restlet beans.

6.20.4.3 Spring as main container

In the second mode, the goal is to leverage the concept of Spring Web Application as an alternative to the Restlet Application. This is sometimes required when the Restlet code is part of a larger Spring-based Web application, with dependencies on the Servlet API for example.

Initially, it was hard to achieve this integration because the Servlet extension, and especially the ServerServlet adapter class was assuming the usage of a Restlet Application. Later we added a lighter adapter based on the ServletConverter class that  lets you directly instantiate Restlet Routers, Finders and Resources from your existing Servlet-based Spring code. You can check the Javadocs for details.

Finally, there is also a SpringFinder class available in the Spring extension. It hasn't any specific dependency to Spring, but the addition of a parameter-less createResource() method allows the usage of the Spring's "lookup-method" mechanism.

In Restlet 1.1, the Spring extensions received several contributions, increasing the number of ways to integrate Restlet with Spring. There is now a RestletFrameworkServlet, a SpringServerServlet, SpringBeanFinder and SpringBeanRouter. Please check the Javadocs of the org.restlet.ext.spring and com.noelios.restlet.ext.spring modules for more details.

6.20.5 Spring extension - Configuring Restlet beans

6.20.5.1 Passing the parent context

One frequent issue that developers encounter when configuring their Restlet beans with Spring XML is that it is not easy to find a way to pass the Context instance to the Restlet subclasses such as Application, Directory or Router. What we actually need to do is to extract the context property from the parent Restlet (typically a Component or an Application) and pass it by reference to the constructor method.

Spring provides two mechanism to achieve this: either using the PropertyPathFactoryBean class to create a context bean such as:

<!-- Restlet Component bean -->
<bean id="component" class="org.restlet.ext.spring.SpringComponent">
	...
</bean>

<!-- Component's Context bean -->
<bean id="component.context" class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>

<!-- Application bean -->
<bean id="application" class="org.restlet.Application">
	<constructor-arg ref="component.context" />
	...
</bean>

The second mechanism is based on the Spring utilities schema and is actually more compact:

<!-- Restlet Component bean -->
<bean id="component" class="org.restlet.ext.spring.SpringComponent">
	...
</bean>

<!-- Application bean -->
<bean id="application" class="org.restlet.Application">
	<constructor-arg>
		<util:property-path path="component.context" />
	</constructor-arg>
	...
</bean>

You also have to make sure that the util namespace is properly declared in your XML configuration header. Here is a snippet for Spring 2.5:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">

<!-- Add you <bean/> definitions here -->

</beans>

This utilities mechanism is quite powerful and flexible, for more information check this page.

6.20.6 Spring extension - A complete example

6.20.6.1 Introduction

This example is a Spring-enabled but otherwise functionally equivalent version of the bookmarks example from chapter 7 of RESTful Web Services by Richardson and Ruby. The complete code for this version is available through CVS from :pserver:anonymous@cvs.cs.luc.edu:/root/laufer/433, module BookmarksRestletSpring. Project dependencies are managed using Apache Maven, and the example illustrates standalone and servlet-container deployment.

In a nutshell, Spring handles the configuration of the top-level Restlet Component and Router beans. The Restlet Resources had to be modified to support the init method and the injection of the dependency on the db4o ObjectContainer, which is also configured in Spring. As expected, the domain objects User and Bookmark remained unchanged.

6.20.6.2 Description

First, we show the configuration of the Restlet Component and top-level Router beans. The top-level Router is necessary only if an non-root context path is required for standalone deployment.

<bean id="top" class="org.restlet.ext.spring.SpringComponent">
	<property name="server">
		<bean class="org.restlet.ext.spring.SpringServer">
			<constructor-arg value="http" />
			<constructor-arg value="3000" />
		</bean>
	</property>
	<property name="defaultTarget" ref="default" />
</bean>

<bean id="default" class="org.restlet.ext.spring.SpringRouter">
	<property name="attachments">
		<map>
			<entry key="/v1" value-ref="root" />
		</map>
	</property>
</bean>

As a result, the main method has become very simple. It loads a Spring context based on two configuration metadata files, one for the preceding top-level beans, and one for the application-specific beans shown below. It then starts up the top-level Restlet Component.

    public static void main(String... args) throws Exception {
	// load the Spring application context
	ApplicationContext springContext = new ClassPathXmlApplicationContext(
		new String[] { "applicationContext-router.xml", "applicationContext-server.xml" });

	// obtain the Restlet component from the Spring context and start it
	((Component) springContext.getBean("top")).start();
    }

Next, we look at the configuration of the application-specific Router. We use a SpringRouter for this purpose, which is configured using a map of URI patterns to resources. The SpringFinder beans provide the extra level of indirection required to create Resource instances lazily on a per-request basis.

In this example, the last URI pattern has to be customized to accept complete URIs (possibly including slashes) as the last component of the pattern. We use Spring's nested properties to drill into the configuration of the URI pattern along with Spring's mechanism for accessing a static field in a class.

<bean id="root" class="org.restlet.ext.spring.SpringRouter">
	<property name="attachments">
		<map>
			<entry key="/users/{username}">
				<bean class="org.restlet.ext.spring.SpringFinder">
					<lookup-method name="createResource"
						bean="userResource" />
				</bean>
			</entry>
			<entry key="/users/{username}/bookmarks">
				<bean class="org.restlet.ext.spring.SpringFinder">
					<lookup-method name="createResource"
						bean="bookmarksResource" />
				</bean>
			</entry>
			<entry key="/users/{username}/bookmarks/{URI}">
				<bean class="org.restlet.ext.spring.SpringFinder">
					<lookup-method name="createResource"
						bean="bookmarkResource" />
				</bean>
			</entry>
		</map>
	</property>
	<property name="routes[2].template.variables[URI]">
		<bean class="org.restlet.util.Variable">
			<constructor-arg ref="org.restlet.util.Variable.TYPE_URI_ALL" />
		</bean>
	</property>
</bean>

<bean id="org.restlet.util.Variable.TYPE_URI_ALL"
	class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />

Unlike the preceding singleton beans, we define the Resources as prototype beans so that they get instantiated separately for each request. All of the Resource beans depend on the db4o ObjectContainer and are configured analogously, so we show only UserResource here.

<bean id="userResource"
	class="org.restlet.example.book.rest.ch7.spring.UserResource"
	scope="prototype">
	<property name="container" ref="db4oContainer" />
</bean>

Using the db4o Spring Module, configuring the ObjectContainer is straightforward.

<bean id="db4oContainer"
	class="org.springmodules.db4o.ObjectContainerFactoryBean">
	<property name="configuration" ref="db4oConfiguration" />
	<property name="databaseFile" value="file://${user.home}/restbook.dbo" />
</bean>

<bean id="db4oConfiguration"
	class="org.springmodules.db4o.ConfigurationFactoryBean">
	<property name="updateDepth" value="2" />
	<property name="configurationCreationMode" value="NEW" />
</bean>

As mentioned above, we added the following elements to each application-specific Resource:

The following code fragment summarizes these changes.

public class UserResource extends Resource {

    private ObjectContainer container;
	
    // other instance variables

    public UserResource() { }
    
    @Override
    public void init(Context context, Request request, Response response) {
    	super.init(context, request, response);
        // code originally in non-default constructor
    }

    public UserResource(Context context, Request request, Response response) {
        super(context, request, response);
        init(context, request, response);
    }

    public ObjectContainer getContainer() {
        return container;
    }
    
    public void setContainer(ObjectContainer container) {
    	this.container = container;
    }

    // other methods
}

6.20.7 Spring extension - Configuration of Restlet Resources

6.20.7.1 Configuration of basic properties

Restlet Resources support only limited configuration beyond injecting custom dependencies such as the ObjectContainer in the example above. To make specific Resource classes more reusable, it would be helpful if their basic properties could be configured through Spring:

Currently, the init method resets these properties to their default values but, in the Spring component life cycle, is invoked after Spring sets the properties. An obvious workaround is to refine the init method like so:

    @Override
    public void init(Context context, Request request, Response response) { 
        final ResourcePropertyHolder backup = new ResourcePropertyHolder();  
        BeanUtils.copyProperties(this, backup);
        super.init(context, request, response);
        BeanUtils.copyProperties(backup, this);
    }

6.20.7.2 Configuration of representation templates

In addition, it would be quite useful if one could map media types to representation templates in Spring. In the following example, we explore this idea further by mapping different media types to different Freemarker and JSON representation factories. Whenever a Resource creates a concrete representation, it passes a uniform data model to the representation factory, which then instantiates the template with the data model and returns the resulting representation. (The Freemarker configuration is also handled by Spring.)

<bean id="resource" class="helloworldrestlet.HelloWorldResource"
	scope="prototype">
	<property name="available" value="true" />
	<property name="representationTemplates">
		<map>
			<entry key-ref="org.restlet.data.MediaType.TEXT_PLAIN"
				value-ref="hwFreemarkerTextPlain" />
			<entry key-ref="org.restlet.data.MediaType.TEXT_HTML"
				value-ref="hwFreemarkerTextHtml" />
			<entry key-ref="org.restlet.data.MediaType.APPLICATION_JSON"
				value-ref="jsonRepresentationFactory" />
		</map>
	</property>
</bean>

<bean id="hwFreemarkerTextPlain"
	class="edu.luc.etl.restlet.spring.FreemarkerRepresentationFactory">
	<property name="templateName" value="hw-plain.ftl" />
	<property name="freemarkerConfig" ref="freemarkerConfig" />
</bean>

<bean id="hwFreemarkerTextHtml"
	class="edu.luc.etl.restlet.spring.FreemarkerRepresentationFactory">
	<property name="templateName" value="hw-html.ftl" />
	<property name="freemarkerConfig" ref="freemarkerConfig" />
</bean>

<bean id="jsonRepresentationFactory"
	class="edu.luc.etl.restlet.spring.JsonRepresentationFactory" />

<!-- omitted beans for specific MediaType static fields --> 

<bean id="freemarkerConfig"
	class="freemarker.template.Configuration">
	<property name="directoryForTemplateLoading"
		value="src/test/resources/presentation" />
	<property name="objectWrapper">
		<bean class="freemarker.template.DefaultObjectWrapper" />
	</property>
</bean>

When using this approach, the Resources themselves become very simple, for example:

public class HelloWorldResource extends ConfigurableRestletResource {
    @Override
    public Representation represent(Variant variant) {
	final Map<String, Object> dataModel = Collections.singletonMap("DATE", (Object) new Date());
	return createTemplateRepresentation(variant.getMediaType(), dataModel);
    }
}

A working proof-of-concept for this approach is available through CVS from :pserver:anonymous@cvs.cs.luc.edu:/root/laufer/433, module ConfigurableRestletResource. Support for the missing configuration of representations tied to responses to non-GET requests is in the works.

6.21 SSL

6.21.1 Introduction

The SSL extension provides concrete implementations of the SslContextFactory that rely on jSSLutils. This extension is located in the com.noelios.restlet.ext.ssl package.

6.21.2 Description

6.21.2.1 JsslutilsSslContextFactory

The JsslutilsSslContextFactory class is a wrapper for jsslutils.sslcontext.SSLContextFactory. It has to be constructed with the instance to wrap and is therefore only suitable to be used in the context sslContextFactory attribute, not parameter. This is more likely to be used for more specialised features such as the key or trust manager wrappers of jSSLutils.

6.21.2.2 PkixSslContextFactory

The PkixSslContextFactory class is a class that uses jsslutils.sslcontext.PKIXSSLContextFactory. It provides a way to configure the key store, the trust store (required for client-side authentication) and the server alias. As part of its trust manager configuration, it provides a way to set up certificate revocation lists (CRLs).

6.21.2.2.1 Example using the Component XML configuration:
<component xmlns="http://www.restlet.org/schemas/1.1/Component"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.restlet.org/schemas/1.1/Component">

	<client protocol="FILE" />

	<server protocol="HTTPS" port="8183">
		<parameter name="sslContextFactory" value="com.noelios.restlet.ext.ssl.PkixSslContextFactory" />
		<parameter name="keystorePath" value="/path/to/keystore.p12" />
		<parameter name="keystoreType" value="PKCS12" />
		<parameter name="keystorePassword" value="testtest" />
		<parameter name="keyPassword" value="testtest" />
		<parameter name="truststorePath" value="/path/to/truststore.jks" />
		<parameter name="truststoreType" value="JKS" />
		<parameter name="truststorePassword" value="testtest" />
		<parameter name="crlUrl" value="file:///path/to/crl.crl" />
		<parameter name="wantClientAuthentication" value="true" />
	</server>

	<defaultHost>
		<attach uriPattern="" targetClass="org.restlet.example.tutorial.Part12" />
	</defaultHost>
</component>

There can be multiple crlUrl parameters. In addition, two other parameters can be set:

The wantClientAuthentication parameter is handled by this the SslContextFactory, but is often used in conjunction with it.

6.21.2.2.2 Example embedded within the program, using two connectors:
Component component = new Component();

Server server1 = component.getServers().add(Protocol.HTTPS, 
   "host1.example.org", 8083);
Series<Parameter> param1 = server1.getContext().getParameters();
 
param1.add("sslContextFactory","com.noelios.restlet.ext.ssl.PkixSslContextFactory");
param1.add("keystorePath","/path/to/keystore1.p12");
param1.add("keystorePassword","...");
param1.add("keystoreType","PKCS12");
//...

Server server2 = component.getServers().add(Protocol.HTTPS, 
   "host2.example.com", 8083);
Series<Parameter> param2 = server2.getContext().getParameters();
 
param2.add("sslContextFactory","com.noelios.restlet.ext.ssl.PkixSslContextFactory");
param2.add("keystorePath","/path/to/keystore2.p12");
//...

This example uses two certificates depending on which server connector (and thus which listening socket) is used.

6.22 Velocity extension

6.22.1 Introduction

Velocity is an embeddable tool that provides a template language used to reference java objects passed to the engine. Any kind of text output (from HTML to autogenerated source code) can be generated.

6.22.2 Description

This extension lets you generate Representations based on the Velocity template engine. Please, refer to the Velocity extension Javadocs and the FAQ #10 for more details.

Here is the list of dependencies for this extension:

6.23 WADL extension

6.23.1 Introduction

6.23.2 Description

6.23.2.1 Indicate schema relative to an XML representation

A bit of theory

Quoting the WADL specification:

The "grammars" element acts as a container for definitions of the format of data
exchanged during execution of the protocol described by the WADL document. Such
definitions may be included inline or by reference using the include element.

For example:

<grammars>
  <include href="NewsSearchResponse.xsd"/>
  <include href="Error.xsd"/>
</grammars>

NB: at this time, the WADL extension of the Restlet framework supports only "included" and not "inline" schemas via the GrammarsInfo#includes attribute.

Then, for XML-based representations, the "element" attribute specifies the qualified name of the root element as described within the grammars section.

For example:

<representation mediaType="application/xml" element="yn:ResultSet"/>

Assuming that the "yn" namespace is declared in the document:

<application [...] xmlns:yn="urn:yahoo:yn" >
Implementation with Restlet

At the level of the subclass of WadlApplication, override the getApplicationInfo method:

@Override
public ApplicationInfo getApplicationInfo(Request request, Response response) {
    ApplicationInfo appInfo = super.getApplicationInfo(request, response);
    appInfo.getNamespaces().put("urn:yahoo:yn", "yn");
    GrammarsInfo grammar = new GrammarsInfo();
    IncludeInfo include = new IncludeInfo();
    include.setTargetRef(new Reference("NewsSearchResponse.xsd"));
    grammar.getIncludes().add(include);
    appInfo.setGrammars(grammar);
    return appInfo;
}

Then, at the level of the subclass of WadlResource, update the RepresentationInfo#element attribute:

RepresentationInfo formRepresentation = new RepresentationInfo();
formRepresentation.setXmlElement("yn:ResultSet");

6.23.3 WADL sample application

6.23.3.1 Documenting the "firstResource" sample application

This sample code is an extension of the "firstResource" sample application. The source code is available in the "org.restlet.example" extension, more precisely in the "org.restlet.ext.wadl" package.

The aim is to provide WADL documentation for this application. Basically, we must be able to generate a proper documentation for:

Here is the list of modifications.

6.23.3.1.1 FirstResourceApplication class
    @Override
    public ApplicationInfo getApplicationInfo(Request request, Response response) {
        ApplicationInfo result = super.getApplicationInfo(request, response);

        DocumentationInfo docInfo = new DocumentationInfo(
                "This sample application shows how to generate online documentation.");
        docInfo.setTitle("First resource sample application.");
        result.setDocumentation(docInfo);

        return result;
    }
6.23.3.1.2 BaseResource class
6.23.3.1.3 ItemsResource
    @Override
    protected Representation describe() {
        setTitle("List of items.");
        return super.describe();
    }
    @Override
    protected void describeGet(MethodInfo info) {
        info.setIdentifier("items");
        info.setDocumentation("Retrieve the list of current items.");

        RepresentationInfo repInfo = new RepresentationInfo(MediaType.TEXT_XML);
        repInfo.setXmlElement("items");
        repInfo.setDocumentation("List of items as XML file");
        info.getResponse().getRepresentations().add(repInfo);
    }
    @Override
    protected void describePost(MethodInfo info) {
        info.setIdentifier("create_item");
        info.setDocumentation("To create an item.");

        RepresentationInfo repInfo = new RepresentationInfo(
                MediaType.APPLICATION_WWW_FORM);
        ParameterInfo param = new ParameterInfo("name", ParameterStyle.PLAIN,
                "Name of the item");
        repInfo.getParameters().add(param);
        param = new ParameterInfo("description", ParameterStyle.PLAIN,
                "Description of the item");
        repInfo.getParameters().add(param);
        repInfo.getStatuses().add(Status.SUCCESS_CREATED);

        repInfo.setDocumentation("Web form.");
        info.getRequest().getRepresentations().add(repInfo);

        FaultInfo faultInfo = new FaultInfo(Status.CLIENT_ERROR_NOT_FOUND);
        faultInfo.setIdentifier("itemError");
        faultInfo.setMediaType(MediaType.TEXT_HTML);
        info.getResponse().getFaults().add(faultInfo);
    }
6.23.3.1.4 ItemResource
    @Override
    public Representation describe() {
        setTitle("Representation a single item");
        return super.describe();
    }
    @Override
    protected void describeGet(MethodInfo info) {
        info.setIdentifier("item");
        info.setDocumentation("To retrieve details of a specific item");

        RepresentationInfo repInfo = new RepresentationInfo(MediaType.TEXT_XML);
        repInfo.setXmlElement("item");
        repInfo.setDocumentation("XML representation of the current item.");
        info.getResponse().getRepresentations().add(repInfo);

        FaultInfo faultInfo = new FaultInfo(Status.CLIENT_ERROR_NOT_FOUND,
                "Item not found");
        faultInfo.setIdentifier("itemError");
        faultInfo.setMediaType(MediaType.TEXT_HTML);
        info.getResponse().getFaults().add(faultInfo);
    }
    @Override
    protected void describeDelete(MethodInfo info) {
        info.setDocumentation("Delete the current item.");

        RepresentationInfo repInfo = new RepresentationInfo();
        repInfo.setDocumentation("No representation is returned.");
        repInfo.getStatuses().add(Status.SUCCESS_NO_CONTENT);
        info.getResponse().getRepresentations().add(repInfo);
    }
    @Override
    protected void describePut(MethodInfo info) {
        info.setDocumentation("Update or create the current item.");

        RepresentationInfo repInfo = new RepresentationInfo(
                MediaType.APPLICATION_WWW_FORM);
        ParameterInfo param = new ParameterInfo("name", ParameterStyle.PLAIN,
                "Name of the item");
        repInfo.getParameters().add(param);
        param = new ParameterInfo("description", ParameterStyle.PLAIN,
                "Description of the item");
        repInfo.getParameters().add(param);
        repInfo.getStatuses().add(Status.SUCCESS_OK);
        repInfo.getStatuses().add(Status.SUCCESS_CREATED);

        repInfo.setDocumentation("Web form.");
        info.getRequest().getRepresentations().add(repInfo);

        super.describePut(info);
    }

6.23.3.2 Getting the documentation

The documentation is available via the OPTIONS method. and is available under 2 formats: WADL or HTML.

6.23.3.2.1 WADL documentation

Here is a way to programmatically obtain the WADL documentation of the application:

Client client = new Client(Protocol.HTTP);

// Displays the WADL documentation of the application
client.options("http://localhost:8182/firstResource").getEntity().write(System.out);

Here is a way to programmatically obtain the WADL documentation of the "items" resource:

Client client = new Client(Protocol.HTTP);

// Displays the WADL documentation of the application
client.options("http://localhost:8182/firstResource/items").getEntity().write(System.out);
6.23.3.2.2 HTML documentation

This format is an XML transformation of the WADL representation with an XSL sheet, developped and maintained by  Mark Nottingham: here

Here is a way to programmatically obtain the HTML documentation of the application:

Client client = new Client(Protocol.HTTP);

// Displays the HTML documentation of the "item1" resource
// Make sure to have a proper transformation engine (it has been tested
// successfully with xalan 1.2.7)
Request request = new Request(Method.OPTIONS, "http://localhost:8182/");
request.getClientInfo().getAcceptedMediaTypes().add(new Preference<MediaType>(MediaType.TEXT_HTML));
client.handle(request).getEntity().write(System.out);

NB: in order to work properly, you will certainly have to updated your classpath with the archove of a convenient transformation engine. Xalan 2.7.1 has been successfully tested.

6.24 Oracle XDB Restlet Adapter

6.24.1 Documentation

6.24.2 Using XDB Restlet Adapter within Maven projects

6.24.3 Oracle XDB Restlet Adapter - Architecture - Introduction

6.24.3.1 Introduction

Oracle XDB Restlet adapter is Server connector for Restlet Framework it provides to Oracle 11g the availability to support server side REST Web Services (WS).
For doing that we use the Oracle JVM, an embedded JVM compatible with JDK 1.5 running inside the database, it means using same memory space and local access to the SQL resources.
Additional to this Oracle XMLDB provides a Servlet 2.2 compatible stack to implement server side Servlets. These components work together to run Restlet Framework and to receive HTTP request using the embedded listener.
Oracle also provides a native SOAP support for running native Web Services, but many people think that REST support brings to Oracle other features:

6.24.3.2 Architecture

Following picture depicts Oracle XDB Restlet adapter and Oracle components.

Note that Oracle SQLNet is accepting either connection using TTC presentation protocol (traditional Client/Server architecture) and HTTP/FTP Presentation protocol.

The application stack is depicted in the following picture:

Following picture shows REST XDB adapter implementation integrated into Oracle.

Return to main document.

6.24.4 Oracle XDB Restlet Adapter - Installing

6.24.4.1 Installing Oracle XDB Adapter

6.24.4.1.1 Requirements
6.24.4.1.2 Installing

First edit into your home directory a file named build.properties with:

# Restlet project
# xdb_11.1 specific
sqlnet.string=test
jdbc.username=RESTLET
jdbc.password=RESTLET
jdbc.sysusr=sys
jdbc.syspwd=change_on_install

Also is necessary a valid ORACLE_HOME environment variable defined to a valid Oracle 11g home directory, this variable then is used to locate for example the SQLPlus application.
Finally go the directory:

# cd src/org.restlet.ext.xdb_11.1/resources

and execute Ant without argument:

# ant

To start using XDB Adapter ant without arguments is the only target required in a fresh database install. Other targets are provided during development stage, for example if you update the adapter code only the target load-server-side-runtime is required to re-install it.

6.24.4.1.2.1 Enabling your XMLDB HTTP support

Oracle databases do not enable by default XMLDB HTTP repository access. To enable it using SQLPlus connected as SYSDBA execute:

SQL> exec dbms_xdb.sethttpport(8080);

Restart your database and test with a browser or any WebDAV enable file manager a connection to http://localhost:8080/

Return to main document.

6.24.5 Oracle XDB Restlet Adapter - Testing

6.24.5.1 Testing

6.24.5.1.1 Testing using a browser

If you performs an installation from the snapshot version, it doesn't include the examples, you have to download the Java SE Edition which includes them.
The Ant scripts used during the installation outputs which commands are required to install the examples, following the steps:

loadjava -r -v -s -g public -u RESTLET/RESTLET@test org/restlet/example/tutorial/Part10.java
arguments: '-u' 'RESTLET/***@test' '-r' '-v' '-s' '-g' 'public' 'org/restlet/example/tutorial/Part10.java'      
...
Errors: 0
[mochoa@mochoa src]$ loadjava -r -v -s -g public -u RESTLET/RESTLET@test org/restlet/example/tutorial/UserResource.java
...
Errors: 0
[mochoa@mochoa src]$ loadjava -r -v -s -g public -u RESTLET/RESTLET@test org/restlet/example/tutorial/OrderResource.java
...
Errors: 0
[mochoa@mochoa src]$ loadjava -r -v -s -g public -u RESTLET/RESTLET@test org/restlet/example/tutorial/OrdersResource.java
...
Errors: 0
[mochoa@mochoa src]$ loadjava -r -v -s -g public -u RESTLET/RESTLET@test org/restlet/example/tutorial/Part12.java
arguments: '-u' 'RESTLET/***@test' '-r' '-v' '-s' '-g' 'public' 'org/restlet/example/tutorial/Part12.java'
...
Synonyms Created: 1
Errors: 0

Test your REST examples with your favorite browser using these URLs (they where configured as XMLDB Servlets by src/org.restlet.ext.xdb/resources/sql/postInstall.sql script):

http://localhost:8080/userapp/users/scott/orders/300

XMLDB is an HTTP 1.0 complaint connector, usually modern browsers try to connect using HTTP 1.1 so you can experiment that the browser leave the connection open because is trying to use Keep-alive feature.

6.24.5.1.2 Tests using telnet

Some test can be done by using telnet application to see which headers are sent and got as response from REST WS. For example:

[mochoa@mochoa resources]$ telnet localhost 8080
Trying 127.0.0.1...
Connected to live.dbprism.mochoa.dyndns.org (127.0.0.1).
Escape character is '^]'.

GET /userapp/users/scott/orders/300 HTTP/1.0
Host: localhost:8080

HTTP/1.1 200 OK
MS-Author-Via: DAV
DAV: 1,2,<http://www.oracle.com/xdb/webdav/props>
Date: Wed, 09 Dec 2009 12:45:37 GMT
Server: Restlet-Framework/2.0m6
Accept-Ranges: bytes
Content-Type: */*; charset=ISO-8859-1
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Content-Length: 28

Order "300" for user "scott"

6.24.5.2 Minimalistic test comparing REST versus native SOAP

6.24.5.2.1 Benchmarking REST application

As you can see in a previous section there is simple User application which returns orders for scott user.
Using ApacheBench you can test the application executing:

ab -n {total_request} -c {concurrent_request} http://localhost:8080/userapp/users/scott/orders/300

Where total_request is number of request sent by Apache benchmark paralleling it in concurrent_request request.
A result of this execution on my notebook can be compared in this Google sheet.

6.24.5.2.2 Testing a similar WS implemented using SOAP

A similar functionality can be implemented using XMLDB Native SOAP WS .
For doing that create this Java source at Scott's schema:

create or replace and compile java source named "my.OrderCalculator" as
package my;

import java.util.logging.Level;
import java.util.logging.Logger;

public class OrderCalculator {
    /**
     * Java Util Logging variables and default values
     */
    private static Logger logger = null;

    /**
     * Constant used to get Logger name
     */
    static final String CLASS_NAME = OrderCalculator.class.getName();

    static {
            logger = Logger.getLogger(CLASS_NAME);
            logger.setLevel(Level.ALL);
    }

   public static String getOrder(String userName, int orderId) {
        logger.entering(CLASS_NAME,"getOrder",new Object [] {userName,new Integer(orderId)});
     logger.exiting(CLASS_NAME,"getOrder","Order '"+orderId+"' for user '"+userName+"'");
     return "Order '"+orderId+"' for user '"+userName+"'";
   }
}
/

Note that I have added JDK Logging functionality to compare a closer example to Restlet functionality, obviously routing and many other default Restlet functionalities are not compared with this example.
And his PLSQL Call Spec:

CREATE OR REPLACE PACKAGE orders_calculator AUTHID CURRENT_USER AS
  FUNCTION getOrder(user_name IN VARCHAR2, order_id IN NUMBER) RETURN VARCHAR2 as LANGUAGE JAVA NAME
     'my.OrderCalculator.getOrder(java.lang.String, int) return java.lang.String';
END orders_calculator;
/

As you can see OrderCalculator class is using JDK logging package, to get JDK logging working this grant is required:

SQL> exec dbms_java.grant_permission( 'SCOTT', 'SYS:java.util.logging.LoggingPermission', 'control', '' );
SQL> exec dbms_java.grant_permission( 'SCOTT', 'SYS:java.lang.RuntimePermission', 'createClassLoader', '' );
SQL> commit;

Finally to send a POST message using Apache benchmark its necessary to edit a POST XML message like:

<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://xmlns.oracle.com/orawsv/SCOTT/ORDERS_CALCULATOR/GETORDER">
   <env:Header/>
   <env:Body>
      <ns1:SVARCHAR2-GETORDERInput>
         <ns1:USER_NAME-VARCHAR2-IN>scott</ns1:USER_NAME-VARCHAR2-IN>
         <ns1:ORDER_ID-NUMBER-IN>300</ns1:ORDER_ID-NUMBER-IN>
      </ns1:SVARCHAR2-GETORDERInput>
   </env:Body>
</env:Envelope>

The ApacheBench command line will look like:

ab -A scott:tiger -H 'SOAPAction: "GETORDER"' -p /tmp/soap-post-func.txt -n {total_request} -c {concurrent_request} http://localhost:8080/orawsv/SCOTT/ORDERS_CALCULATOR/GETORDER

Where:

Do not forget grant XDB_WEBSERVICES and XDB_WEBSERVICES_OVER_HTTP roles to SCOTT, also register the orawsv Servlet.

6.24.5.2.3 Testing with Apache mod_mem_cache.

One of the most important consequence of REST architecture is that is on top on HTTP protocol, so why not include for example reverse proxy in front of Oracle XMLDB Restlet adapter.
On Linux you can try this configuration:
Add this to /etc/httpd/modules.d/57_mod_mem_cache.conf file:

.....
<IfModule mod_cache.c>

    # CacheEnable - A cache type and partial URL prefix below which caching is enabled
    #CacheEnable mem /manual
    #CacheEnable fd /images
    CacheEnable mem /userapp
    CacheEnable mem /orawsv

</IfModule>
....

This will enable mod_mem_cache to any URL starting with /userapp/ directory, this directory will be retrieved using Apache mod_proxy.
Edit /etc/httpd/modules.d/30_mod_proxy.conf adding these lines:

<IfModule mod_proxy.c>
....
    SetEnv proxy-nokeepalive 1
....
    ProxyPass /userapp/ http://localhost:8080/userapp/
    ProxyPassReverse /userapp/ http://localhost:8080/userapp/
    ProxyPass /orawsv/ http://localhost:8080/orawsv/
    ProxyPassReverse /orawsv/ http://localhost:8080/orawsv/
....
</IfModule>

This will redirect automatically any URL http://localhost:80/userapp/ to XMLDB http://localhost:8080/userapp/.
Finally start Apache Web Server and test the URL http://localhost/userapp/users/scott/orders/300 note now we are using port 80, not port 8080.
To boost your REST WS performance you can change, for example, the expiration header of the response, many WS can use this trick a typically example is a weather service which is updated every 30 minutes. In our User application this change can be injected at org.restlet.example.tutorial.OrderResource class method represent, for example:

    @Override
    public Representation represent(Variant variant) throws ResourceException {
        Representation result = null;

        if (variant.getMediaType().equals(MediaType.TEXT_PLAIN)) {
            result = new StringRepresentation("Order \"" + this.orderId
                    + "\" for user \"" + this.userName + "\"");
       }

        Date expirationDate = new Date(System.currentTimeMillis()+10000);
        result.setExpirationDate(expirationDate);
        return result;
    }

This small change represent for 100 request in User application a difference between:
Requests per second:    49.65 [#/sec] (mean)
to
Requests per second:    1407.90 [#/sec] (mean)
and 1 request to XMLDB instead of 100 request, reducing a lot a server workload.
There is no change with our SOAP WS because POST messages are not cached by mod_mem_cache reverse proxy.

6.24.5.2.3.1 Testing performance with Apache JMeter

XMLDB Restlet Adapter can be tested with Apache JMeter, here some captures with the above REST and SOAP WS.
Test plan used with Users Restlet example:

Thread Group -> Thread Properties
Number of Threads (users): 10
Ramp Up Period (in seconds): 0
Loop Count: 200
HTTP Request -> Web Server
Server Name or IP: localhost
HTTP Request -> HTTP Request
Protocol: http
Method: GET
Path: /userapp/users/scott/orders/300
Gaussian Random Timer -> Thread Delay Properties
Deviation (in milliseconds): 100.0
Constant Delay Offset (in milliseconds): 300

6.24.5.2.4 Graph Results

  Test plan used with Users SOAP example:

Number of Threads (users): 10
Ramp Up Period (in seconds): 0
Loop Count: 200
SOAP/XML-RPC Request -> Web Server
Server Name or IP: localhost
HTTP Request -> HTTP Request
URL: http://localhost:8080/orawsv/SCOTT/ORDERS_CALCULATOR/GETORDER
Send SOAPAction: GETORDER
User KeepAlive: true
SOAP/XML-RPC Data Filename: /tmp/soap-post-func.txt
HTTP Header Manager -> Headers Stored in the Header Manager
Authorization: Basic c2NvdHQ6dGlnZXI=    (Base 64 encoding of scott/tiger)
Gaussian Random Timer -> Thread Delay Properties
Deviation (in milliseconds): 100.0
Constant Delay Offset (in milliseconds): 300
/tmp/soap-post-func.txt file content:
<?xml version = '1.0'?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://xmlns.oracle.com/orawsv/SCOTT/ORDERS_CALCULATOR/GETORDER">
   <env:Header/>
   <env:Body>
      <ns1:SVARCHAR2-GETORDERInput>
         <ns1:USER_NAME-VARCHAR2-IN>scott</ns1:USER_NAME-VARCHAR2-IN>
         <ns1:ORDER_ID-NUMBER-IN>300</ns1:ORDER_ID-NUMBER-IN>
      </ns1:SVARCHAR2-GETORDERInput>
   </env:Body>
</env:Envelope>

6.24.5.2.5 Graph Results

Return to main document.

6.24.6 Oracle XDB Restlet Adapter - FAQ

6.24.6.1 Where Restlet logging information goes?

Restlet framework and XMLDB Restlet Adapter uses JDK logging package, by default logging information goes to $ORACLE_BASE/diag/rdbms/$SID/$SID/trace directory.
Due REST WS are started by a background process automatically controlled by Oracle database logging information is at files named $SID_snnn_pid.trc, for example:

Trace file /u01/app/oracle/diag/rdbms/test/test/trace/test_s000_10024.trc
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
ORACLE_HOME = /u01/app/oracle/product/11_2_0_1_0/db_1
System name:    Linux
Node name:      mochoa
Release:        2.6.31.5-desktop-1mnb
Version:        #1 SMP Fri Oct 23 01:46:54 EDT 2009
Machine:        i686
Instance name: test
Redo thread mounted by this instance: 1
Oracle process number: 19
Unix process pid: 10024, image: oracle@mochoa (S000)

*** 2009-12-09 09:08:48.888
*** SESSION ID:(143.17) 2009-12-09 09:08:48.888
*** CLIENT ID:() 2009-12-09 09:08:48.888
*** SERVICE NAME:(SYS$USERS) 2009-12-09 09:08:48.888
*** MODULE NAME:() 2009-12-09 09:08:48.888
*** ACTION NAME:() 2009-12-09 09:08:48.888

jox_call_xdb_class_ c_state 0

*** 2008-06-04 15:28:23.018
jox_call_xdb_class_ argvec[0] 0 argvec[1] 0

*** 2009-12-09 09:17:42.296
jox_call_xdb_class_ argvec[0] 0 argvec[1] 0
UsersRestlet: init                         
UsersRestlet: [Noelios Restlet Engine] - The ServerServlet address = 127.0.0.1
UsersRestlet: [Noelios Restlet Engine] - The ServerServlet port = 8080        
UsersRestlet: [Noelios Restlet Engine] - The ServerServlet endpoint = 1       
UsersRestlet: [Noelios Restlet Engine] - Schema: RESTLET class: org.restlet.ext.xdb.XdbServerServlet loader: class oracle.aurora.rdbms.DbmsJava
Dec 9, 2009 12:17:42 PM org.restlet.ext.xdb.internal.XdbServletWarClientHelper start                                                           
INFO: efective user is: ANONYMOUS                                                                                                              
Dec 9, 2009 12:17:42 PM org.restlet.ext.xdb.internal.XdbServletWarClientHelper handleLocal                                                     
INFO: looking resources at: /home/ANONYMOUS/wars/UsersRestlet/WEB-INF/restlet.xml                                                              
Dec 9, 2009 12:17:42 PM org.restlet.ext.xdb.internal.XdbServletWarClientHelper start                                                           
INFO: efective user is: ANONYMOUS                                                                                                              
Dec 9, 2009 12:17:42 PM org.restlet.ext.xdb.internal.XdbServletWarClientHelper handleLocal                                                     
INFO: looking resources at: /home/ANONYMOUS/wars/UsersRestlet/WEB-INF/restlet.xml                                                              
UsersRestlet: [Noelios Restlet Engine] - Schema: RESTLET class: org.restlet.example.tutorial.Part12 loader: class oracle.aurora.rdbms.DbmsJava
Dec 9, 2009 12:17:42 PM org.restlet.ext.xdb.internal.XdbServletWarClientHelper start                                                           
INFO: efective user is: ANONYMOUS                                                                                                              
Dec 9, 2009 12:17:42 PM org.restlet.ext.xdb.internal.XdbServletWarClientHelper handleLocal                                                     
INFO: looking resources at: /home/ANONYMOUS/wars/UsersRestlet/WEB-INF/restlet.xml                                                              
UsersRestlet: [Restlet] Attaching application: org.restlet.example.tutorial.Part12@e2c7e499 to URI: /userapp                                   
Dec 9, 2009 12:17:42 PM org.restlet.ext.xdb.internal.XdbServletWarClientHelper start                                                           
INFO: efective user is: ANONYMOUS                                                                                                              

*** 2009-12-09 09:17:43.598
Dec 9, 2009 12:17:43 PM org.restlet.engine.log.LogFilter afterHandle
INFO: 2009-12-09        12:17:43        -       -       127.0.0.1       8080    GET     /userapp/users/scott/orders/300 -       200     28      -       1001    http://localhost:8080   -       -

6.24.6.2 How many concurrent session are started by Oracle?

As mentioned in previous answer the Oracle JVM session which receives the request is automatically started by Oracle, how many concurrent sessions are started by Oracle Listener is automatically computed by Oracle and you don't care about it. My testing shows that for heavy workload there is around 5 to 7 % of concurrent request.

6.24.6.3 Which is the effective Oracle user when run a REST WS?

It depends on the HTTP authorization mechanism.
REST WS which are available as anonymous access, no HTTP authorization information, runs with ANONYMOUS Oracle user and PUBLIC database role.
REST WS which are authorized though HTTP header Authorization are executed with his effective Oracle user, for example SCOTT.

6.24.6.4 How to enable anonymous REST WS?

First unlock ANONYMOUS Oracle account. By default XMLDB Restlet Adapter do this command at postInstall.sql script

SQL> alter user anonymous account unlock;

Then you have to register your Restlet application into XMLDB configuration file (named /xdbconfig.xml) with this Servlet role:

              <servlet xmlns="http://xmlns.oracle.com/xdb/xdbconfig.xsd">
                <servlet-name>UsersRestlet</servlet-name>
                <servlet-language>Java</servlet-language>
                <display-name>Restlet Servlet</display-name>
                <servlet-class>org.restlet.ext.xdb.XdbServerServlet</servlet-class>
                <servlet-schema>PUBLIC</servlet-schema>
                <init-param xmlns="http://xmlns.oracle.com/xdb/xdbconfig.xsd">
                  <param-name>org.restlet.application</param-name>
                  <param-value>RESTLET:org.restlet.example.tutorial.Part12</param-value>
                  <description>REST User Application</description>
                </init-param>
                <security-role-ref xmlns="http://xmlns.oracle.com/xdb/xdbconfig.xsd">
                  <description/>
                  <role-name>PUBLIC</role-name>
                  <role-link>PUBLIC</role-link>
                </security-role-ref>
              </servlet>

Above registration can be done by a following PLSQL script executed logged as SYS:

DECLARE
  configxml SYS.XMLType;
begin
  dbms_xdb.deleteServletMapping('UsersRestlet');
  dbms_xdb.deleteServlet('UsersRestlet');
  dbms_xdb.addServlet(name=>'UsersRestlet',language=>'Java',class=>'org.restlet.ext.xdb.XdbServerServlet',dispname=>'Restlet Servlet',schema=>'PUBLIC');
  -- Modify the configuration
  -- Due this servlet provide public access, it can not load
  -- '/home/'||USER||'/restlet/UsersRestlet.xml' from XMLDB repository
  SELECT INSERTCHILDXML(xdburitype('/xdbconfig.xml').getXML(),'/xdbconfig/sysconfig/protocolconfig/httpconfig/webappconfig/servletconfig/servlet-list/servlet[servlet-name="UsersRestlet"]','init-param',
  XMLType('<init-param xmlns="http://xmlns.oracle.com/xdb/xdbconfig.xsd">
                  <param-name>org.restlet.application</param-name>
                  <param-value>RESTLET:org.restlet.example.tutorial.Part12</param-value>
                  <description>REST User Application</description>
           </init-param>'),'xmlns="http://xmlns.oracle.com/xdb/xdbconfig.xsd"') INTO configxml
  FROM DUAL;
  -- Update the configuration to use the modified version
  --I got this error at this line :
  dbms_xdb.cfg_update(configxml);
  dbms_xdb.addServletSecRole(SERVNAME => 'UsersRestlet',ROLENAME => 'PUBLIC',ROLELINK => 'PUBLIC');
  dbms_xdb.addServletMapping('/userapp/*','UsersRestlet');
  commit;
end;
/
commit;

For more information on how to register a Servlet with anonymous access read Using Protocols to Access the Repository.

6.24.6.5 How can I define my Application in XdbServerServlet?

XMLDB do not accept context parameters so unlike org.restlet.ext.servlet.ServerServlet class, XdbServerServlet have two way to define org.restlet.application parameter.
First option was used in previous examples, it means using Servlet 2.2 <init-param> tag, this is very useful for anonymous REST applications.
For authenticated applications there is another option which is to put an XML file at XMLDB repository using this predefined path:
/home/USER/wars/appName/WEB-INF/restlet.xml

where USER is the efective connected username, for example SCOTT, and appName is the servlet name; name argument in dbms_xdb.addServlet procedure used for registering Servlet in XMLDB, in above example is UsersRestlet.

This file look like:

<restlet-app>
   <org.restlet.application>org.restlet.example.tutorial.Part12</org.restlet.application>
</restlet-app>

Second option do not require DBA role if you want to update your application class name.

Return to main document.

6.24.7 Oracle XDB Restlet Adapter - Others

6.24.7.1 Future plans

XmldbDirectory class sub-classing Directory to provide load and browse operation over XMLDB repository (Done!! example of browsing coming soon).
XMLType optimized Variant to exploit Lazy DOM native implementation inside the OJVM, extract method and native stream support.

6.24.7.2 Known caveats

Some browser such Firefox reports an unexpected exception because it tries to stay connected to XMLDB HTTP protocol handler, you can avoid it changing network.http.keep-alive property to false. See this OTN Forums thread, or better than this you can use XMLDB listener behind a proxy such as Apache mod_proxy, read the FAQ to see how to configure Apache mod_proxy and mod_mem_cache modules.

Usually to run REST application in other schema like SCOTT these grants are required (JDK Logging and class loader functionality):

SQL> exec dbms_java.grant_permission( SCOTT, 'SYS:java.lang.RuntimePermission', 'getClassLoader', '' );
SQL> exec dbms_java.grant_permission( SCOTT, 'SYS:java.lang.RuntimePermission', 'createClassLoader', '' );
SQL> exec dbms_java.grant_permission( SCOTT, 'SYS:java.util.logging.LoggingPermission', 'control', '' );
SQL> exec dbms_java.grant_permission( SCOTT, 'SYS:java.lang.RuntimePermission', 'accessDeclaredMembers', '' );
SQL> commit;

6.24.7.3 Reference

Return to main document.

6.24.8 XMLDB Restet Adapter/Lucene/Maven

6.24.8.1 Purpose of the document

This document and his related project aims to show how to implement REST Web Services inside Oracle JVM.
To show it, the idea is to implement some services which interacts with Lucene Domain Index for Oracle, this domain index provides to Oracle free text searching facilities using Apache Lucene library.
To re-use some ideas and specification we use Lucene WS API Document.

6.24.8.2 Change Log

6.24.8.3 Dependencies

This project depends on:

6.24.8.4 Where to download

This project is downloaded from several sources as follow:
- Project binary archive Zip or Tar.gz
- Project source from CVS repository, follow instructions from (http://sourceforge.net/cvs/?group_id=56183) module lucene-restlet.
- Lucene Domain Index binary distribution, download and extract in any directory, then follow Maven install instruction to add to your local repository.
- RESTs artifacts, automatically download from http://maven.restlet.org/.
- Lucene artifacts, automatically downloaded from Maven's public repository.

6.24.8.5 Directory structure

This project follows Maven standard layout. Here a list of the content of each one:
src/main/java (source of Lucene WS API implementation)
src/main/scripts (HTTP test messages to show Lucene WS API usage)
src/main/sql (post installation script to register Lucene WS API as XMLDB Servlet)
src/main/webapp (a Web Application layout to test and debug this implementation outside the OJVM using Jetty)
src/test/java (Client side JUnit tests suites which consumes Lucene REST WS API, coming soon)
src/test/jmeter (Apache JMeter test suites for testing WS performance)
src/resources (a build.properties file used to deploy Lucene WS API inside the OJVM)

6.24.8.6 Configuration Parameters

Several parameters at the boton of pom.xml file, properties section, are used during install target, here a brief explanation of each one:

....
<properties>
    <sqlplus.app.value>${env.ORACLE_HOME}/bin/sqlplus</sqlplus.app.value>
    <restlet.owner.value>RESTLET</restlet.owner.value>
    <sqlnet.string.value>test</sqlnet.string.value>
    <jdbc.str.value>test</jdbc.str.value>
    <jdbc.username.value>LUCENE</jdbc.username.value>
    <jdbc.password.value>LUCENE</jdbc.password.value>
    <jdbc.sysusr.value>sys</jdbc.sysusr.value>
    <jdbc.syspwd.value>change_on_install</jdbc.syspwd.value>
  </properties>
....

sqlplus.app: using ORACLE_HOME environment variable will work in most of the installation, this parameter is used to locate Oracle SQLPlus executable application used to connect as sysdba.
restlet.owner: Oracle schema where XMLDB Restlet adapter was installed.
sqlnet.string: SQLNet connect string to the target database.
jdbc.{username,password,sysusr,syspwd}: username/password where Lucene REST WS API will be installed, sysusr/syspwd used to connect with sysdba role to perform post installation steps.

6.24.8.7 Targets

mvn clean

Clean Maven's target directory.

mvn compile

Compile Lucene REST WS API implementation. First execution of this target will try to download from Maven publics repostories Oracle JDBC driver and Oracle-Lucene artifacts, this Maven's artifacts are not in public repositories you can install into your local repository as follow

mvn install:install-file -DgroupId=oracle -DartifactId=ojdbc5 -Dversion=11.1.0 -Dpackaging=jar -Dfile=$ORACLE_HOME/jdbc/lib/ojdbc5.jar
mvn install:install-file -DgroupId=oracle -DartifactId=xdb -Dversion=11.1.0 -Dpackaging=jar -Dfile=$ORACLE_HOME/rdbms/jlib/xdb.jar
mvn install:install-file -DgroupId=org.apache.lucene -DartifactId=lucene-ojvm -Dversion=2.3.2 -Dpackaging=jar -Dfile=/home/mochoa/jdevhome/mywork/ojvm-bin/11g/ojvm/lib/lucene-ojvm-2.3.jar
mvn install:install-file -DgroupId=org.apache.lucene -DartifactId=lucene-ojvm-test -Dversion=2.3.2 -Dpackaging=jar -Dfile=/home/mochoa/jdevhome/mywork/ojvm-bin/11g/ojvm/lib/lucene-ojvm-2.3-test.jar

mvn test

Runs JUnit test suites. By now only a simple test suite is performed, Maven requires one to create an artifact. More Restlet client side test suites will be added soon.

mvn install

Install Lucene REST WS API into the database using configurations parameters explained above. Also copy a .jar file to a local repository.

Return to main document.

6.24.9 XMLDB Restet Adapter/Lucene/Maven - Running/Testing

6.24.9.1 Starting Jetty to debug these services outside OJVM

This Maven target provides a client side environment to test and debug REST WS without installing it inside the OJVM. Note that in this server side implementation of REST WS we are using a unique entry point to get the SQL connection, this connection when running outside the database use System's properties to get user, password and SQLNet connect string to connect to the target database.

[mochoa@mochoa lucene-restlet]$ mvn jetty:run
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'jetty'.
[INFO] ----------------------------------------------------------------------------
[INFO] Building org.apache.lucene.ws
[INFO]    task-segment: [jetty:run]
[INFO] ----------------------------------------------------------------------------
[INFO] Preparing jetty:run
[INFO] [resources:resources]
.....
[INFO] Property db.str=test was set
[INFO] Property db.usr=LUCENE was set
[INFO] Property db.pwd=LUCENE was set

2008-06-19 09:21:03.559::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
[INFO] Context path = /
[INFO] Tmp directory =  determined at runtime
[INFO] Web defaults = org/mortbay/jetty/webapp/webdefault.xml
[INFO] Web overrides =  none
[INFO] Webapp directory = /home/mochoa/jdevhome/mywork/lucene-restlet/src/main/webapp
[INFO] Starting jetty 6.1.7 ...
2008-06-19 09:21:03.796::INFO:  jetty-6.1.7
2008-06-19 09:21:04.286::INFO:  No Transaction manager found - if your webapp requires one, please configure one.
2008-06-19 09:21:05.171::INFO:  Started SelectChannelConnector@0.0.0.0:8088
[INFO] Started Jetty Server
[INFO] Starting scanner at interval of 10 seconds.
2008-06-19 09:24:08.039:/:INFO:  UsersRestlet: [Noelios Restlet Engine] - The ServerServlet address = null
2008-06-19 09:24:08.039:/:INFO:  UsersRestlet: [Noelios Restlet Engine] - The ServerServlet port = 8080
2008-06-19 09:24:08.039:/:INFO:  UsersRestlet: [Noelios Restlet Engine] - The ServerServlet endpoint = 1
2008-06-19 09:24:08.039:/:INFO:  UsersRestlet: [Noelios Restlet Engine] - Try to load 'org.restlet.attribute.application' parameter from '/home/'||USER||'/restlet/UsersRestlet.xml
2008-06-19 09:24:11.584:/:INFO:  UsersRestlet: [Noelios Restlet Engine] - Try to load 'org.restlet.attribute.component' parameter from '/home/'||USER||'/restlet/UsersRestlet.xml
2008-06-19 09:24:11.595:/:INFO:  UsersRestlet: [Noelios Restlet Engine] - Try to load 'org.restlet.component' parameter from '/home/'||USER||'/restlet/UsersRestlet.xml
Jun 19, 2008 9:24:11 AM org.restlet.Connector <init>
WARNING: The connector has been instantiated without any protocol.
2008-06-19 09:24:11.808:/:INFO:  UsersRestlet: [Noelios Restlet Engine] - Try to load 'org.restlet.attribute.server' parameter from '/home/'||USER||'/restlet/UsersRestlet.xml
2008-06-19 09:24:11.818:/:INFO:  UsersRestlet: [Noelios Restlet Engine] - Attaching application: org.apache.lucene.ws.LuceneApplication@5878d2 to URI: /lucene
Jun 19, 2008 9:24:11 AM com.noelios.restlet.ext.xdb.XdbServletWarClientHelper start
INFO: efective user is: LUCENE
Jun 19, 2008 9:24:12 AM com.noelios.restlet.LogFilter afterHandle
INFO: 2008-06-19        09:24:12        -       -       -       8080    GET     /lucene/        -       200     157     -       704     http://localhost:8088 -       -

Note that LUCENE user is configured in pom.xml file, so it will passed to Jetty as System properties and used by XMLDB Restlet adapter as effective user. If you will try to test LuceneApplication using telnet scripts change LUCENE/LUCENE to scott/tiger into pom.xml file.

You can debug and test LuceneApplication.java using Restlet default servlet engine starting it as a simple Java application, but this scenary will not test XMLDB Restlet stack.

6.24.9.2 Testing with telnet

Directory src/main/scripts have several .txt file which includes HTTP content information to test Lucene REST WS API.
For example to get all Lucene Domain Indexes at SCOTT's schema you can execute:

[mochoa@mochoa lucene-restlet]$ cat src/main/scripts/test_get_scott.txt
GET /lucene/ HTTP/1.0
Authorization: Basic c2NvdHQ6dGlnZXI=
Host: localhost:8080

[mochoa@mochoa lucene-restlet]$ telnet localhost 8080
Trying 127.0.0.1...
Connected to live.dbprism.mochoa.dyndns.org (127.0.0.1).
Escape character is '^]'.
GET /lucene/ HTTP/1.0
Authorization: Basic c2NvdHQ6dGlnZXI=
Host: localhost:8080

HTTP/1.1 200 OK
MS-Author-Via: DAV
DAV: 1,2,<http://www.oracle.com/xdb/webdav/props>
Date: Wed, 18 Jun 2008 23:08:06 GMT
Server: Noelios-Restlet-Engine/1.1.snapshot
Content-Type: application/atomsvc+xml; charset=ISO-8859-1
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Content-Length: 330
Expires: Wed, 18 Jun 2008 23:08:16 GMT

<?xml version="1.0" encoding="ISO-8859-1"?>
<service xmlns="http://purl.org/atom/app#">
   <workspace title="Lucene Web Service">
         <collection href="SOURCE_BIG_LIDX/" title="Index Name: SOURCE_BIG_LIDX status: VALID">
                     <member-type>entry</member-type>
         </collection>
   </workspace>
</service>
Connection closed by foreign host.

Note that the Authorization header have a B64 encoding information of scott:tiger user/password, if your database have different values it will not work. Also we are using XMLDB default HTTP port (8080).
The example shows that scott have one Lucene Domain Index named SOURCE_BIG_LIDX. This index was created using a table and index creation SQL script like:

SQL> create table test_source_big as (select * from all_source);

SQL> create index source_big_lidx on test_source_big(text)
indextype is lucene.LuceneIndex
parameters('AutoTuneMemory:true;Analyzer:org.apache.lucene.analysis.StopAnalyzer;\
MergeFactor:500;FormatCols:line(0000);ExtraCols:line "line"');

6.24.9.3 Testing with JMeter plugin for Maven

Download and install JMeter Maven Plugin following this guide at http://wiki.apache.org/jakarta-jmeter/JMeterMavenPlugin
Install required libraries from JMeter distribution

mvn install:install-file -DgroupId=org.apache.jmeter -DartifactId=jmeter -Dversion=2.2 -Dpackaging=jar -Dfile=/home/mochoa/Download/jmeter-2.2.jar -DpomFile=/home/mochoa/Download/jmeter-2.2.pom
mvn install:install-file -DgroupId=org.apache.jorphan -DartifactId=jorphan -Dversion=2.2 -Dpackaging=jar -Dfile=/usr/local/jakarta-jmeter-2.3.1/lib/jorphan.jar  
mvn install:install-file -DgroupId=org.mozilla.javascript -DartifactId=javascript -Dversion=1.0 -Dpackaging=jar -Dfile=/usr/local/jakarta-jmeter-2.3.1/lib/js_rhino1_6R5.jar 
mvn install:install-file -DgroupId=jcharts -DartifactId=jcharts -Dversion=0.7.5 -Dpackaging=jar -Dfile=/usr/local/jakarta-jmeter-2.3.1/lib/jCharts-0.7.5.jar  

pom.xml file modifications

....

    <dependency>
      <groupId>org.apache.jmeter</groupId>
      <artifactId>maven-jmeter-plugin</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
....

      <plugin>
        <groupId>org.apache.jmeter</groupId>
        <artifactId>maven-jmeter-plugin</artifactId>
        <configuration>
          <includes>
            <include>test_get_scott.jmx</include>
          </includes>

          <reportDir>target/jmeter-reports</reportDir>

        </configuration>
      </plugin>

....

running

mvn org.apache.jmeter:maven-jmeter-plugin:jmeter

6.24.9.4 Measuring performance using Apache JMeter

Using some of the JMeter templates at directory src/test/jmeter you can performs performance test of Lucene REST WS API over Lucene Domain Index. Here a sample screen shoot:

Return to main document.

6.24.10 XMLDB Restet Adapter/Lucene/Maven - Todo List

6.24.10.1 ToDo list

Return to main document.

6.24.11 XMLDB Restet Adapter/Lucene/Maven - Services implemented

6.24.11.1 Services implemented

GET services are implemented because PUT methods are easier to perform using SQL interface. There is no limitation to implement PUT, POST and DELETE methods, but we think that SQL interface is a better place to do it.
Other services will be implemented soon to provide other services not available through SQL interface and Lucene REST WS API, for example to get term info.
Here a list of GET services implemented and his link to the specification

Resource Method Description Server Content Class
Service

GET

Retrieves a list of indices

AtomPP introspection document

IndexesResource.java

Index

GET

Most recent modified documents

Atom Feed

IndexResource.java

Index

GET (with ?query)

Searches the index

Atom Feed

QueryResource.java

Index.Properties

GET

Retrieves the list of properties for the index

Atom Entry

IndexProperty.java

OpenSearch Description

GET

Gets the OpenSearch Description document

OSD Document

IndexOpenSearch.java

Document

GET

Gets a document from the index

Atom Entry

DocumentResource.java

Document

GET (with /mlt at end)

Gets a list of document like this (More like this)

Atom Feed

To be Implemented

Document

GET (with /fieldName at end)

Gets a list of term freq for a given term

Atom Feed

To be implemented

Return to main document.

7 Restlet-GWT module

This covers version 1.1 of the Restlet Framework. See this page for version 2.0.

7.1 Introduction

This chapter presents the Restlet-GWT module, which is a port of the client side Restlet API to GWT 1.5.

7.2 Description

Google Web Toolkit is a powerful and widely used platform for rich internet application. It is based on a smart compiler taking Java source and producing optimized JavaScript (byte)code.

By default, GWT recommends using a custom GWT-RPC mechanism to communicate between the GWT front-end (Web browser) and the back-end (Web server). In addition, the back-end has to be built using a Servlet container in order to work properly and to invoke your custom classes and methods. This might remind you of the RMI (Remote Method Invocation) or CORBA mechanisms and it comes with the same issues: the tight coupling between client and server code. Also, this reduces the opportunities of integration with other back-end technologies, outside Java/Servlet.

As you know, REST is a much more flexible and interoperable way to communicate between a client and a server. On the server-side, you can use Restlet or alternative technologies. But on the GWT front-end, the support has been limited so far. The GWT API does contain classes to send HTTP requests but they are quite low-level (you need to understand the HTTP headers syntax for example) and slow down productivity.

Thanks to the new GWT 1.5 release, it was possible to quickly port the Restlet API and Engine to GWT. We kept only the classes required for the client-side obviously and had to remove classes based on Java APIs not available in GWT (such as NIO channels or BIO streams). We tried to provide an easy integration with JSON and XML as they are the two most common media types to exchange representations in REST for rich clients.

7.3 Architecture flexibility

7.3.1 Introduction

7.3.2 GWT's idiomatic RPC approach

Figure 1. (For comparison)  GWT's idiomatic RPC approach requires a Servlet container and communicates opaquely via JSON-encoded data atoms.  Alternatives involve writing low-level HTTP code.

7.3.3 The client-side Restlet-GWT module

Figure 2.  The client-side Restlet-GWT module (org.restlet.gwt) plugs into your Google Web Toolkit code as a module, and allows you to use the high level Restlet API to talk to any server platform.  XML and JSON representations are supported by default, and of course you can develop your own representational abstractions as well.  Code written for Restlet should be simple to port to Restlet-GWT.

7.3.4 Restlet-GWT can work alongside GWT-RPC

Figure 3. Restlet-GWT can work alongside GWT-RPC and other mechanisms.  REST APIs exposed by your custom Servlets can work alongside GWT-RPC in a Servlet container environment.

7.3.5 Restlet, an ideal server side companion for Restlet-GWT

Figure 4. .  Not only does Restlet provide a simple means of defining and mapping REST resources, it also provides useful facilities like the Redirector, which can be used to gateway requests to other servers, easily working around the single-source limitations of the AJAX programming model.  The Restlet server-side library even works in GWT Hosted Mode using the Noelios GWT Extension, so your entire application can be readily debugged.

7.3.6 Integration with standalone Restlet connectors

Figure 5.  If you don't need to use the Servlet-dependent GWT-RPC API, your compiled GWT application can be deployed very efficiently in a standalone Restlet environment using one of the embedded server connectors.  Restlet 1.1's internal server connector, for example, has no dependencies other than Java; with this, it is possible to create and release an extremely small, but very full featured, standalone application.

7.4 Setting up a project

7.4.1 Client Side

To use Restlet-GWT on the client side of your GWT application (Figure 2-5 above):

1) Create an application normally with the applicationCreator and/or projectCreator scripts supplied with GWT, or using your favorite GWT design or IDE plugins.

2) Add the Restlet-GWT JAR (org.restlet.gwt.jar) to the project classpath [explain]

3) Add the following to your application's module definition file (yourapp.gwt.xml):

<inherits name='org.restlet.GWT'/>

This will make the Restlet-GWT API available to your GWT compiled code.  The Restlet-GWT module in turn inherits the GWT standard HTTP, JSON, and XML modules. You can also check the full Javadocs of the API online.

7.4.2 Hosted Mode

If you would like to debug your application in hosted mode using Restlet on the server side as well (Figure 4 above), you must also modify the GWT-generated web.xml file in hosted mode's %projectHome%/tomcat/webapps/WEB-INF directory (note that this directory is generated dynamically by GWT when launching the hosted mode for the first time).  GwtShellServletWrapper, provided by the Noelios GWT Extension (com.noelios.restlet.ext.gwt_1.5.jar) extends ServerServlet and shares its semantics, but also knows how to pass Hosted Mode requests to the GWT Shell Servlet.

1) Add com.noelios.restlet.ext.gwt_1.5.jar, org.restlet.jar, com.noelios.restlet.jar, and com.noelios.restlet.ext.servlet_2.5.jar to the project classpath [explain].  Also, be sure to add any other Restlet extension JARs necessary for extensions you plan to use on the server side.

2) Modify the web.xml to use the GwtShellServletWrapper:

<?xml version="1.0" encoding="UTF-8"?>
<web-app>

	<servlet>
		<servlet-name>adapter</servlet-name>
		<servlet-class>com.noelios.restlet.ext.gwt.GwtShellServletWrapper</servlet-class>
		<init-param>
		  <param-name>org.restlet.application</param-name>
		  <param-value>application</param-value>
		</init-param>
		<init-param>
		  <param-name>module</param-name>
		  <param-value>module</param-value>
		</init-param>
	</servlet>
	
	<servlet-mapping>
		<servlet-name>adapter</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>

</web-app>

For application, supply the name of your Restlet Application, e.g. org.restlet.test.gwt.server.TestApplication.  You can also supply a component via an org.restlet.component parameter, or any other permitted ServerServlet configuration parameter.

The module should be the name of your GWT module as seen in the hosted mode URI path.  This is the package name plus the base filename of your GWT module file, e.g. org.restlet.test.gwt.TestClient.

The web.xml file can be overwritten by GWT Hosted Mode in some situations.  If your Restlet server side functionality fails and you start receiving messages about server requests being incorrectly dispatched to an unknown module, check that the web.xml file still contains valid contents.

7.5 Invoking server side code

7.5.1 Description

The Restlet-GWT API is both a subset and a superset of the Restlet API.

It is a subset because, as mentioned above, parts of the Restlet API have been deleted, where they depend on Java platform features not available in the Javascript environment.

It is a superset because the Restlet-GWT API is fully (and only) asynchronous, which the Restlet 1.1 API is not.  This is necessary to conform to the behavior of the XmlHttpRequest-based Client, as well as the strictures of the unthreaded Javascript environment.  In the future, the Restlet API will expose asynchronous calls, and these will hopefully converge with the Restlet-GWT API.

Here is a snippet of code (from the downloadable example below) showing briefly how to instantiate a Client and make an asynchronous GET call:

        closeButton.addClickListener(new ClickListener() {
            public void onClick(Widget sender) {
                final Client client = new Client(Protocol.HTTP);
                client.get("http://localhost:8888/ping", new Callback() {
                    @Override
                    public void onEvent(Request request, Response response) {
                        button.setText(response.getEntity().getText());
                    }
                });
                dialogBox.hide();
            }
        });

7.6 Examples

7.6.1 Introduction

An example project download is provided that works both under Eclipse and via ant build.  This sets up the basic framework for GWT compilation and debugging in Hosted Mode, provides a basic Restlet-powered server, and demonstrates how the compiled GWT application can be bundled into an executable server JAR.

Download Restlet GWT -- Simple Example

This is a simple example demonstrating some basic patterns for using Restlet and GWT.  It produces an executable JAR file which depends only on core Restlet libraries (included in "lib") to start a small Java Web server on port 8888, which you can visit to access a  compiled GWT application that, in turn, talks to the Web server.

You can also run the application in GWT Hosted Mode under Eclipse by using the included SimpleExample.launch configuration; right click this and choose Run As ... SimpleExample.

It is structured as an Eclipse project; you should be able to import it into your Eclipse 3.3 or better workspace.  You can also run the ant build script directly to produce the executable.

You must supply your own GWT 1.5 binaries; update the Eclipse build path and/or the GWT_1.5 property in the ant build script to point to the GWT binaries for your platform.

7.6.1.1 Zip content

Name

Description

src

Source files of both:

  • client page developped with GWT and Restlet, in package "org.restlet.example.gwt.client".
  • Web server application developped with Restlet that serves the compiled web page and hosts a resource requested from the Web page.

build.xml

Ant script that:

  • compiles the GWT page
  • produces a final JAR file (RestletGWTSimpleExample.jar") of the server code in directory "dist". It also includes the "/etc/manifest.mf" file.

dist

Final directory where is located the final JAR of the server code.

etc

Directory where is located the "MANIFEST.MF" file of the server final JAR.

lib

Libraries taken from the Restlet framework (server and client APIs and implementations, GWT integration, servlet integration).

tomcat

Gathers configuration files for running the sample application inside Tomcat.

SimpleExample.launch

Used to run the application in GWT Hosted Mode under Eclipse; right click this and choose "Run As ... SimpleExample".

README.txt

Read it!

7.6.2 Description

7.6.2.1 GWT page

You can find the source code of this page in directory "src/org/restlet/example/gwt/client".

Once the server is running, this page can be accessed at the following URL: "http://localhost:8888/SimpleExample.html" .

This page is in charge to display several sample item such image, button, etc organized in panels. All of these objects are instances of GWT classes:

// Define an image
Image img = new Image("http://code.google.com/webtoolkit/logo-185x175.png");
// Define a button
final Button button = new Button("Click me");
[...]
// Define a panel
VerticalPanel vPanel = new VerticalPanel();
// We can add style names.
vPanel.addStyleName("widePanel");
vPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
// Add image, button, tree
vPanel.add(img);
vPanel.add(button);

These class illustrates also how to add an asynchronous call with AJAX inside the final Web page. It is as simple as to use a simple Restlet client in order to request the "ping" resource located at URL '"http://localhost:8888/ping" :

                final Client client = new Client(Protocol.HTTP);
                client.get("http://localhost:8888/ping", new Callback() {
                    @Override
                    public void onEvent(Request request, Response response) {
                        button.setText(response.getEntity().getText());
                    }
                });

7.6.2.2 Server side

Basically, the server s responsible to serve the generated page, and to respond to asynchronous call described just above.

The generated page is served by a simple Directory Restlet from the "bin" directory when the server is run under Eclipse.

The asynchronous call is delegated to the PingResource class which inherits from the Restlet Resource class. It simply answers to requests with a line of text.

    @Override
    public Representation represent(Variant variant) throws ResourceException {
    	return new StringRepresentation(
                "The Restlet server side is alive. Method called: "
                        + getRequest().getMethod(), MediaType.TEXT_PLAIN);
    }

7.7 Authenticating requests

7.7.1 Introduction

If you want to access to securized resources, the request must be completed with authentication credentials via the ChallengeResponse object. Such object is instantiated with the required challenge scheme (such as HTTP_BASIC, HTTP_DIGEST) and the credentials.

You must be aware that at the end the relation between your browser and the server is handled by the XmlHttpRequest javascript object. According to the provided data (scheme, credentials), it generates the right request and in case the credentials are not sufficient, you will be prompted to enter your credentials in a pop-up window.

7.7.2 Authentication with the HTTP_BASIC scheme

The following snippet of code illustrates pre-emptive authentication with the HTTP_BASIC scheme. It simply instantiates a new ChallengeResponse object with the authentication scheme, the login and password.

// Send an authenticated request using the Basic authentication scheme.
Request request = new Request(Method.GET, "http://localhost:8888/guarded");
ChallengeResponse authentication = new ChallengeResponse(ChallengeScheme.HTTP_BASIC, "scott", "tiger");
request.setChallengeResponse(authentication);
new Client(Protocol.HTTP).handle(request, new Callback() {
    @Override
    public void onEvent(Request request, Response response) {
        tb.setText(response.getEntity().getText());
    }
});

7.7.3 Authentication with the HTTP_DIGEST scheme

The following snippet of code illustrates pre-emptive authentication with the HTTP_DIGEST scheme. It simply instantiates a new ChallengeResponse object with the authentication scheme, the login and password.

// Send an authenticated request using the DIGEST authentication scheme.
final Reference reference = new Reference("http://localhost:8888/guarded_digest");
final Client client = new Client(Protocol.HTTP);
Request request = new Request(Method.GET, reference);
ChallengeResponse authentication = new ChallengeResponse(ChallengeScheme.HTTP_DIGEST, "login", "secret");
request.setChallengeResponse(authentication);
// Send the request
client.handle(request, new Callback() {
    @Override
    public void onEvent(Request request, Response response) {
        if (response.getStatus().isSuccess()) {
            tbDigest.setText(response.getEntity().getText());
        }
    }
});

7.8 Working with JSON

7.8.1 Description

There is a special org.restlet.gwt.resource.JsonRepresentation class that you can leverage to either parse a JSON representation received or to serialize a JSON value. In addition, a shortcut org.restlet.gwt.data.Response#getEntityAsJson() was added to automatically wrap the response entity in a JsonRepresentation instance.

Here is a sample code taken from the example application. The JsonRepresentation gives access to the underlying JSONValue after the representation has been parsed.

Request request = new Request(Method.GET, "http://localhost:8888/test");
// Indicates the client preferences and let the server handle the best representation with content negotiation.
request.getClientInfo().getAcceptedMediaTypes().add(new Preference<MediaType>(MediaType.APPLICATION_JSON));
new Client(Protocol.HTTP).handle(request, new Callback() {
        @Override
        public void onEvent(Request request, Response response) {
                // Get the representation as an JsonRepresentation
                JsonRepresentation rep = response.getEntityAsJson();
                // Displays the properties and values.
                JSONObject object = rep.getValue().isObject();
                if (object != null) {
                        for (String key : object.keySet()) {
                                jsonRoot.addItem(key + ":" + object.get(key));
                        }
                }
        }
});

7.9 Working with XML

7.9.1 Description

There is a special org.restlet.gwt.resource.XmlRepresentation class that you can leverage to either parse a XML representation received or to serialize a XML DOM. In addition, a shortcut org.restlet.gwt.data.Response#getEntityAsXml() was added to automatically wrap the response entity in a XmlRepresentation instance.

Here is a sample code taken from the example application. The XmlRepresentation gives access to the underlying DOM document via the "getDocument()" method.

Request request = new Request(Method.GET, "http://localhost:8888/test");
// Indicates the client preferences and let the server handle the best representation with content negotiation.
request.getClientInfo().getAcceptedMediaTypes().add(new Preference<MediaType>(MediaType.TEXT_XML));
new Client(Protocol.HTTP).handle(request, new Callback() {
        @Override
        public void onEvent(Request request, Response response) {
                // Get the representation as an XmlRepresentation
                XmlRepresentation rep = response.getEntityAsXml();

                // Loop on the nodes to retrieve the node names and text content.
                NodeList nodes = rep.getDocument().getDocumentElement().getChildNodes();
                for (int i = 0; i < nodes.getLength(); i++) {
                        Node node = nodes.item(i);
                        xmlRoot.addItem(node.getNodeName() + ":" + node.getFirstChild().getNodeValue());
                }
        }
});

7.10 Tips and tricks

7.10.1 Responses with no entity

This tip applies in the case of applications that run in GWT hosted mode.
Imagine that a resource handles a POST request and tells a user to redirect to another URI. In this case, it seems useless to add en entity body since its content is generally discarded by the client. However, you will notice that your Internet browser displays a white page even if the POST request has been correctly issued by the server.
This is due to a limitation not fixed yet where very small entities are swallowed by the servlet container of the GWT hosted mode.

If you face this problem, a simple workaround is just to add a reasonably sized entity to the response. For example, you can add a simple filter at the top of your hierarchy of nodes which ensure that an entity is sent back to the client.

7.11 Deploy GWT sample application in Servlet container

7.11.1 Introduction

Since the example project provides a basic Restlet-powered server, it should be easy to deploy it inside a servlet container. GWT does not provide standard way to achieve this task, however, you can still get more information at this URL : http://code.google.com/docreader/#p=google-web-toolkit-doc-1-5&s=google-web-toolkit-doc-1-5&t=FAQ_PackageAppInWARFile.

Our sample application is composed of:

The main task is to generate a correct WAR file. Hopefully this is not very difficult.

7.11.2 Set up the WAR file

Here is the content of the target WAR file:

+ META-INF
    - MANIFEST.MF
+ WEB-INF
    - web.xml
    + lib
        - org.restlet.jar, com.noelios.restlet.jar: Restlet core archives
        - com.noelios.restlet.ext.servlet_2.5.jar: Servlet adapter for Restlet
        - org.restlet.ext.json_2.0.jar, org.json.jar: Json extension
        - RestletGWTSimpleExample.jar: generated by the ant script, contains the static pages and the code of the server application.

Here the content of the web.xml file:

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app>
   <context-param>
      <param-name>org.restlet.application</param-name>  
      <param-value>org.restlet.example.gwt.server.TestServerApplication</param-value>  
   </context-param> 
   <context-param>
      <param-name>org.restlet.clients</param-name>
      <param-value>HTTP CLAP</param-value>
   </context-param>
   <servlet>
      <servlet-name>adapter</servlet-name>
      <servlet-class>com.noelios.restlet.ext.servlet.ServerServlet</servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>adapter</servlet-name>
      <url-pattern>/*</url-pattern>
   </servlet-mapping>
</web-app>

You may have to change either the URIs called from the static page, or configure Tomcat in order to listen to the right port, and load the War file with the right prefix. By default, the URIs are as follow : "http://localhost:8888/ping", taht is to say port is equals to 8888 and no application prefix.

8 Glossary

8.1 Table of contents

  1. Application
  2. Client
  3. Component
  4. Connector
  5. Context
  6. Directory
  7. Engine
  8. Filter
  9. Finder
  10. Guard
  11. Redirector
  12. Representation
  13. Request
  14. Resource
  15. Response
  16. Restlet
  17. Route
  18. Router
  19. Server
  20. Transformer
  21. Uniform
  22. Virtual Host

8.2 Application

Restlet that can be attached to one or more VirtualHosts. Applications are guaranteed to receive calls with their base reference set relatively to the VirtualHost that served them. This class is both a descriptor able to create the root Restlet and the actual Restlet that can be attached to one or more VirtualHost instances.

8.3 Client

Connector acting as a generic client. It internally uses one of the available connectors registered with the current Restlet implementation.

8.4 Component

Restlet managing a set of Clients, Servers and other Restlets.
"A component is an abstract unit of software instructions and internal state that provides a transformation of data via its interface." Roy T. Fielding

Component managing a set of VirtualHosts and Applications. Applications are expected to be directly attached to VirtualHosts. Components are also exposing a number of services in order to control several operational features in a portable way, like access log and status setting.

8.5 Connector

Restlet enabling communication between Components.
"A connector is an abstract mechanism that mediates communication, coordination, or cooperation among components. Connectors enable communication between components by transferring data elements from one interface to another without changing the data." Roy T. Fielding

"Encapsulate the activities of accessing resources and transferring resource representations. The connectors present an abstract interface for component communication, enhancing simplicity by providing a clean separation of concerns and hiding the underlying implementation of resources and communication mechanisms." Roy T. Fielding

8.6 Context

Contextual data and services provided to a Restlet. The context is the means by which a Restlet may access the software environment within the framework. It is typically provided by the immediate parent Restlet (Component and Application are the most common cases). The services provided are access to a logger, access to configuration parameters and to a request dispatcher.

8.7 Directory

Handler mapping a directory of local resources. Those resources have representations accessed by the file system, the WAR context or the class loaders. An automatic content negotiation mechanism (similar to the one in Apache HTTP server) is used to select the best representation of a resource based on the available variants and on the client capabilities and preferences.

8.8 Engine

A Restlet Engine is an implementation of the Restlet API. The reference implementation, provided by Noelios Technologies, is therefore called the Noelios Restlet Engine (NRE).

8.9 Filter

Restlet filtering calls before passing them to an attached Restlet. The purpose is to do some pre-processing or post-processing on the calls going through it before or after they are actually handled by an attached Restlet. Also note that you can attach and detach targets while handling incoming calls as the filter is ensured to be thread-safe.

8.10 Finder

Restlet that can find the target resource that will concretely handle the request. Based on a given resource class, it is also able to instantiate the resource with the call's context, request and response without requiring the usage of a subclass. Once the target resource has been found, the call is automatically dispatched to the appropriate handle*() method (where the '*' character corresponds to the method name) if the corresponding allow*() method returns true.

For example, if you want to support a MOVE method for a WebDAV server, you just have to add a handleMove() method in your subclass of Resource and it will be automatically be used by the Finder instance at runtime.

If no matching handle*() method is found, then a Status.CLIENT_ERROR_METHOD_NOT_ALLOWED is returned.

8.11 Guard

Filter guarding the access to an attached Restlet.

8.12 Redirector

Rewrites URIs then redirects the call or the client to a new destination.

8.13 Representation

Current or intended state of a resource. For performance purpose, it is essential that a minimal overhead occurs upon initialization. The main overhead must only occur during invocation of content processing methods (write, getStream, getChannel and toString).Current or intended state of a resource.

"REST components perform actions on a resource by using a representation to capture the current or intended state of that resource and transferring that representation between components. A representation is a sequence of bytes, plus representation metadata to describe those bytes. Other commonly used but less precise names for a representation include: document, file, and HTTP message entity, instance, or variant." Roy T. Fielding

8.14 Request

Generic request sent by client connectors. It is then received by server connectors and processed by Restlets. This request can also be processed by a chain of Restlets, on the client or server sides. Requests are uniform across all types of connectors, protocols and components.

8.15 Resource

Intended conceptual target of a hypertext reference. "Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on. In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource."

"The only thing that is required to be static for a resource is the semantics of the mapping, since the semantics is what distinguishes one resource from another." Roy T. Fielding

Another definition adapted from the URI standard (RFC 3986): a resource is the conceptual mapping to a representation (also known as entity) or set of representations, not necessarily the representation which corresponds to that mapping at any particular instance in time. Thus, a resource can remain constant even when its content (the representations to which it currently corresponds) changes over time, provided that the conceptual mapping is not changed in the process. In addition, a resource is always identified by a URI.

8.16 Response

Generic response sent by server connectors. It is then received by client connectors. Responses are uniform across all types of connectors, protocols and components.

8.17 Restlet

Dispatcher that provides a context and life cycle support.

8.18 Route

Filter scoring the affinity of calls with the attached Restlet. The score is used by an associated Router in order to determine the most appropriate Restlet for a given call.

8.19 Router

Restlet routing calls to one of the attached routes. Each route can compute an affinity score for each call depending on various criteria. The attach() method allow the creation of routes based on URI patterns matching the beginning of a the resource reference's remaining part.

In addition, several routing modes are supported, implementing various algorithms:

Note that for routes using URI patterns will update the resource reference's base reference during the routing if they are selected. If you are using hierarchical paths, remember to directly attach the child routers to their parent router instead of the top level Restlet component. Also, remember to manually handle the path separator characters in your path patterns otherwise the delegation will not work as expected.

Finally, you can modify the routes list while handling incoming calls as the delegation code is ensured to be thread-safe.

8.20 Server

Connector acting as a generic server. It internally uses one of the available connectors registered with the current Restlet implementation.

8.21 Transformer

Filter that can transform XML representations by applying an XSLT transform sheet.

8.22 Uniform

Base class exposing a uniform REST interface.

"The central feature that distinguishes the REST architectural style from other network-based styles is its emphasis on a uniform interface between components. By applying the software engineering principle of generality to the component interface, the overall system architecture is simplified and the visibility of interactions is improved. Implementations are decoupled from the services they provide, which encourages independent evolvability." Roy T. Fielding

It has many subclasses that focus on a specific ways to handle calls like filtering, routing or finding a target resource. The context property is typically provided by a parent component as a way to give access to features such as logging and client connectors.

8.23 Virtual Host

Router of calls from Server connectors to Restlets. The attached Restlets are typically Applications.