[jboss-cvs] JBossAS SVN: r101063 - projects/docs/enterprise/5.0.1/Seam_Reference_Guide/en-US.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed Feb 17 02:21:42 EST 2010


Author: laubai
Date: 2010-02-17 02:21:42 -0500 (Wed, 17 Feb 2010)
New Revision: 101063

Modified:
   projects/docs/enterprise/5.0.1/Seam_Reference_Guide/en-US/Book_Info.xml
   projects/docs/enterprise/5.0.1/Seam_Reference_Guide/en-US/Revision_History.xml
   projects/docs/enterprise/5.0.1/Seam_Reference_Guide/en-US/Webservices.xml
Log:
Partially corrected Architecture chapter.

Modified: projects/docs/enterprise/5.0.1/Seam_Reference_Guide/en-US/Book_Info.xml
===================================================================
--- projects/docs/enterprise/5.0.1/Seam_Reference_Guide/en-US/Book_Info.xml	2010-02-17 07:02:19 UTC (rev 101062)
+++ projects/docs/enterprise/5.0.1/Seam_Reference_Guide/en-US/Book_Info.xml	2010-02-17 07:21:42 UTC (rev 101063)
@@ -6,7 +6,7 @@
 	<title>Seam Reference Guide CP01</title>
 	<subtitle>for Use with JBoss Enterprise Application Platform 5.0 Cumulative Patch 1</subtitle>
 	<edition>2.0</edition>
-	<pubsnumber>1.1</pubsnumber>
+	<pubsnumber>1.2</pubsnumber>
 	<productname>JBoss Enterprise Application Platform</productname>
 	<productnumber>5.0</productnumber>
 <!--	<pubdate>Sep, 2007</pubdate> -->

Modified: projects/docs/enterprise/5.0.1/Seam_Reference_Guide/en-US/Revision_History.xml
===================================================================
--- projects/docs/enterprise/5.0.1/Seam_Reference_Guide/en-US/Revision_History.xml	2010-02-17 07:02:19 UTC (rev 101062)
+++ projects/docs/enterprise/5.0.1/Seam_Reference_Guide/en-US/Revision_History.xml	2010-02-17 07:21:42 UTC (rev 101063)
@@ -4,8 +4,8 @@
 
 <revhistory>
 	<revision>
-		<revnumber>1.1</revnumber>
-		<date>Mon Feb 15 2010</date>
+		<revnumber>1.2</revnumber>
+		<date>Wed Feb 17 2010</date>
 		<author>
 			<firstname>Laura</firstname>
 			<surname>Bailey</surname>
@@ -13,7 +13,7 @@
 		</author>
 		<revdescription>
 			<simplelist>
-				<member>Added RESTEasy section.</member>
+				<member>Updated RESTEasy section.</member>
 			</simplelist>
 		</revdescription>
 	</revision>

Modified: projects/docs/enterprise/5.0.1/Seam_Reference_Guide/en-US/Webservices.xml
===================================================================
--- projects/docs/enterprise/5.0.1/Seam_Reference_Guide/en-US/Webservices.xml	2010-02-17 07:02:19 UTC (rev 101062)
+++ projects/docs/enterprise/5.0.1/Seam_Reference_Guide/en-US/Webservices.xml	2010-02-17 07:21:42 UTC (rev 101063)
@@ -178,216 +178,693 @@
 	
 	 <section>
 		<title>RESTful HTTP webservices with RESTEasy</title>
-		 <para>
-			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:
-		</para>
-		 <itemizedlist>
-			<listitem>
-				<para>
-					RESTEasy bootstrap and configuration, with automatic resource detection. and providers.
-				</para>
-			</listitem>
-			 <listitem>
-				<para>
-					SeamResourceServlet-served HTTP/REST requests, without the need for an external servlet or configuration in <filename>web.xml</filename>.
-				</para>
-			</listitem>
-			 <listitem>
-				<para>
-					Resources written as Seam components with full Seam lifecycle management and bijection.
-				</para>
-			</listitem>
-		</itemizedlist>
-		 <section>
-			<title>RESTEasy configuration and request serving</title>
-			 <para>
-				First, download the RESTEasy libraries and the <filename>jaxrs-api.jar</filename>, and deploy them alongside the integration library (<filename>jboss-seam-resteasy.jar</filename>) and any other libraries your application requires.
+
+     <para>
+        Seam integrates the RESTEasy implementation of the JAX-RS specification (JSR 311). You can decide how
+        "deep" the integration into your Seam application is going to be:
+     </para>
+
+      <itemizedlist>
+         <listitem>
+            <para>
+               Seamless integration of RESTEasy bootstrap and configuration, automatic detection of resources
+               and providers.
+            </para>
+         </listitem>
+         <listitem>
+            <para>
+               Serving HTTP/REST requests with the <classname>SeamResourceServlet</classname>, no external servlet or configuration in
+               <filename>web.xml</filename> required.
+            </para>
+         </listitem>
+         <listitem>
+            <para>
+               Writing resources as Seam components, with full Seam lifecycle management and interception (bijection).
+            </para>
+         </listitem>
+      </itemizedlist>
+
+      <section>
+         <title>RESTEasy configuration and request serving</title>
+
+         <para>
+            First, get the RESTEasy libraries and the <filename>jaxrs-api.jar</filename> and deploy them with the
+            other libraries of your application. Also deploy the integration library,
+            <filename>jboss-seam-resteasy.jar</filename>.
+         </para>
+
+         <para>
+            On startup, all classes annotated <literal>@javax.ws.rs.Path</literal> will be discovered automatically
+            and registered as HTTP resources. Seam automatically accepts and serves HTTP requests with its built-in
+            <literal>SeamResourceServlet</literal>. The URI of a resource is build as follows:
+         </para>
+
+         <itemizedlist>
+             <listitem>
+                <para>
+                   The URI starts with the host and context path of your application,
+                    e.g. <literal>http://your.hostname/myapp</literal>.
+                </para>
+             </listitem>
+            <listitem>
+               <para>
+                  Then the pattern mapped in <filename>web.xml</filename> for the <classname>SeamResourceServlet</classname>,
+                   for example, <filename>/seam/resource</filename> if you follow the common examples, is appended.
+                  Change this setting to expose your RESTful resources under a different base.
+                  Note that this is a global change and other Seam resources (for example, <literal>s:graphicImage</literal>)
+                  are then also served under that base path.
+               </para>
+            </listitem>
+            <listitem>
+               <para>
+                  The RESTEasy integration for Seam then appends a configurable string to the base path, by default
+                  this is <filename>/rest</filename>. Hence, the full base path of your resources would e.g. be
+                  <filename>/myapp/seam/resource/rest</filename>. We recommend that you change this string in your application,
+                  you could for example add a version number to prepare for a future REST API upgrade of your services
+                  (old clients would keep the old URI base): <filename>/myapp/seam/resource/restv1</filename>.
+               </para>
+            </listitem>
+            <listitem>
+               <para>
+                  Finally, the actual resource is available under the defined <literal>@Path</literal>, for example, a resource
+                  mapped with <literal>@Path("/customer")</literal> would be available under
+                  <filename>/myapp/seam/resource/rest/customer</filename>.
+               </para>
+            </listitem>
+         </itemizedlist>
+
+         <para>
+            As an example, the following resource definition would return a plaintext representation for any
+            GET requests using the URI <filename>http://your.hostname/myapp/seam/resource/rest/customer/123</filename>:
+         </para>
+
+         <programlisting role="JAVA"><![CDATA[@Path("/customer")
+public class MyCustomerResource {
+
+    @GET
+    @Path("/{customerId}")
+    @Produces("text/plain")
+    public String getCustomer(@PathParam("customerId") int id) {
+         return ...;
+    }
+
+}]]></programlisting>
+
+         <para>
+            No additional configuration is required, you do not have to edit <literal>web.xml</literal> or any
+            other setting if these defauls are acceptable. However, you can configure RESTEasy in your Seam application.
+            First import the <literal>resteasy</literal> namespace into your XML configuration file header:
+         </para>
+
+         <programlisting role="XML"><![CDATA[<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">]]></programlisting>
+
+         <para>
+            You can then change the <filename>/rest</filename> prefix as mentioned earlier:
+         </para>
+
+         <programlisting role="XML"><![CDATA[<resteasy:application resource-path-prefix="/restv1"/>]]></programlisting>
+
+         <para>
+            The full base path to your resources is now <filename>/myapp/seam/resource/restv1/{resource}</filename> - note
+            that your <literal>@Path</literal> definitions and mappings do NOT change. This is an application-wide
+            switch usually used for versioning of the HTTP interface.
+         </para>
+
+         <para>
+            Seam will scan your classpath for any deployed <literal>@javax.ws.rs.Path</literal> resources and any
+            <literal>@javax.ws.rs.ext.Provider</literal> classes. You can disable scanning and configure these
+            classes manually:
+         </para>
+         
+         <programlisting role="XML"><![CDATA[<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>]]></programlisting>
+
+         <para>
+            The <literal>use-built-in-providers</literal> switch enables (default) or disables the RESTEasy built-in
+            providers. We recommend you leave them enabled, as they provide plaintext, JSON, and JAXB marshalling
+            out of the box.
+         </para>
+
+         <para>
+            RESTEasy supports plain EJBs (EJBs that are not Seam components) as resources. Instead of configuring the
+            JNDI names in a non-portable fashion in <filename>web.xml</filename> (see RESTEasy documentation), you can
+            simply list the EJB implementation classes, not the business interfaces, in <filename>components.xml</filename>
+            as shown above. Note that you have to annotate the <literal>@Local</literal> interface of the EJB with
+            <literal>@Path</literal>, <literal>@GET</literal>, and so on - not the bean implementation class. This allows
+            you to keep your application deployment-portable with the global Seam <literal>jndi-pattern</literal> switch
+            on <literal>&lt;core:init/&gt;</literal>. 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 <literal>@Name</literal> annotation.
+         </para>
+
+         <para>
+            Finally, you can configure media type and language URI extensions:
+         </para>
+
+         <programlisting role="XML"><![CDATA[<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>]]></programlisting>
+
+         <para>
+            This definition would map the URI suffix of <literal>.txt.deutsch</literal> to
+            additional <literal>Accept</literal> and <literal>Accept-Language</literal> header values
+            <literal>text/plain</literal> and <literal>de-DE</literal>.
+         </para>
+
+      </section>
+
+      <section>
+         <title>Resources as Seam components</title>
+
+         <para>
+            Any resource and provider instances are managed by RESTEasy by default. That means a resource class
+            will be instantiated by RESTEasy and serve a single request, after which it will be destroyed. This is
+            the default JAX-RS lifecycle. Providers are instantiated once for the whole application and are
+            effectively singletons and supposed to be stateless.
+         </para>
+
+         <para>
+            You can write resources as Seam components and benefit from the richer lifecycle management
+            of Seam, and interception for bijection, security, and so on. Simply make your resource class a
+            Seam component:
+         </para>
+
+         <programlisting role="JAVA"><![CDATA[@Name("customerResource")
+ at Path("/customer")
+public class MyCustomerResource {
+
+    @In
+    CustomerDAO customerDAO;
+
+    @GET
+    @Path("/{customerId}")
+    @Produces("text/plain")
+    public String getCustomer(@PathParam("customerId") int id) {
+         return customerDAO.find(id).getName();
+    }
+
+}]]></programlisting>
+
+         <para>
+            An instance of <literal>customerResource</literal> is now handled by Seam when a request hits the
+            server. This is a Seam JavaBean component that is <literal>EVENT</literal>-scoped, hence no different
+            than the default JAX-RS lifecycle. You get full Seam injection and interception support, and all other Seam
+            components and contexts are available to you. Currently also supported are <literal>APPLICATION</literal>
+            and <literal>STATELESS</literal> resource Seam components. These three scopes allow you to create an effectively
+            stateless Seam middle-tier HTTP request-processing application.
+         </para>
+
+         <para>
+            You can annotate an interface and keep the implementation free from JAX-RS annotations:
+         </para>
+
+         <programlisting role="JAVA"><![CDATA[@Path("/customer")
+public interface MyCustomerResource {
+
+    @GET
+    @Path("/{customerId}")
+    @Produces("text/plain")
+    public String getCustomer(@PathParam("customerId") int id);
+
+}]]></programlisting>
+
+         <programlisting role="JAVA"><![CDATA[@Name("customerResource")
+ at Scope(ScopeType.STATELESS)
+public class MyCustomerResourceBean implements MyCustomerResource {
+
+    @In
+    CustomerDAO customerDAO;
+
+    public String getCustomer(int id) {
+         return customerDAO.find(id).getName();
+    }
+
+}]]></programlisting>
+
+         <para>
+           You can use <literal>SESSION</literal>-scoped Seam components. By default, the session will however be shortened
+           to a single request. In other words, when an HTTP request is being processed by the RESTEasy integration code,
+           an HTTP session will be created so that Seam components can utilize that context. When the request has
+           been processed, Seam will look at the session and decide if the session was created only to serve that
+           single request (no session identifier has been provided with the request, or no session existed for the request).
+           If the session has been created only to serve this request, the session will be destroyed after the request!
+         </para>
+
+         <para>
+           Assuming that your Seam application only uses event, application, or stateless components, this procedure
+           prevents exhaustion of available HTTP sessions on the server. The RESTEasy integration with Seam assumes
+           by default that sessions are not used, hence anemic sessions would add up as every REST request would start
+           a session that will only be removed when timed out.
+         </para>
+
+         <para>
+            If your RESTful Seam application has to preserve session state across REST HTTP requests, disable this
+            behavior in your configuration file:
+         </para>
+
+         <programlisting role="XML"><![CDATA[<resteasy:application destroy-session-after-request="false"/>]]></programlisting>
+
+         <para>
+             Every REST HTTP request will now create a new session that will only be removed by timeout or explicit
+             invalidation in your code through <literal>Session.instance().invalidate()</literal>.
+             It is your responsibility to pass a valid session identifier along with your HTTP requests, if you want
+             to utilize the session context across requests.
+         </para>
+
+         <para>
+            <literal>CONVERSATION</literal>-scoped resource components and mapping of conversations to temporary HTTP
+            resources and paths is planned but currently not supported.
+         </para>
+
+         <para>
+            EJB Seam components are supported as REST resources. Always annotate the local business interface, not
+            the EJB implementation class, with JAX-RS annotations. The EJB has to be <literal>STATELESS</literal>.
+         </para>
+
+         <note>
+            <para>
+               Sub-resources as defined in the JAX RS specification, section 3.4.1, can not be Seam component instances
+               at this time. Only root resource classes can be registered as Seam components. In other words, do not
+               return a Seam component instance from a root resource method.
+            </para>
+         </note>
+
+         <note>
+            <para>
+                Provider classes can currently not be Seam components. Although you can configure an
+                <literal>@Provider</literal> annotated class as a Seam component, it will at runtime be managed
+                by RESTEasy as a singleton with no Seam interception, bijection, etc. The instance will not be
+                a Seam component instance. We plan to support Seam component lifecycle for JAX-RS providers in
+                the future.
+            </para>
+         </note>
+
+      </section>
+
+      <section>
+         <title>Securing resources</title>
+
+         <para>
+            You can enable the Seam authentication filter for HTTP Basic and Digest authentication in
+            <filename>components.xml</filename>:
+         </para>
+
+         <programlisting role="XML"><![CDATA[<web:authentication-filter url-pattern="/seam/resource/rest/*" auth-type="basic"/>]]></programlisting>
+
+         <para>
+            See the Seam security chapter on how to write an authentication routine.
+         </para>
+
+         <para>
+            After successful authentication, authorization rules with the common
+            <literal>@Restrict</literal> and <literal>@PermissionCheck</literal> annotations are in effect. You can
+            also access the client <literal>Identity</literal>, work with permission mapping, and so on. All
+            regular Seam security features for authorization are available.
+         </para>
+
+      </section>
+
+      <section>
+         <title>Mapping exceptions to HTTP responses</title>
+
+         <para>
+            Section 3.3.4 of the JAX-RS specification defines how checked or unchecked exceptions are handled by the
+            JAX RS implementation. In addition to using an exception mapping provider as defined by JAX-RS, the integration
+            of RESTEasy with Seam allows you to map exceptions to HTTP response codes within Seam's <filename>pages.xml</filename>
+            facility. If you are already using <filename>pages.xml</filename> declarations, this is easier to maintain than
+            potentially many JAX RS exception mapper classes.
+         </para>
+
+         <para>
+            Exception handling within Seam requires that the Seam filter is executed for your HTTP request. Ensure that
+            you do filter <emphasis>all</emphasis> requests in your <filename>web.xml</filename>, not - as
+            some Seam examples might show - a request URI pattern that doesn't cover your REST request paths.
+            The following example intercepts <emphasis>all</emphasis> HTTP requests and enables Seam exception handling:
+         </para>
+
+         <programlisting role="XML"><![CDATA[<filter>
+    <filter-name>Seam Filter</filter-name>
+    <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
+</filter>
+
+<filter-mapping>
+    <filter-name>Seam Filter</filter-name>
+    <url-pattern>/*</url-pattern>
+</filter-mapping>]]></programlisting>
+
+         <para>
+            To convert the unchecked <literal>UnsupportedOperationException</literal> thrown by your resource
+            methods to a <literal>501 Not Implemented</literal> HTTP status response, add the following to your
+            <filename>pages.xml</filename> descriptor:
+         </para>
+
+         <programlisting role="XML"><![CDATA[<exception class="java.lang.UnsupportedOperationException">
+    <http-error error-code="501">
+        <message>The requested operation is not supported</message>
+    </http-error>
+</exception>]]></programlisting>
+
+         <para>
+            Custom or checked exceptions are handled the same:
+         </para>
+
+         <programlisting role="XML"><![CDATA[<exception class="my.CustomException" log="false">
+    <http-error error-code="503">
+        <message>Service not available: #{org.jboss.seam.handledException.message}</message>
+    </http-error>
+</exception>]]></programlisting>
+
+         <para>
+            You do not have to send an HTTP error to the client if an exception occurs. Seam allows you to map the
+            exception as a redirect to a view of your Seam application. As this feature is typically used for human
+            clients (web browsers) and not for REST API remote clients, you should pay extra attention to conflicting
+            exception mappings in <filename>pages.xml</filename>.
+         </para>
+
+         <para>
+            Note that the HTTP response still passes through the servlet container, so an additional mapping might apply
+            if you have <literal>&lt;error-page&gt;</literal> mappings in your <filename>web.xml</filename> configuration.
+            The HTTP status code would then be mapped to a rendered HTML error page with status <literal>200 OK</literal>!
+         </para>
+
+      </section>
+
+      <section>
+         <title>Exposing entities via RESTful API</title>
+         
+         <para>
+            Seam makes it really easy to use a RESTful approach for accessing application data. One of the improvements that
+            Seam introduces is the ability to expose parts of your SQL database for remote access via plain HTTP calls.
+            For this purpose, the Seam/RESTEasy integration module provides two components: <literal>ResourceHome</literal> and
+            <literal>ResourceQuery</literal>, which benefit from the API provided by the Seam Application Framework
+            (<xref linkend="framework"/>). These components allow you to bind domain model entity classes to an HTTP API.
+         </para>
+         
+         <section>
+         	<title>ResourceQuery</title>
+         	
+         	<para>
+         		ResourceQuery exposes entity querying capabilities as a RESTful web service. By default, a simple
+         		underlying Query component, which returns a list of instances of a given entity class, is created automatically. 
+         		Alternatively, the ResourceQuery component can be attached to an existing Query component in more sophisticated 
+         		cases. The following example demonstrates how easily ResourceQuery can be configured:
+         	</para>
+         	
+         	<programlisting role="XML"><![CDATA[<resteasy:resource-query
+   path="/user"
+   name="userResourceQuery"
+   entity-class="com.example.User"/>]]></programlisting>
+         	
+         	<para>
+         		With this single XML element, a ResourceQuery component is set up. The configuration is straightforward:
+         	</para>
+         		
+         	<itemizedlist>
+         		<listitem>
+	           		<para>
+         	 			The component will return a list of <literal>com.example.User</literal> instances.
+         	 		</para>
+         	 	</listitem>
+           		<listitem>
+	           		<para>
+         	 			The component will handle HTTP requests on the URI path <filename>/user</filename>.
+         	 		</para>
+         	 	</listitem>
+         	 	<listitem>
+         	 		<para>
+         	 			The component will by default transform the data into XML or JSON (based on client's preference).
+         	 			The set of supported mime types can be altered by using the <varname>media-types</varname> attribute,
+                      for example:
+         	 		</para>
+         	 	</listitem>
+         	</itemizedlist>
+         	 
+         	 <programlisting role="XML"><![CDATA[<resteasy:resource-query
+   path="/user"
+   name="userResourceQuery"
+   entity-class="com.example.User"
+   media-types="application/fastinfoset"/>]]></programlisting>
+         	
+         	<para>	
+				Alternatively, if you do not like configuring components using XML, you can set up the component by extension:
 			</para>
-			 <para>
-				All classes annotated with <literal>@javax.ws.rs.Path</literal> will automatically be discovered and registered as HTTP resources at startup. Seam automatically accepts and serves HTTP requests with its built-in <literal>SeamResourceServlet</literal>. The URI of a resource is built like so:
+			
+			<programlisting role="JAVA"><![CDATA[@Name("userResourceQuery")
+ at Path("user")
+public class UserResourceQuery extends ResourceQuery<User>
+{
+}]]></programlisting>
+
+			<para>
+				Queries are read-only operations, the resource only responds to GET requests. Furthermore, ResourceQuery allows
+            clients  of a web service to manipulate the resultset of a query using the following path parameters:
 			</para>
-			 <itemizedlist>
-				<listitem>
-					<para>
-						The URI begins with the pattern mapped in <filename>web.xml</filename> for the <literal>SeamResourceServlet</literal> — in the examples provided, <literal>/seam/resource</literal>. Change this setting to expose your RESTful resources under a different base. Remember that this is a <emphasis>global</emphasis> change, and other Seam resources (<literal>s:graphicImage</literal>) will also be served under this base path.
-					</para>
-				</listitem>
-				 <listitem>
-					<para>
-						Seam&#39;s RESTEasy integration then appends a configurable string to the base path (<literal>/rest</literal> by default). So, in the example, the full base path of your resources would be <literal>/seam/resource/rest</literal>. 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.
-					</para>
-				</listitem>
-				 <listitem>
-					<para>
-						Finally, the resource is made available under the defined <literal>@Path</literal>. For example, a resource mapped with <literal>@Path("/customer")</literal> would be available under <literal>/seam/resource/rest/customer</literal>.
-					</para>
-				</listitem>
-			</itemizedlist>
-			 <para>
-				The following resource definition would return a plain text representation for any GET request using the URI <literal>http://your.hostname/seam/resource/rest/customer/123</literal>:
+			
+			<informaltable>
+				<tgroup cols='3'>
+					<thead>
+						<row>
+  							<entry>Parameter name</entry>
+  							<entry>Example</entry>
+  							<entry>Description</entry>
+						</row>
+					</thead>
+					<tbody>
+	         			<row>
+	         				<entry>start</entry>
+         					<entry>/user?start=20</entry>
+         					<entry>Returns a subset of a database query result starting with the 20th entry.</entry>
+         				</row>
+	         			<row>
+	         				<entry>show</entry>
+         					<entry>/user?show=10</entry>
+         					<entry>Returns a subset of the database query result limited to 10 entries.</entry>
+         				</row>
+         			</tbody>
+         		</tgroup>
+         	</informaltable>
+			
+			<para>
+				For example, you can send an HTTP GET request to <literal>/user?start=30&amp;show=10</literal> to get a list of
+            entries representing 10 rows starting with row 30.
 			</para>
-			 
-<programlisting role="JAVA"><![CDATA[@Path("/customer") 
-public class MyCustomerResource { 
-  @GET @Path("/{customerId}") @Produces("text/plain") 
-  public String getCustomer(@PathParam("customerId") int id) { 
-    return 
-    ...; 
-  } 
-}]]>
-</programlisting>
-			 <para>
-				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 <literal>resteasy</literal> namespace into your XML configuration file header:
+			
+			<note>
+            	<para>
+                	RESTEasy uses JAXB to marshall entities. Thus, in order to be able to transfer them over the wire, you
+                  need to annotate entity classes with <literal>@XMLRootElement</literal>. Consult the JAXB and
+                  RESTEasy documentation for more information.
+            	</para>
+         	</note>
+         
+         </section>
+         
+         <section>
+         
+         	<title>ResourceHome</title>
+         	
+         	<para>
+         		Just as ResourceQuery makes Query's API available for remote access, so does ResourceHome for the Home
+               component. The following table describes how the two APIs (HTTP and Home) are bound together.
+         	</para>
+         	
+         	<table>
+            <title>Bindings in ResourceHome</title>
+				    <tgroup cols='4'>
+					    <thead>
+						    <row>
+      							<entry>HTTP method</entry>
+      							<entry>Path</entry>
+      							<entry>Function</entry>
+      							<entry>ResourceHome method</entry>
+						    </row>
+					    </thead>
+					    <tbody>
+	             			<row>
+	             				<entry>GET</entry>
+             					<entry>{path}/{id}</entry>
+             					<entry>Read</entry>
+             					<entry>getResource()</entry>
+             				</row>
+	             			<row>
+	             				<entry>POST</entry>
+             					<entry>{path}</entry>
+             					<entry>Create</entry>
+             					<entry>postResource()</entry>
+             				</row>
+	             			<row>
+	             				<entry>PUT</entry>
+             					<entry>{path}/{id}</entry>
+             					<entry>Update</entry>
+             					<entry>putResource()</entry>
+             				</row>
+	             			<row>
+	             				<entry>DELETE</entry>
+             					<entry>{path}/{id}</entry>
+             					<entry>Delete</entry>
+             					<entry>deleteResource()</entry>
+             				</row>
+             			</tbody>
+             		</tgroup>
+             	</table>
+         	
+       		<itemizedlist>
+           		<listitem>
+              		<para>
+               			You can GET, PUT, and DELETE a particular user instance by sending HTTP requests to /user/{userId}
+               		</para>
+               	</listitem>
+               	<listitem>
+               		<para>
+               			Sending a POST request to <filename>/user</filename> creates a new user entity instance and persists it.
+                        Usually, you leave it up to the persistence layer to provide the entity instance with an identifier
+                        value and thus an URI. Therefore, the URI is sent back to the client in the
+                        <literal>Location</literal> header of the HTTP response.
+               		</para>
+               	</listitem>
+            </itemizedlist>
+         	
+         	<para>
+         		The configuration of ResourceHome is very similar to ResourceQuery except that you need to explicitly specify the underlying 
+         		Home component and the Java type of the entity identifier property.
+         	</para>
+         	
+         	<programlisting role="XML"><![CDATA[<resteasy:resource-home
+   path="/user"
+   name="userResourceHome"
+   entity-home="#{userHome}"
+   entity-id-class="java.lang.Integer"/>]]></programlisting>
+         	
+         	<para>Again, you can write a subclass of ResourceHome instead of XML:</para>
+         	
+         	<programlisting role="JAVA"><![CDATA[@Name("userResourceHome")
+ at Path("user")
+public class UserResourceHome extends ResourceHome<User, Integer>
+{
+
+   @In
+   private EntityHome<User> userHome;
+
+   @Override
+   public Home<?, User> getEntityHome()
+   {
+      return userHome;
+   }
+}]]></programlisting>
+
+			<para>
+				For more examples of ResourceHome and ResourceQuery components, take a look at the <emphasis>Seam Tasks</emphasis> 
+            example application, which demonstrates how Seam/RESTEasy integration can be used together with a jQuery web client.
+            In addition, you can find more code example in the <emphasis>Restbay</emphasis> example, which is used mainly
+            for testing purposes.
 			</para>
-			 
-<programlisting role="XML"><![CDATA[<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.1.xsd 
-               http://jboss.com/products/seam/components 
-               http://jboss.com/products/seam/components-2.1.xsd">]]>
-</programlisting>
-			 <para>
-				You can then edit the <literal>/rest</literal> prefix (as mentioned earlier) so that it is more descriptive:
-			</para>
-			 
-<programlisting role="XML"><![CDATA[<resteasy:application resource-path-prefix="/restv1"/>]]>
-</programlisting>
-			 <para>
-				The full base path to your resources is now <literal>/seam/resource/restv1/{resource}</literal>. Note that your <literal>@Path</literal> definitions and mappings do not change. This is an application-wide switch, usually used for versioning of the HTTP API.
-			</para>
-			 <para>
-				If you want to map the full path in your resources, you can disable base path stripping:
-			</para>
-			 
-<programlisting role="XML"><![CDATA[<resteasy:application strip-seam-resource-path="false"/>]]>
-</programlisting>
-			 <para>
-				Here, the path of a resource is now mapped with <literal>@Path("/seam/resource/rest/customer")</literal>. Disabling this feature binds your resource class mappings to a particular deployment scenario. This is <emphasis>not</emphasis> recommended.
-			</para>
-			 <para>
-				Seam scans your classpath for any deployed <literal>@javax.ws.rs.Path</literal> resources or <literal>@javax.ws.rs.ext.Provider</literal> classes. You can disable scanning and configure these classes manually like so:
-			</para>
-			 
-<programlisting role="XML"><![CDATA[<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> 
-  </resteasy:resource-class-names> 
-  <resteasy:provider-class-names> 
-    <value>org.foo.MyFancyProvider</value> 
-  </resteasy:provider-class-names> 
-</resteasy:application>]]>
-</programlisting>
-			 <para>
-				The <literal>use-built-in-providers</literal> switch enables (default) or disables the RESTEasy built-in providers. Since these provide plain text, JSON and JAXB marshalling, we recommend that these are left enabled.
-			</para>
-			 <para>
-				Finally, you can configure media type and language URI extensions:
-			</para>
-			 
-<programlisting role="XML"><![CDATA[<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>]]>
-</programlisting>
-			 <para>
-				This definition would map the URI suffix of <literal>.txt.deutsch</literal> to the additional <literal>Accept</literal> and <literal>Accept-Language</literal> header values, <literal>text/plain</literal> and <literal>de-DE</literal>.
-			</para>
-		</section>
-		
-		 <section>
-			<title>Resources and providers as Seam components</title>
-			 <para>
-				Resource and provider instances are, by default, managed by RESTEasy. A resource class will be instantiated by RESTEasy and serve a single request, after which it will be destroyed. This is the default JAX-RS lifecycle. Providers are instantiated once for the entire application. These are stateless singletons.
-			</para>
-			 <para>
-				Resources and providers can also be written as Seam components to take advantage of Seam&#39;s richer lifecycle management, and bijection and security abilities. Make your resource class into a Seam component like so:
-			</para>
-			 
-<programlisting role="JAVA"><![CDATA[@Name("customerResource") 
- at Path("/customer") 
-public class MyCustomerResource { 
-  @In CustomerDAO customerDAO; 
-  @GET @Path("/{customerId}") 
-  @Produces("text/plain") 
-  public String getCustomer(@PathParam("customerId") int id) { 
-    return customerDAO.find(id).getName(); 
-  } 
-}]]>
-</programlisting>
-			 <para>
-				A <literal>customerResource</literal> instance is now handled by Seam when a request hits the server. This component is event-scoped, so its lifecycle is identical to that of the JAX-RS. However, the Seam JavaBean component gives you full injection support, and full access to all other components and contexts. Session, application, and stateless resource components are also supported. Remember that any HTTP request must transmit a valid session identifier — a cookie, or URI path parameter — for the server-side session context to be handled correctly.
-			</para>
-			 <para>
-				Conversation-scoped resource components and conversation mapping are not currently supported, but are planned for future versions of Seam.
-			</para>
-			 <para>
-				Provider classes can also be Seam components. They must be either application-scoped or stateless.
-			</para>
-			 <para>
-				Resources and providers can be EJBs or JavaBeans, like any other Seam component.
-			</para>
-		</section>
-		
-		 <section>
-			<title>Mapping exceptions to HTTP responses</title>
-			 <para>
-				Section 3.3.4 of the JAX-RS specification defines how JAX RS handles checked and unchecked exceptions. Integrating RESTEasy with Seam allows you to map exceptions to HTTP response codes within Seam&#39;s <filename>pages.xml</filename>. If you use <filename>pages.xml</filename> already, this is easier to maintain than many JAX RS exception mapper classes.
-			</para>
-			 <para>
-				Forexceptions to be handled within Seam, the Seam filter must be executed for your HTTP request. You must filter all requests in your <filename>web.xml</filename>, <emphasis>not</emphasis> as a request URI pattern that does not cover your REST requests. The following example intercepts all HTTP requests and enables Seam exception handling:
-			</para>
-			 
-<programlisting role="XML"><![CDATA[<filter> 
-  <filter-name>Seam Filter</filter-name> 
-  <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class> 
-</filter> 
+         	
+         </section>
+               
+      </section>
 
-<filter-mapping> 
-  <filter-name>Seam Filter</filter-name> 
-  <url-pattern>/*</url-pattern> 
-</filter-mapping>]]>
-</programlisting>
-			 <para>
-				To convert the unchecked <literal>UnsupportedOperationException</literal> thrown by your resource methods to a <literal>501 Not Implemented</literal> HTTP status response, add the following to your <filename>pages.xml</filename> descriptor:
-			</para>
-			 
-<programlisting role="XML"><![CDATA[<exception class="java.lang.UnsupportedOperationException"> 
-  <http-error error-code="501"> 
-    <message>The request operation is not supported</message> 
-  </http-error> 
-</exception>]]>
-</programlisting>
-			 <para>
-				Custom or checked exceptions are handled in the same way:
-			</para>
-			 
-<programlisting role="XML"><![CDATA[<exception class="my.CustomException" log="false"> 
-  <http-error error-code="503"> 
-    <message>
-      The service is currently not available: #{org.jboss.seam.handledException.message}
-    </message> 
-  </http-error> 
-</exception>]]>
-</programlisting>
-			 <para>
-				You do not have to send a HTTP error to the client if an exception occurs. Seam lets you map the exception as a redirect to a view of your Seam application. Since this feature is typically used for human clients (web browsers) and not for REST API remote clients, you should pay attention to conflicting exception mappings in <filename>pages.xml</filename>.
-			</para>
-			 <para>
-				The HTTP response does pass through the servlet container, so an additional mapping may apply if you have <literal><![CDATA[<error-page>]]></literal> mappings in your <literal>web.xml</literal> configuration. The HTTP status code would then be mapped to a rendered HTML error page with status <literal>200 OK</literal>.
-			</para>
-		</section>
+      <section>
+         <title>Testing resources and providers</title>
+         
+         <para>
+            Seam includes a unit testing utility class that helps you create unit tests for a RESTful
+            architecture. Extend the <literal>SeamTest</literal> class as usual and use the
+            <literal>ResourceRequestEnvironment.ResourceRequest</literal> to emulate HTTP requests/response cycles:
+         </para>
+      
+         <programlisting role="JAVA"><![CDATA[import org.jboss.seam.mock.ResourceRequestEnvironment;
+import org.jboss.seam.mock.EnhancedMockHttpServletRequest;
+import org.jboss.seam.mock.EnhancedMockHttpServletResponse;
+import static org.jboss.seam.mock.ResourceRequestEnvironment.ResourceRequest;
+import static org.jboss.seam.mock.ResourceRequestEnvironment.Method;
+
+public class MyTest extends SeamTest {
+
+   ResourceRequestEnvironment sharedEnvironment;
+
+   @BeforeClass
+   public void prepareSharedEnvironment() throws Exception {
+       sharedEnvironment = new ResourceRequestEnvironment(this) {
+            @Override
+            public Map<String, Object> getDefaultHeaders() {
+               return new HashMap<String, Object>() {{
+                   put("Accept", "text/plain");
+               }};
+            }
+         };
+   }
+
+   @Test
+   public void test() throws Exception
+   {
+      //Not shared: new ResourceRequest(new ResourceRequestEnvironment(this), Method.GET, "/my/relative/uri)
+
+      new ResourceRequest(sharedEnvironment, Method.GET, "/my/relative/uri)
+      {
+         @Override
+         protected void prepareRequest(EnhancedMockHttpServletRequest request)
+         {
+            request.addQueryParameter("foo", "123");
+            request.addHeader("Accept-Language", "en_US, de");
+         }
+
+         @Override
+         protected void onResponse(EnhancedMockHttpServletResponse response)
+         {
+            assert response.getStatus() == 200;
+            assert response.getContentAsString().equals("foobar");
+         }
+
+      }.run();
+   }
+}]]></programlisting>
+
+         <para>
+            This test only executes local calls, it does not communicate with the <literal>SeamResourceServlet</literal>
+            through TCP. The mock request is passed through the Seam servlet and filters and the response is then
+            available for test assertions. Overriding the <methodname>getDefaultHeaders()</methodname> method in a shared
+            instance of <literal>ResourceRequestEnvironment</literal> allows you to set request headers for every
+            test method in the test class.
+         </para>
+
+         <para>
+            Note that a <literal>ResourceRequest</literal> has to be executed in a <literal>@Test</literal> method
+            or in a <literal>@BeforeMethod</literal> callback. You can not execute it in any other callback,
+            such as <literal>@BeforeClass</literal>.
+         </para>
+
+      </section>
 		
 	</section>
 </chapter>
-




More information about the jboss-cvs-commits mailing list