cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache CXF Documentation > JAX-RS Redirection
Date Thu, 25 Oct 2012 15:45:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2042/9/1/_/styles/combined.css?spaceKey=CXF20DOC&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+Redirection">JAX-RS
Redirection</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~sergey_beryozkin">Sergey
Beryozkin</a>
    </h4>
        <br/>
                         <h4>Changes (1)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >At the moment, this provider is statically
configured to support text/html content types, but it can be easily configured to support
other content types if needed.   <br> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">In
addition to &#39;resourcePath&#39; and &#39;dispatcherName&#39; properties,
one can set a &#39;scope&#39; property which has two possible values, &#39;request&#39;
and &#39;session&#39; with &#39;request&#39; being the default value. It affects
the way the JSP code can retrieve parameters passed to it by the RequestDispatcherProvider.
If it is a &#39;request&#39; scope then all the parameters are set as the attributes
on the current HTTP request.  If session scope then they&#39;re set as the attributes
on the current HTTP session. <br> <br>{{RequestDispatcherProvider}} sets the following
parameters : <br> <br>- JAXRS method response object.  The name of this parameter
is either a simple class name of this object (lower case) or a value retrieved from a beanNames
map property using the fully qualified class name of this object. <br>- All the path,
query and matrix parameters which have been initialized during the method execution <br>-
&quot;absolute.path&quot;, &quot;base.path&quot; and &quot;relative.path&quot;
obtained from the current UriInfo <br> <br> <br></td></tr>
            <tr><td class="diff-unchanged" >Here are some examples. Lets assume
we have a book.war web application deployed. <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <p><span style="font-size:2em;font-weight:bold"> JAX-RS : Redirection
</span></p>

<div>
<ul>
    <li><a href='#JAX-RSRedirection-WithRequestDispatcherProvider'>With RequestDispatcherProvider</a></li>
<ul>
    <li><a href='#JAX-RSRedirection-Loggingredirects'>Logging redirects</a></li>
</ul>
    <li><a href='#JAX-RSRedirection-WithCXFServlet'>With CXFServlet</a></li>
    <li><a href='#JAX-RSRedirection-CustomRedirection'>Custom Redirection</a></li>
</ul></div>

<h1><a name="JAX-RSRedirection-WithRequestDispatcherProvider"></a>With RequestDispatcherProvider</h1>

<p><a href="http://svn.apache.org/repos/asf/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/RequestDispatcherProvider.java"
class="external-link" rel="nofollow">RequestDispatcherProvider</a> is a JAXRS MessageBodyWriter
which can redirect to JSP pages, named or default servlets. It can be used to serve all the
responses from a given resource class or restricted to serving a limited set of classes only
using a classResources map property.</p>

<p>Starting from CXF 2.5.0 and 2.4.4 it is also possible to specify that only responses
to requests with matching URIs that will be processed.</p>

<p>At the moment, this provider is statically configured to support text/html content
types, but it can be easily configured to support other content types if needed.  </p>

<p>In addition to 'resourcePath' and 'dispatcherName' properties, one can set a 'scope'
property which has two possible values, 'request' and 'session' with 'request' being the default
value. It affects the way the JSP code can retrieve parameters passed to it by the RequestDispatcherProvider.
If it is a 'request' scope then all the parameters are set as the attributes on the current
HTTP request.  If session scope then they're set as the attributes on the current HTTP session.</p>

<p><tt>RequestDispatcherProvider</tt> sets the following parameters :</p>

<ul class="alternate" type="square">
	<li>JAXRS method response object.  The name of this parameter is either a simple class
name of this object (lower case) or a value retrieved from a beanNames map property using
the fully qualified class name of this object.</li>
	<li>All the path, query and matrix parameters which have been initialized during the
method execution</li>
	<li>"absolute.path", "base.path" and "relative.path" obtained from the current UriInfo</li>
</ul>



<p>Here are some examples. Lets assume we have a book.war web application deployed.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;jaxrs:server id=<span class="code-quote">"bookservice1"</span>
address=<span class="code-quote">"/bookstore1"</span>&gt;</span>
    <span class="code-tag">&lt;jaxrs:serviceBeans&gt;</span>
      <span class="code-tag">&lt;bean class=<span class="code-quote">"org.apache.cxf.systest.jaxrs.BookStoreDispatch"</span>/&gt;</span>
    <span class="code-tag">&lt;/jaxrs:serviceBeans&gt;</span>		  
    <span class="code-tag">&lt;jaxrs:providers&gt;</span>
       <span class="code-tag">&lt;ref bean=<span class="code-quote">"dispatchProvider"</span>/&gt;</span>
    <span class="code-tag">&lt;/jaxrs:providers&gt;</span> 
<span class="code-tag">&lt;/jaxrs:server&gt;</span>

<span class="code-tag">&lt;bean id=<span class="code-quote">"dispatchProvider"</span>
class=<span class="code-quote">"org.apache.cxf.jaxrs.provider.RequestDispatcherProvider"</span>&gt;</span>
      <span class="code-tag">&lt;property name=<span class="code-quote">"resourcePath"</span>
value=<span class="code-quote">"/book.html"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

</pre>
</div></div>

<p>The above redirects the response to a default book.html page which is available directly
in the /webapps/book folder. Typically one would do it to return some static confirmation
to the client. For example, consider a POST form request that has been processed by a given
JAX-RS method and the only thing that needs to be done now is to return the HTML confirmation
view. Note that JAX-RS MessageBodyWriters are not invoked if the resource method returns no
custom object - which is not needed in the case of the static confirmation, so for RequestDispatcherProvider
be able to redirect to book.html one should simply introduce say an EmptyConfirmation bean
with no properties and return it from the resource method.</p>

<p>Here is another example (omitting jaxrs:server declaration for brewity):</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">

<span class="code-tag">&lt;bean id=<span class="code-quote">"dispatchProvider"</span>
class=<span class="code-quote">"org.apache.cxf.jaxrs.provider.RequestDispatcherProvider"</span>&gt;</span>
      <span class="code-tag">&lt;property name=<span class="code-quote">"resourcePath"</span>
value=<span class="code-quote">"/book.jsp"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

</pre>
</div></div>

<p>The only difference from the previous example is that "/book.jsp" will be delegated
to with the task of creating a view. This is a more interesting example and we presume that
the resource method returns say an instance of the "org.bar.Book" bean:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
@Path(<span class="code-quote">"/books"</span>)
<span class="code-keyword">public</span> Resource {
    @GET
    @Produces({<span class="code-quote">"text/html"</span>, <span class="code-quote">"application/xml"</span>})
    @Path(<span class="code-quote">"{id}"</span>)
    <span class="code-keyword">public</span> Book getBook(@PathParam(<span
class="code-quote">"id"</span>) <span class="code-object">String</span>
id) {
        <span class="code-comment">// <span class="code-keyword">return</span>
the book
</span>    }
}
</pre>
</div></div>

<p>Note how non-intrusive RequestDispatcherProvider is as far as writing the JAX-RS
resource code is concerned, you simply list supported media types in @Produces as usual. </p>

<p>RequestDispatcherProvider will make an instance of Book available as an HttpServletRequest
attribute named "org.bar.Book" by default. this can be customized. If a "beanName" property
is set, for example to "book", then book.jsp will access a Book instance as a "book" attribute.
If you have say 2 resource methods returning instances of different bean classes, possibly
for different view handlers then a beanNames map property can be used, for example: </p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">

<span class="code-tag">&lt;bean id=<span class="code-quote">"dispatchProvider"</span>
class=<span class="code-quote">"org.apache.cxf.jaxrs.provider.RequestDispatcherProvider"</span>&gt;</span>
      <span class="code-tag">&lt;property name=<span class="code-quote">"classResources"</span>&gt;</span>
          <span class="code-tag">&lt;map&gt;</span>
             <span class="code-tag">&lt;entry key=<span class="code-quote">"org.bar.Book"</span>
 value=<span class="code-quote">"/book.jsp"</span>/&gt;</span>
             <span class="code-tag">&lt;entry key=<span class="code-quote">"org.bar.Customer"</span>
 value=<span class="code-quote">"/customer.jsp"</span>/&gt;</span>
          <span class="code-tag">&lt;/map&gt;</span>
      <span class="code-tag">&lt;/property&gt;</span>
      <span class="code-tag">&lt;property name=<span class="code-quote">"beanNames"</span>&gt;</span>
          <span class="code-tag">&lt;map&gt;</span>
             <span class="code-tag">&lt;entry key=<span class="code-quote">"org.bar.Book"</span>
 value=<span class="code-quote">"book"</span>/&gt;</span>
             <span class="code-tag">&lt;entry key=<span class="code-quote">"org.bar.Customer"</span>
 value=<span class="code-quote">"customer"</span>/&gt;</span>
          <span class="code-tag">&lt;/map&gt;</span>
      <span class="code-tag">&lt;/property&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

</pre>
</div></div>

<p>The above configuration says that a "book.jsp" resource will handle an instance of
Book by accessing it as a "book" attribute and a "customer.jsp" - an instance of Customer
by retrieving it as a "customer" attribute. Note you don't need to use the "beanNames" property
in such cases, a simpler "beanName" property can do unless you have a single (jsp) resource
dealing with both Book and Customer. </p>

<p>Apart from making an instance of response class available as HttpServletRequest attribute,
RequestDispatcherProvider will also make all the Path, Query and Matrix parameters available
as HttpServletRequest parameters (as opposed to attributes) by default. For example, given
the above code fragment, an HttpServletRequest parameter named "id" representing a @PathParam("id")
available to the view handler, as well as all other query and matrix parameters.<br/>
Note that RequestDispatcherProvider can be configured to save all these request parameters
as HttpServletRequest attributes by setting a boolean saveParametersAsAttributes property
to true. </p>

<p>Now, imagine a scenario like this: we have two resource methods returning a ReservationStatus
bean. The first method returns a successful confirmation or uses Response.seeOther(...) to
redirect to a method handling the failed reservation. So both methods return the same ReservationStatus
bean but we will have two different views handling successful and failed reservations respectively.
Here is one way to manage it:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;bean id=<span class="code-quote">"reserveRegistrationViews"</span>
class=<span class="code-quote">"org.apache.cxf.jaxrs.provider.RequestDispatcherProvider"</span>&gt;</span>
         <span class="code-tag">&lt;property name=<span class="code-quote">"resourcePaths"</span>&gt;</span>
            <span class="code-tag">&lt;map&gt;</span>
              <span class="code-tag">&lt;entry key=<span class="code-quote">"/reservations/reserve/complete"</span>
value=<span class="code-quote">"/forms/reservationConfirm.jsp"</span>/&gt;</span>
              <span class="code-tag">&lt;entry key=<span class="code-quote">"/reservations/reserve/failure"</span>
value=<span class="code-quote">"/forms/reservationFailure.jsp"</span>/&gt;</span>
            <span class="code-tag">&lt;/map&gt;</span>
         <span class="code-tag">&lt;/property&gt;</span>
         <span class="code-tag">&lt;property name=<span class="code-quote">"beanName"</span>
value=<span class="code-quote">"data"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>
</pre>
</div></div>

<p>Given that the same ReservationStatus bean is returned in both cases, it is actually
the original request URI fragments which are used to match which view handler will deal with
a given ReservationStatus.</p>

<p>Note that RequestDispatcherProvider has a 'dispatcherName' property - that can be
handy when redirecting to named servlets (example, MyServlet) including<br/>
such ones as "jsp" or "default", especially when CXFServlet handling a given invocation has
a uri pattern that may also capture the redirection requestwell-known servlets such as "default",
see the next section for more information. </p>

<p>Starting from CXF 2.6.1 it is possible to configure the provider to check if the
current class has an associated view handler or not, for example:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;bean id=<span class="code-quote">"viewHandler"</span>
class=<span class="code-quote">"org.apache.cxf.jaxrs.provider.RequestDispatcherProvider"</span>&gt;</span>
         <span class="code-tag">&lt;property name=<span class="code-quote">"dispatcherName"</span>
value=jsp""/&gt;</span>
         <span class="code-tag">&lt;property name=<span class="code-quote">"useClassNames"</span>
value=<span class="code-quote">"true"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>
</pre>
</div></div>

<p>For example, given a simple class name such as "BookInfo", RequestDispatcherProvider
will check if a "/WEB-INF/bookInfo.jsp" handler is available or not. The provider will likely
be extended to check few more locations as needed.  </p>

<p>Finally, a 'servletContextPath' property can be used to have some other ServletContext
(as opposed to the current one) be used for RequestDispatcher look-ups. If set then the current
ServletContext.getContext(servletContextPath) will be used to get the needed ServletContext.</p>

<h2><a name="JAX-RSRedirection-Loggingredirects"></a>Logging redirects</h2>

<p>To get RequestDispatcherProvider log the information about redirects, please set
a 'logRedirects' property:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;bean id=<span class="code-quote">"reserveRegistrationViews"</span>
class=<span class="code-quote">"org.apache.cxf.jaxrs.provider.RequestDispatcherProvider"</span>&gt;</span>
         <span class="code-tag">&lt;property name=<span class="code-quote">"logRedirects"</span>
value=<span class="code-quote">"true"</span>/&gt;</span>
         <span class="code-tag"><span class="code-comment">&lt;!-- other properties
as needed --&gt;</span></span> 
<span class="code-tag">&lt;/bean&gt;</span>
</pre>
</div></div>

<p>You will see the logging entry like this one:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
23-Jul-2012 11:26:13 org.apache.cxf.jaxrs.provider.RequestDispatcherProvider logRedirection

INFO: Setting an instance of <span class="code-quote">"oauth2.common.ConsumerRegistration"</span>
as HttpServletRequest attribute <span class="code-quote">"newClient"</span> and
redirecting the response to <span class="code-quote">"/forms/registerAppConfirm.jsp"</span>
</pre>
</div></div>

<h1><a name="JAX-RSRedirection-WithCXFServlet"></a>With CXFServlet</h1>

<p>Please see the "Redirection" section on the <a href="/confluence/display/CXF20DOC/Servlet+Transport"
title="Servlet Transport">Servlet Transport</a> page.</p>

<p>Note that both CXFServlet and JAXRS RequestDispatcherProvider can work together effectively
on executing the redirection requests as described at that page.</p>

<p>If CXFServlet URI pattern does not match the resource URIs RequestDispatcherProvider
is redirecting to then there's nothing to worry about. </p>

<p>If you have CXFServlet listening on "/" (thus effectively catching all the requests)
and also would like to use RequestDispatcherProvider, then make sure that a 'dispatcherName'
property is also set, for example:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;bean id=<span class="code-quote">"dispatchProvider"</span>
class=<span class="code-quote">"org.apache.cxf.jaxrs.provider.RequestDispatcherProvider"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"dispatcherName"</span>
value=<span class="code-quote">"jsp"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"resourcePath"</span>
value=<span class="code-quote">"/WEB-INF/jsp/test.jsp"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span> 
</pre>
</div></div>

<p>If resources which are redirected to can be made public (i.e, moved out of /WEB-INF)
then alternative option (instead of adding a 'dispatcherName' property to RequestDispatcherProvider
and still have CXFServlet listening on '/') is to configure both RequestDispatcherProvider
and CXFServlet to redirect to resources such as "/jsp/test.jsp". </p>

<p>Also if you have many public view handlers then rather than having a "dispatcherName"
property set on every dispatcher bean, you can get it set only once on CXFServlet:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;servlet&gt;</span>
        <span class="code-tag">&lt;servlet-name&gt;</span>RESTServlet<span
class="code-tag">&lt;/servlet-name&gt;</span>
        <span class="code-tag">&lt;servlet-class&gt;</span>org.apache.cxf.transport.servlet.CXFServlet<span
class="code-tag">&lt;/servlet-class&gt;</span>
        <span class="code-tag">&lt;init-param&gt;</span>
    	   <span class="code-tag">&lt;param-name&gt;</span>redirects-list<span
class="code-tag">&lt;/param-name&gt;</span>
	   <span class="code-tag">&lt;param-value&gt;</span>/forms/.*<span
class="code-tag">&lt;/param-value&gt;</span>
	<span class="code-tag">&lt;/init-param&gt;</span>
	<span class="code-tag">&lt;init-param&gt;</span>
    	   <span class="code-tag">&lt;param-name&gt;</span>redirect-servlet-name<span
class="code-tag">&lt;/param-name&gt;</span>
	   <span class="code-tag">&lt;param-value&gt;</span>jsp<span class="code-tag">&lt;/param-value&gt;</span>
	<span class="code-tag">&lt;/init-param&gt;</span>
	<span class="code-tag">&lt;load-on-startup&gt;</span>1<span class="code-tag">&lt;/load-on-startup&gt;</span>
    <span class="code-tag">&lt;/servlet&gt;</span>
    <span class="code-tag">&lt;servlet-mapping&gt;</span>
        <span class="code-tag">&lt;servlet-name&gt;</span>RESTServlet<span
class="code-tag">&lt;/servlet-name&gt;</span>
        <span class="code-tag">&lt;url-pattern&gt;</span>/*<span class="code-tag">&lt;/url-pattern&gt;</span>
    <span class="code-tag">&lt;/servlet-mapping&gt;</span>
</pre>
</div></div>

<p>Here we have all the requests targeted at /form/* (example, /form/book.jsp, etc)
handled by a jsp handler.</p>


<h1><a name="JAX-RSRedirection-CustomRedirection"></a>Custom Redirection</h1>

<p>One can borrow some of the code from RequestDispatcherProvider and do the custom
redirection from CXF in interceptors or custom invokers, if you will try to do it then you
will also need to set an AbstractHTTPDestination.REQUEST_REDIRECTED property with a 'true'
value on a current input message.</p>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+Redirection">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=24190950&revisedVersion=8&originalVersion=7">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+Redirection?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message