cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache CXF > REST Support
Date Fri, 14 Aug 2009 14:00:00 GMT
<html>
<head>
    <base href="http://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/1519/1/11/_/styles/combined.css?spaceKey=CXF&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background-color: white" bgcolor="white">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
     <h2><s>REST Support</s></h2>
     <h4>Page <b>removed</b> by             <a href="http://cwiki.apache.org/confluence/display/~dkulp">Daniel
Kulp</a>
    </h4>
     <br/>
     <div class="notificationGreySide">
         <h1><a name="RESTSupport-RESTDesign"></a>REST Design</h1>


<h3><a name="RESTSupport-GoalsandNonGoals%3A"></a>Goals and Non-Goals:</h3>

<ul>
	<li>Support "plain old XML" interaction with services using REST Read and Update. REST
Create and Delete are not supported at this moment.</li>
	<li>The key idea of REST is "few verbs", thus there is a mapping between REST verbs
(CRUD) and backend service operations. There are two strategies we may consider:</li>
</ul>




<ol>
	<li>Using the protocol method to describe the verb. For example, <a href="http://xxx.com/customers/ABC"
rel="nofollow">http://xxx.com/customers/ABC</a> returns a Customer instance whose
id is ABC.</li>
	<li>Encoding the verb as part of the URI, the service interprets the verb in the URI
as the action to perform. For example, <a href="http://xxx.com/customers/getCustomer" rel="nofollow">http://xxx.com/customers/getCustomer</a>
is interpreted as performing getCustomer operation, the result is returning a Customer instance,
who is identified by the parameters sent by the request.</li>
</ol>




<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For the first cut, we would prefer
to implement the latter in the interest of simplicity.</p>
<ul>
	<li>Client side REST support:  REST service can be accessed from web browsers. We also
need to provide client side programming APIs to access REST service. In CXF, the client programming
APIs will be JAX-WS style.</li>
	<li>Server side REST support: Users need to be able to write a new REST service in
CXF or expose an existing CXF service as REST service without any changes (or with minimal
changes). The support for existing services will include services based on SOAP binding and
XML binding.</li>
</ul>


<h3><a name="RESTSupport-Scenarios%3A"></a>Scenarios:</h3>

<p>The request <a href="http://xxx.com/customerservice/getCustomers" rel="nofollow">http://xxx.com/customerservice/getCustomers</a>
maps to getCustomers method, returns a list of URIs to the customer.</p>

<p>The request <a href="http://xxx.com/customerservice/getCustomer" rel="nofollow">http://xxx.com/customerservice/getCustomer</a>
maps to getCustomer(String id) method, the parameter id is decoded either from HTTP get parameters
(in this case, can only support simple types) or from HTTP POST as parameters of the Web service.</p>

<p>The request <a href="http://xxx.com/customerservice/updateCustomer" rel="nofollow">http://xxx.com/customerservice/updateCustomer</a>
maps to updateCustomers(String, id, Customer data). Parameters are from HTTP POST as parameters
of the Web service.</p>

<p>To allow non-CXF clients access CXF REST services, the HTTP message exchanged on
the wire should confirm to the example below. </p>

<p>READ:</p>

<p>Request:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
POST /customerservice/getCustomer HTTP/1.0
Connection: close
Content-Type: text/xml
Content-Length: 620
Pragma: no-cache

&lt;tns:Customer xmlns:tns=<span class="code-quote">"urn:Customer"</span>&gt;
&lt;CustomerID&gt;ABC&lt;/CustomerID&gt;
&lt;/tns:Customer&gt;
</pre>
</div></div>
<p>Response:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
HTTP/1.1 200 OK
X-Powered-By: Servlet/2.5
Content-Type: text/xml
Connection: close

&lt;?xml version=<span class="code-quote">"1.0"</span> encoding=<span class="code-quote">"UTF-8"</span>?&gt;
&lt;tns:Customer xmlns:tns=<span class="code-quote">"urn:Customer"</span>&gt;
  &lt;CustomerName&gt;John&lt;/CustomerName&gt;
  &lt;CustomerID&gt;ABC&lt;/CustomerID&gt;
&lt;/tns:Customer&gt;
</pre>
</div></div>

<p>Update:</p>

<p>Request:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
POST /customerservice/updateCustomer HTTP/1.0
Connection: close
Content-Type: text/xml
Content-Length: 620
Pragma: no-cache

&lt;tns:Customer xmlns:tns=<span class="code-quote">"urn:Customer"</span>&gt;
  &lt;CustomerName&gt;John&lt;/CustomerName&gt;
  &lt;CustomerID&gt;ABC&lt;/CustomerID&gt;
&lt;/tns:Customer&gt;
</pre>
</div></div>

<p>Response:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
HTTP/1.1 200 OK
X-Powered-By: Servlet/2.5
Content-Type: text/xml

&lt;tns:Customer xmlns:tns=<span class="code-quote">"urn:Customer"</span>&gt;
  &lt;CustomerName&gt;John&lt;/CustomerName&gt;
  &lt;CustomerID&gt;ABC&lt;/CustomerID&gt;
&lt;/tns:Customer&gt;
</pre>
</div></div>

<h3><a name="RESTSupport-Implementations%3A"></a>Implementations: </h3>

<p>I propose we implement REST as a binding in CXF. The REST binding should look very
similar to the XML binding.</p>

<ul>
	<li>REST verbs to service operation mapping:</li>
</ul>


<p>As mentioned early, we choose to implement the verb as part of the URI (i.e., use
<a href="http://xxx.com/customers/getCustomer" rel="nofollow">http://xxx.com/customers/getCustomer</a>).
 To implement this, we adopt the approaches discussed in Tuscany mailing list <a href="/confluence/pages/createpage.action?spaceKey=CXF&amp;title=1&amp;linkCreation=true&amp;fromPageId=23580"
class="createlink">1</a>. Two approaches can be taken:</p>


<p><b>Annotation driven state-change -&gt; method mapping:</b></p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  @Remotable
  <span class="code-keyword">public</span> <span class="code-keyword">interface</span>
CustomersService {

     @RESTMethod(RestMethods.READ)
     @RESTBaseURIContext(<span class="code-quote">"/customerservice"</span>)
     <span class="code-object">String</span> getCustomers()
     {
       <span class="code-keyword">return</span> all customers 
     }

     @RESTMethod(RestMethods.READ)
     @RESTBaseURIContext(<span class="code-quote">"/customerservice"</span>)
     <span class="code-object">String</span> getCustomer(<span class="code-object">String</span>
customerID)
     {
       get the customer using customer ID
     }

     @RESTMethod(RestMethods.UPDATE)
     @RESTBaseURIContext(<span class="code-quote">"/customerservice"</span>)
     <span class="code-object">String</span> UpdateCustomers(<span class="code-object">String</span>
customerID, Customer data)
     {
       update customer data
     }
  }
</pre>
</div></div>

<p><b>Fixed method names for the REST operations:</b></p>

<p>If there is no annotation in the code, then we have to stick to the fixed pattern
with fixed method names. The URL pattern for method getFoo is something like <a href="http://localhost/baseURI/getFoo"
rel="nofollow">http://localhost/baseURI/getFoo</a>. In this case, we need a configuration
to: </p>

<p>1.	Specify the base URI context. This is done by specifying the http:address in wsdl
port, e.g., &lt;http:address location="http://localhost:9000/baseURI "/&gt; <br/>
2.	Specify which methods are REST operations. Or by default, all methods in SEI (and the invoke
method in provider) are restful methods. </p>

<p>In the short term, we probably won't go that far to invent annotations for REST.
We will be ok with the second approach.</p>


<ul>
	<li>Parameter passing using HTTP GET and POST.</li>
</ul>


<p>When using HTTP GET, input parameters are encoded into URL.  There are two most commonly
used patterns:</p>

<p><a href="http://localhost:8080/customerservice/addnumbers/num1/10/num2/20" rel="nofollow">http://localhost:8080/customerservice/addnumbers/num1/10/num2/20</a></p>

<p><a href="http://localhost:8080/customerservice/addnumbers?num1=10&amp;num2=50"
rel="nofollow">http://localhost:8080/customerservice/addnumbers?num1=10&amp;num2=50</a></p>

<p>We only support the second pattern for the time being.</p>


<ul>
	<li>The client APIs need to be able to specify HTTP method (GET/POST, PUT/DELETED will
be supported later).  ( have not figured out how to do this yet <img class="emoticon" src="/confluence/images/icons/emoticons/wink.gif"
height="20" width="20" align="absmiddle" alt="" border="0"/> )</li>
</ul>


<ul>
	<li>The client side needs to support JAX-WS Dispatcher. When Dispatcher mode is used,
it is the responsibility of user application code to set the target URI properly, e.g., the
operation name needs to be encoded in URL. Following code snippet shows how this can be done:</li>
</ul>


<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
service = Service.create(qname); 
service.addPort(qname, HTTPBinding.HTTP_BINDING, url);
Dispatch&lt;Source&gt; dispatcher = service.createDispatch(<span class="code-keyword">new</span>
QName(<span class="code-quote">"", "</span>"),
                                        Source.class, service.Mode.PAYLOAD);
</pre>
</div></div>

<ul>
	<li>The client side needs to support JAX-WS SEI style. The code will look very similar
to XML binding client side SEI code. See the hello_world_xml_bare sample in Celtix 1.0 for
details. The REST binding needs to encode the operation name into request URL, and if it is
HTTP GET, the parameters need to be encoded into URL as well.</li>
</ul>



<ul>
	<li>The server side needs to support JAX-WS provider. Besides the standard provider
support, the requested URL needs to pass into provider. User's logic in provider implementation
needs this info to resolve operation name.  One way to pass URL is putting it into MessageContext.
See<a href="/confluence/pages/createpage.action?spaceKey=CXF&amp;title=4&amp;linkCreation=true&amp;fromPageId=23580"
class="createlink">4</a> for an example. Provider style is normally used to write
a new REST service in CXF.</li>
</ul>



<ul>
	<li>The server side needs to support JAX-WS SEI. In this case, REST binding needs to
resolve operation name from requested URL as well as parse input parameters from GET or POST.
SEI style can be used to expose existing SOAP/XML binding services as REST service.</li>
</ul>


<ul>
	<li>We need a wsdltorest tool to generate wsdl for REST binding.</li>
</ul>




<p><a href="/confluence/pages/createpage.action?spaceKey=CXF&amp;title=1&amp;linkCreation=true&amp;fromPageId=23580"
class="createlink">1</a>. <a href="http://www.mail-archive.com/tuscany-dev%40ws.apache.org/msg06704.html"
rel="nofollow">http://www.mail-archive.com/tuscany-dev%40ws.apache.org/msg06704.html</a></p>

<p><a href="/confluence/pages/createpage.action?spaceKey=CXF&amp;title=2&amp;linkCreation=true&amp;fromPageId=23580"
class="createlink">2</a>. <a href="http://java.sun.com/developer/technicalArticles/WebServices/restful/"
rel="nofollow">http://java.sun.com/developer/technicalArticles/WebServices/restful/</a></p>

<p><a href="/confluence/pages/createpage.action?spaceKey=CXF&amp;title=3&amp;linkCreation=true&amp;fromPageId=23580"
class="createlink">3</a>. <a href="http://ws.apache.org/axis2/1_0/rest-ws.html"
rel="nofollow">http://ws.apache.org/axis2/1_0/rest-ws.html</a></p>

<p><a href="/confluence/pages/createpage.action?spaceKey=CXF&amp;title=4&amp;linkCreation=true&amp;fromPageId=23580"
class="createlink">4</a>. <a href="http://weblogs.java.net/blog/kohlert/archive/2006/01/publishing_a_re.html"
rel="nofollow">http://weblogs.java.net/blog/kohlert/archive/2006/01/publishing_a_re.html</a></p>
     </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message