Help

Built with Seam

You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.

This page is a work in progress. We use it to collect all TODOs and other items related to REST-oriented application architecture with Seam.

Two general strategies are considered:

1. Running an AJAX client application (GWT, any JS library with REST/AJAX support) that accesses a Seam server-side application. The Seam application should be able to provide a REST-oriented remote API. Representation formats could be JSON, XML, or XHTML. This is related to our research into Three-tier applications with Seam.

2. A REST-oriented remote API on HTTP as a replacement for the dumb SOAP/RPC webservices.

To accomplish this, we need a standards-based solution for declaring resources in a Seam application and for routing and marshaling HTTP requests and responses.


JAX-RS and RESTEasy integration

The Java standard for defining RESTful resources and declaring HTTP APIs is JAX-RS (JSR 311).

Seam integrates this in version 2.1 with the RESTeasy implementation.

This allows you to run your existing @Path and @Provider classes in a Seam app without any additional configuration or changes. Drop the classes into the classpath and Seam will serve HTTP requests through its existing resource-loading architecture (the SeamResourceServlet is enabled in all Seam applications). You can even hook into that request processing and customize the dispatcher, wrap the request, and so on. This is regular Seam stuff.

Seam component programming model

Of course people want that integration not only for integrated bootstrap and request processing but for the Seam programming model when writing resources and providers:

You can put an @Name onto your @Path root resource class. This enables Seam lifecycle management for the resource object. If it is ScopeType.EVENT you basically get the JAX-RS default (POJO per request) lifecycle. If it is ScopeType.APPLICATION, you get Singleton lifecycle - you can also put @Synchronized on it. And so on for ScopeType.SESSION and ScopeType.CONVERSATION. Once your resource classes and providers are Seam components, you get full Seam interception for @In(jection), and so on. E.g. you can use @In ItemDAO on a field in your ItemResource implementation.

You can put @Name on your @Provider class. It has to be ScopeType.APPLICATION or ScopeType.STATELESS.

(For the STATELESS providers we need an extension to RESTEasy - this is not implemented. We need to tell RESTEasy how it should look up an instance of a Provider from Seam at runtime. Right now Resteasy only support setProvider(clazz) and setProviderInstance(o) at bootstrap. We need setProviderLookup(anImplementationOfALookupInterface) or something similar.)

Security

Basic and digest HTTP authentication is available in Seam Security, it can be wrapped around any URI with a regex in configuration. That means any JAX-RS resources have full access to Seams @Restrict and any meta-annotated @PermissionCheck authorization solution.

We should support some more advanced authentication schemes out of the box, like Amazon S3 - tokens/subtokens, etc.

Exception mapping

JAX-RS specifies the ExceptionMapper providers: The job of an ExceptionMapper is to convert an Exception instance to an HttpResponse. In addition to this solution, Seam users should be able to use the mappings defined in pages.xml. This requires some changes to RESTEasy, see jbseam://3265.

Conversation integration

We'll probably have a mechanism for transporting conversation identifiers in HTTP headers. However, we are thinking that the way this should be implemented is with explicit automatically created resources that identify a particular conversation workspace. For example, a natural (named) conversation can be exposed as a resource: http://server/resource/editCustomer/666 would be an edit conversation for customer identifier 666.

See Bill's blog about JMS integration and how you'd model a transaction resource RESTfully. This is the same approach just for Seam conversations.

CRUD functionality out of box

In a second stage we might want to integrate the Seam Application Framework. This is a basic CRUD framework, today used for quick development of JSF apps. We can use this as a foundation to expose entity lists and instances for CRUD/search directly from the database as HTTP resources. Similar to what Rails does out of the box, just nicer :)

Implementing connected resources

I'm thinking about a special provider that can marshal an object graph into an XHTML (not just XML) response body and back from an XHTML request body to an object graph. This is about the connectedness of resources, see the O'Reilly REST book. As a developer I should write a Facelets XHTML template that defines the transformation. Imagine that you write it the same way you write a JSF template today, with bidirectional binding using EL expressions, from object getter/setter pair to XML attribute or element value. We can even have built-in Facelets widgets that render certain microformats. Seam has some machinery for this already but we might need an extra interceptor on resource methods to trigger the transformation. Or we use Seams pages.xml navigation rules (when this resource method finishes, render this template).

I've locally implemented one-way rendering of XHTML representations for GET requests:


@GET
@Path("/customer/{id}")
@ProduceMime("application/xhtml+xml")
@FaceletsXhtmlResponse(
    template = "/some/path/to/template/#{thisCanEvenBeEL}/foo.xhtml"
)
@Out(value = "currentCustomer", scope = ScopeType.EVENT)
public Customer getCustomer(@PathParam("id") String id) { ... }

The outjection occurs after the method returns and before the template is rendered. So the currentCustomer is available through EL in the template.

For PUT/POST payloads we might need a more sophisticated solution, I'm thinking we might also need state saving on the server or client, like JSF.


Challenges

Things we need to implement in Seam or find patterns based on existing Seam features.

Incomplete HTTP Clients/Browsers

Looks like Safari/Webkit does only GET and POST. Other methods of the application protocol need to be simulated, probably with a custom POST header that is transparently mapped on the Seam backend to DELETE, PUT, and HEAD operations.

Same Origin Domain Limitation

The security model of webbrowsers requires that Javascript can only send HTTP requests to the same domain (or a subdomain) that served the original Javascript code. Common workarounds:

  • Enable the UniversalBrowserRead property on the client, should ask the user for permission, works with signed scripts, etc. Disqualified because it doesn't work with MSFT software.
  • Javascript On Demand loading with the unsecured <script src="URI"> tag. Evil hack.
  • The server acts as a pass-through proxy and simply forwards the requests/respsonse 1:1. This is a risky strategy, you ideally want some filtering here. I don't like that solution at all.
  • ???

Two Connection Limitation

The HTTP standard seems to restrict the allowed number of parallel connections (asynchronous) to one domain to 2. I haven't heard about this and we need to check the HTTP spec and what browser actually do. Common workaround seems to be to put some resources into subdomains, e.g. images.mydomain.com, scripts.mydomain.com, etc.

Update: It doesn't look so bad anymore, see http://www.stevesouders.com/blog/2008/03/20/roundup-on-parallel-connections/.


Useful stuff

The O'Reilly book RESTful Web Services is the only readable and consistent documentation I found about REST.