23.4. RESTful HTTP web services with RESTEasy
Seam integrates the RESTEasy implementation of the JAX-RS specification (JSR 311). You can decide which of the following features are integrated with your Seam application:
- RESTEasy bootstrap and configuration, with automatic resource detection. and providers.
- SeamResourceServlet-served HTTP/REST requests, without the need for an external servlet or configuration in
web.xml
. - Resources written as Seam components with full Seam life cycle management and bijection.
23.4.1. RESTEasy configuration and request serving
First, download the RESTEasy libraries and the
jaxrs-api.jar
, and deploy them alongside the integration library (jboss-seam-resteasy.jar
) and any other libraries your application requires.
In seam-gen based projects, this can be done by appending
jaxrs-api.jar
, resteasy-jaxrs.jar
and jboss-seam-resteasy.jar
to the deployed-jars.list
(war deployment) or deployed-jars-ear.list
(ear deployment) file. For a JBDS based project, copy the libraries mentioned above to the EarContent/lib
(ear deployment) or WebContent/WEB-INF/lib
(war deployment) folder and reload the project in the IDE.
All classes annotated with
@javax.ws.rs.Path
will automatically be discovered and registered as HTTP resources at start up. Seam automatically accepts and serves HTTP requests with its built-in SeamResourceServlet
. The URI of a resource is built like so:
- The URI begins with the pattern mapped in
web.xml
for theSeamResourceServlet
— in the examples provided,/seam/resource
. Change this setting to expose your RESTful resources under a different base. Remember that this is a global change, and other Seam resources (s:graphicImage
) will also be served under this base path. - Seam's RESTEasy integration then appends a configurable string to the base path (
/rest
by default). So, in the example, the full base path of your resources would be/seam/resource/rest
. We recommend changing this string in your application to something more descriptive — add a version number to prepare for future REST API upgrades. This allows old clients to keep the old URI base. - Finally, the resource is made available under the defined
@Path
. For example, a resource mapped with@Path("/customer")
would be available under/seam/resource/rest/customer
.
The following resource definition would return a plain text representation for any GET request using the URI
http://your.hostname/seam/resource/rest/customer/123
:
@Path("/customer") public class MyCustomerResource { @GET @Path("/{customerId}") @Produces("text/plain") public String getCustomer(@PathParam("customerId") int id) { return ...; } }
If these defaults are acceptable, there is no need for additional configuration. However, if required, you can configure RESTEasy in your Seam application. First, import the
resteasy
namespace into your XML configuration file header:
<components xmlns="http://jboss.com/products/seam/components" xmlns:resteasy="http://jboss.com/products/seam/resteasy" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation= "http://jboss.com/products/seam/resteasy http://jboss.com/products/seam/resteasy-2.2.xsd http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.2.xsd">
<resteasy:application resource-path-prefix="/restv1"/>
The full base path to your resources is now
/seam/resource/restv1/{resource}
. Note that your @Path
definitions and mappings do not change. This is an application-wide switch, usually used for versioning of the HTTP API.
If you want to map the full path in your resources, you can disable base path stripping:
<resteasy:application strip-seam-resource-path="false"/>
Here, the path of a resource is now mapped with
@Path("/seam/resource/rest/customer")
. Disabling this feature binds your resource class mappings to a particular deployment scenario. This is not recommended.
Seam scans your classpath for any deployed
@javax.ws.rs.Path
resources or @javax.ws.rs.ext.Provider
classes. You can disable scanning and configure these classes manually like so:
<resteasy:application scan-providers="false" scan-resources="false" use-builtin-providers="true"> <resteasy:resource-class-names> <value>org.foo.MyCustomerResource</value> <value>org.foo.MyOrderResource</value> <value>org.foo.MyStatelessEJBImplementation</value> </resteasy:resource-class-names> <resteasy:provider-class-names> <value>org.foo.MyFancyProvider</value> </resteasy:provider-class-names> </resteasy:application>
The
use-built-in-providers
switch enables (default) or disables the RESTEasy built-in providers. Since these provide plain text, JSON and JAXB marshaling, we recommend that these are left enabled.
RESTEasy supports plain EJBs (EJBs that are not Seam components) as resources. Instead of configuring the JNDI names in a non-portable fashion in
web.xml
(see RESTEasy documentation), you can simply list the EJB implementation classes, not the business interfaces, in components.xml
as shown above. Note that you have to annotate the @Local
interface of the EJB with @Path
, @GET
, and so on - not the bean implementation class. This allows you to keep your application deployment-portable with the global Seam jndi-pattern
switch on <core:init/>
. Note that plain (non-Seam component) EJB resources will not be found even if scanning of resources is enabled, you always have to list them manually. Again, this whole paragraph is only relevant for EJB resources that are not also Seam components and that do not have an @Name
annotation.
Finally, you can configure media type and language URI extensions:
<resteasy:application> <resteasy:media-type-mappings> <key>txt</key> <value>text/plain</value> </resteasy:media-type-mappings> <resteasy:language-mappings> <key>deutsch</key><value>de-DE</value> </resteasy:language-mappings> </resteasy:application>
This definition would map the URI suffix of
.txt.deutsch
to the additional Accept
and Accept-Language
header values, text/plain
and de-DE
.