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.

JAX-RS and RESTEasy integration

The Java standard for defining RESTful resources and declaring HTTP APIs is JAX-RS (JSR 311). Seam integrates this (starting in 2.1) with the RESTeasy implementation.

This allows you to run your existing @Path and @Provider annotated 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 needs to be enabled in web.xml for this to work but it should be in almost 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 - have a look at the source code of the /src/resteasy/ module if you are interested in the details of the integration code.

You can find more information about the existing integration in the reference documentation of your Seam version in the Webservices chapter.

The tests and examples can all be found in /examples/restbay and /examples/tasks.

We track all feature request and bugs under the WS JIRA component.

The rest of this page describes features we are discussing for implementation in future versions and notes about missing features of the current implementation. Features mentioned here as working might only be available in Seam nightly builds or SVN!

Provider component life cycle

In addition to using plain JAX-RS providers that are autodetected, you can put @Name on your @Provider class and make it a Seam component. It has to be ScopeType.APPLICATION. This is the current test matrix:

                                   | EVENT | CONVERSATION | SESSION | APPLICATION | STATELESS
---------------------------------------------------------------------------------------------
Plain JAX-RS Provider              |   -   |      -       |    -    |      -      |   OK
---------------------------------------------------------------------------------------------
RESTEasy StringConverter Provider  |   -   |      -       |    -    |      -      |   OK
---------------------------------------------------------------------------------------------
RESTEasy StringConverter Component |   ?   |      -       |    -    |      ?      |    ?
---------------------------------------------------------------------------------------------
POJO Seam Component Provider       |   ?   |      -       |    -    |     OK      |    ?
---------------------------------------------------------------------------------------------
POJO interface-annotated Component |   ?   |      -       |    -    |     OK      |    ?
---------------------------------------------------------------------------------------------
EJB Plain SLSB Provider            |   -   |      -       |    -    |      -      |    ?
---------------------------------------------------------------------------------------------
EJB SLSB Seam Component Provider   |   -   |      -       |    -    |      -      |    ?
---------------------------------------------------------------------------------------------
EJB SFSB Seam Component Resource   |   ?   |      -       |    -    |      ?      |    -
---------------------------------------------------------------------------------------------

Resource component life cycle

We try to integrate the JAX-RS resource lifecycle with the Seam POJO, Seam EJB, and plain EJB component models.

This is the current test matrix, see JBSEAM-4167. Assume that anything that is not OK is currently not supported at all:

                                   | EVENT | CONVERSATION | SESSION | APPLICATION | STATELESS
---------------------------------------------------------------------------------------------
Plain JAX-RS Resource              |  OK   |      -       |    -    |      -      |    -
---------------------------------------------------------------------------------------------
POJO Seam Component Resource       |  OK   |      ?       |    ?    |     OK      |   OK
---------------------------------------------------------------------------------------------
POJO interface-annotated Component |  OK   |      ?       |    ?    |     OK      |   OK
---------------------------------------------------------------------------------------------
EJB Plain SLSB Resource            |   -   |      -       |    -    |      -      |   OK
---------------------------------------------------------------------------------------------
EJB SLSB Seam Component Resource   |   -   |      -       |    -    |      -      |   OK
---------------------------------------------------------------------------------------------
EJB SFSB Seam Component Resource   |   ?   |      ?       |    ?    |      ?      |    -
---------------------------------------------------------------------------------------------

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. This is not as configurable as we'd like it to be, with the built-in Seam filter:

<web:authentication-filter url-pattern="/seam/resource/rest/*" auth-type="basic"/>

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

Testing RESTful architecture

The Seam core mock objects for HttpSession/Request/Response and so on are almost anemic and not usable for embedded unit testing. We developed enhanced versions that are in org.jboss.seam.resteasy.testfwk. This also includes a ResourceSeamTest that helps instantiating requests and passing it directly into the Seam filter/resource-servlet chain (no TCP connection, all local calls). We need to merge this solution with the core Seam testing harness and mocks. Track this JIRA issue for progress.

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

We currently have a prototype implementation of integration with the Seam CRUD framework. That means you can map an EntityHome and EntityQuery to HTTP resources with a few lines in components.xml. This is currently undocumented, see the /examples/restbay application and tests for demo.

Need more tests and review of the API.

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.

Also see this about JAXB templating.


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. This is going to be a problem not for computer-to-computer communication but if webbrowser clients want to use the same REST API. We might have to add a POST overload mechanism.

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.