camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "willem jiang (Confluence)" <conflue...@apache.org>
Subject [CONF] Apache Camel > CXFRS
Date Mon, 18 Nov 2013 06:38:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/en/2176/1/1/_/styles/combined.css?spaceKey=CAMEL&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/CAMEL/CXFRS">CXFRS</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~njiang">willem
jiang</a>
    </h4>
        <div id="versionComment">
        <b>Comment:</b>
        CAMEL-6971<br />
    </div>
        <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" >- {{SimpleConsumer}} =&gt; see
the [Consuming a REST Request with the Simple Binding Style|#Consuming a REST Request - Simple
Binding Style] below. <br>- {{Default}} =&gt; the default style. For consumers this
passes on a {{MessageContentsList}} to the route, requiring low-level processing in the route.
| {{bindingStyle=SimpleConsumer}} | No | _Default_ | <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">|
{{providers}}| *Since Camel 2.12.2* Add custom JAX-RS providers to the list of providers.
| No | _None_ | <br>| {{schemaLocations}} | *Since Camel 2.12.2* Sets the locations
of the schemas which can be used to validate the incoming XML or JAXB-driven JSON. | NO |
_None_ | <br></td></tr>
            <tr><td class="diff-unchanged" >{div} <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h2><a name="CXFRS-CXFRSComponent"></a>CXFRS Component</h2>

<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/warning.gif" width="16" height="16"
align="absmiddle" alt="" border="0"></td><td>When using CXF as a consumer,
the <a href="/confluence/display/CAMEL/CXF+Bean+Component" title="CXF Bean Component">CXF
Bean Component</a> allows you to factor out how message payloads are received from their
processing as a RESTful or SOAP web service. This has the potential of using a multitude of
transports to consume web services. The bean component's configuration is also simpler and
provides the fastest method to implement web services using Camel and CXF.</td></tr></table></div>

<p>The <b>cxfrs:</b> component provides integration with <a href="http://incubator.apache.org/cxf/"
class="external-link" rel="nofollow">Apache CXF</a> for connecting to JAX-RS services
hosted in CXF.</p>

<p>Maven users will need to add the following dependency to their pom.xml for this component:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Default; brush: xml; gutter: false" style="font-size:12px; font-family:
ConfluenceInstalledFont,monospace;">
&lt;dependency&gt;
   &lt;groupId&gt;org.apache.camel&lt;/groupId&gt;
   &lt;artifactId&gt;camel-cxf&lt;/artifactId&gt;
   &lt;version&gt;x.x.x&lt;/version&gt;  &lt;!-- use the same version
as your Camel core version --&gt;
&lt;/dependency&gt;
</pre>
</div></div>

<h3><a name="CXFRS-URIformat"></a>URI format</h3>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Default; brush: java; gutter: false" style="font-size:12px; font-family:
ConfluenceInstalledFont,monospace;">
cxfrs://address?options
</pre>
</div></div>
<p>Where <b>address</b> represents the CXF endpoint's address</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Default; brush: java; gutter: false" style="font-size:12px; font-family:
ConfluenceInstalledFont,monospace;">
cxfrs:bean:rsEndpoint
</pre>
</div></div>
<p>Where <b>rsEndpoint</b> represents the spring bean's name which presents
the CXFRS client or server</p>

<p>For either style above, you can append options to the URI as follows:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Default; brush: java; gutter: false" style="font-size:12px; font-family:
ConfluenceInstalledFont,monospace;">
cxfrs:bean:cxfEndpoint?resourceClasses=org.apache.camel.rs.Example
</pre>
</div></div>

<h3><a name="CXFRS-Options"></a>Options</h3>
<div class="confluenceTableSmall"><div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Name </th>
<th class='confluenceTh'> Description </th>
<th class='confluenceTh'> Example </th>
<th class='confluenceTh'> Required? </th>
<th class='confluenceTh'> default value </th>
</tr>
<tr>
<td class='confluenceTd'> <tt>resourceClasses</tt> </td>
<td class='confluenceTd'> The resource classes which you want to export as REST service.
Multiple classes can be separated by comma. </td>
<td class='confluenceTd'> <tt>resourceClasses=org.apache.camel.rs.Example1,</tt><br/>
<tt>org.apache.camel.rs.Exchange2</tt> </td>
<td class='confluenceTd'> No </td>
<td class='confluenceTd'> <em>None</em> </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>resourceClass</tt> </td>
<td class='confluenceTd'> <b>Deprecated</b>: Use <tt>resourceClasses</tt>
The resource class which you want to export as REST service. </td>
<td class='confluenceTd'> <tt>resourceClass =org.apache.camel.rs.Example1</tt>
</td>
<td class='confluenceTd'> No </td>
<td class='confluenceTd'> <em>None</em> </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>httpClientAPI</tt> </td>
<td class='confluenceTd'> <b>new to Camel 2.1</b> If it is true, the CxfRsProducer
will use the HttpClientAPI to invoke the service <br class="atl-forced-newline" />
If it is false, the CxfRsProducer will use the ProxyClientAPI to invoke the service </td>
<td class='confluenceTd'> httpClientAPI=true </td>
<td class='confluenceTd'> No </td>
<td class='confluenceTd'> <em>true</em> </td>
</tr>
<tr>
<td class='confluenceTd'> synchronous </td>
<td class='confluenceTd'> New in 2.5, this option will let CxfRsConsumer decide to use
sync or async API to do the underlying work. The default value is false which means it will
try to use async API by default. </td>
<td class='confluenceTd'> synchronous=true </td>
<td class='confluenceTd'> No </td>
<td class='confluenceTd'> false </td>
</tr>
<tr>
<td class='confluenceTd'> throwExceptionOnFailure </td>
<td class='confluenceTd'> New in 2.6, this option tells the CxfRsProducer to inspect
return codes and will generate an Exception if the return code is larger than 207. </td>
<td class='confluenceTd'> throwExceptionOnFailure=true </td>
<td class='confluenceTd'> No </td>
<td class='confluenceTd'> true </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>maxClientCacheSize</tt> </td>
<td class='confluenceTd'> New in 2.6, you can set a IN message header CamelDestinationOverrideUrl
to dynamically override the target destination Web Service or REST Service defined in your
routes.&nbsp; The implementation caches CXF clients or ClientFactoryBean in CxfProvider
and CxfRsProvider.&nbsp; This option allows you to configure the maximum size of the cache.
<br class="atl-forced-newline" /> </td>
<td class='confluenceTd'> maxClientCacheSize=5 </td>
<td class='confluenceTd'> No <br class="atl-forced-newline" /> </td>
<td class='confluenceTd'> 10 </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>setDefaultBus</tt> </td>
<td class='confluenceTd'> New in 2.9.0. Will set the default bus when CXF endpoint create
a bus by itself </td>
<td class='confluenceTd'> <tt>setDefaultBus=true</tt> </td>
<td class='confluenceTd'> No </td>
<td class='confluenceTd'> <tt>false</tt> </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>bus</tt> </td>
<td class='confluenceTd'> New in 2.9.0. A default bus created by CXF Bus Factory. Use
<tt>&#35;</tt> notation to reference a bus object from the registry. The referenced
object must be an instance of <tt>org.apache.cxf.Bus</tt>. </td>
<td class='confluenceTd'> <tt>bus=#busName</tt> </td>
<td class='confluenceTd'> No </td>
<td class='confluenceTd'> <em>None</em> </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>bindingStyle</tt> </td>
<td class='confluenceTd'> <b>As of 2.11</b>. Sets how requests and responses
will be mapped to/from Camel. Two values are possible: 
<ul class="alternate" type="square">
	<li><tt>SimpleConsumer</tt> =&gt; see the <a href="#CXFRS-ConsumingaRESTRequestSimpleBindingStyle">Consuming
a REST Request with the Simple Binding Style</a> below.</li>
	<li><tt>Default</tt> =&gt; the default style. For consumers this passes
on a <tt>MessageContentsList</tt> to the route, requiring low-level processing
in the route.</li>
</ul>
</td>
<td class='confluenceTd'> <tt>bindingStyle=SimpleConsumer</tt> </td>
<td class='confluenceTd'> No </td>
<td class='confluenceTd'> <em>Default</em> </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>providers</tt></td>
<td class='confluenceTd'> <b>Since Camel 2.12.2</b> Add custom JAX-RS providers
to the list of providers. </td>
<td class='confluenceTd'> No </td>
<td class='confluenceTd'> <em>None</em> </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>schemaLocations</tt> </td>
<td class='confluenceTd'> <b>Since Camel 2.12.2</b> Sets the locations of
the schemas which can be used to validate the incoming XML or JAXB-driven JSON. </td>
<td class='confluenceTd'> NO </td>
<td class='confluenceTd'> <em>None</em> </td>
</tr>
</tbody></table>
</div>
</div>

<p>You can also configure the CXF REST endpoint through the spring configuration. Since
there are lots of difference between the CXF REST client and CXF REST Server, we provide different
configuration for them.<br/>
Please check out the <a href="http://svn.apache.org/repos/asf/camel/trunk/components/camel-cxf/src/main/resources/schema/cxfEndpoint.xsd"
class="external-link" rel="nofollow">schema file</a> and <a href="http://cwiki.apache.org/CXF20DOC/jax-rs.html"
class="external-link" rel="nofollow">CXF REST user guide</a> for more information.</p>

<h3><a name="CXFRS-HowtoconfiguretheRESTendpointinCamel"></a>How to configure
the REST endpoint in Camel</h3>

<p>In <a href="http://svn.apache.org/repos/asf/camel/trunk/components/camel-cxf/src/main/resources/schema/cxfEndpoint.xsd"
class="external-link" rel="nofollow">camel-cxf schema file</a>, there are two elements
for the REST endpoint definition. <b>cxf:rsServer</b> for REST consumer, <b>cxf:rsClient</b>
for REST producer.<br/>
You can find a Camel REST service route configuration example here.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Default; brush: xml; gutter: false"><![CDATA[
&lt;beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:cxf="http://camel.apache.org/schema/cxf"
       xmlns:jaxrs="http://cxf.apache.org/jaxrs"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd
       http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
    "&gt;

    &lt;bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/&gt;

  &lt;!-- Defined the real JAXRS back end service  --&gt;
  &lt;jaxrs:server id="restService"
		        address="http://localhost:${CXFTestSupport.port2}/CxfRsRouterTest/rest" 
		        staticSubresourceResolution="true"&gt;
    &lt;jaxrs:serviceBeans&gt;
      &lt;ref bean="customerService"/&gt;
    &lt;/jaxrs:serviceBeans&gt;       
  &lt;/jaxrs:server&gt;
  
  &lt;!--  bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.JSONProvider"/--&gt;

  &lt;bean id="customerService" class="org.apache.camel.component.cxf.jaxrs.testbean.CustomerService"
/&gt;
   
  &lt;!-- Defined the server endpoint to create the cxf-rs consumer --&gt; 
  &lt;cxf:rsServer id="rsServer" address="http://localhost:${CXFTestSupport.port1}/CxfRsRouterTest/route"
    serviceClass="org.apache.camel.component.cxf.jaxrs.testbean.CustomerService" 
    loggingFeatureEnabled="true" loggingSizeLimit="20" skipFaultLogging="true"/&gt;

  &lt;!-- Defined the client endpoint to create the cxf-rs consumer --&gt;
  &lt;cxf:rsClient id="rsClient" address="http://localhost:${CXFTestSupport.port2}/CxfRsRouterTest/rest"
    serviceClass="org.apache.camel.component.cxf.jaxrs.testbean.CustomerService"
    loggingFeatureEnabled="true" skipFaultLogging="true"/&gt;
  
  &lt;!-- The camel route context --&gt;
  &lt;camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"&gt;
    &lt;route&gt;
       &lt;from uri="cxfrs://bean://rsServer"/&gt;
       &lt;!-- We can remove this configure as the CXFRS producer is using the HttpAPI
by default --&gt;
       &lt;setHeader headerName="CamelCxfRsUsingHttpAPI"&gt;
         &lt;constant&gt;True&lt;/constant&gt;        
       &lt;/setHeader&gt;
       &lt;to uri="cxfrs://bean://rsClient"/&gt;
    &lt;/route&gt;
  &lt;/camelContext&gt;
  
&lt;/beans&gt;
]]></script>
</div></div>

<h3><a name="CXFRS-ConsumingaRESTRequestSimpleBindingStyle"></a>Consuming
a REST Request - Simple Binding Style</h3>

<p><b>Available as of Camel 2.11</b></p>

<p>The <tt>Default</tt> binding style is rather low-level, requiring the
user to manually process the <tt>MessageContentsList</tt> object coming into the
route. Thus, it tightly couples the route logic with the method signature and parameter indices
of the JAX-RS operation. Somewhat inelegant, difficult and error-prone.</p>

<p>In contrast, the <tt>SimpleConsumer</tt> binding style performs the following
mappings, in order to <b>make the request data more accessible</b> to you within
the Camel Message:</p>

<ul>
	<li>JAX-RS Parameters (@HeaderParam, @QueryParam, etc.) are injected as IN message
headers. The header name matches the value of the annotation.</li>
	<li>The request entity (POJO or other type) becomes the IN message body. If a single
entity cannot be identified in the JAX-RS method signature, it falls back to the original
<tt>MessageContentsList</tt>.</li>
	<li>Binary <tt>@Multipart</tt> body parts become IN message attachments,
supporting <tt>DataHandler</tt>, <tt>InputStream</tt>, <tt>DataSource</tt>
and CXF's <tt>Attachment</tt> class.</li>
	<li>Non-binary <tt>@Multipart</tt> body parts are mapped as IN message
headers. The header name matches the Body Part name.</li>
</ul>


<p>Additionally, the following rules apply to the <b>Response mapping</b>:</p>

<ul>
	<li>If the message body type is different to <tt>javax.ws.rs.core.Response</tt>
(user-built response), a new <tt>Response</tt> is created and the message body
is set as the entity (so long it's not null). The response status code is taken from the <tt>Exchange.HTTP_RESPONSE_CODE</tt>
header, or defaults to 200 OK if not present.</li>
	<li>If the message body type is equal to <tt>javax.ws.rs.core.Response</tt>,
it means that the user has built a custom response, and therefore it is respected and it becomes
the final response.</li>
	<li>In all cases, Camel headers permitted by custom or default <tt>HeaderFilterStrategy</tt>
are added to the HTTP response.</li>
</ul>


<h4><a name="CXFRS-EnablingtheSimpleBindingStyle"></a>Enabling the Simple
Binding Style</h4>

<p>This binding style can be activated by setting the <tt>bindingStyle</tt>
parameter in the consumer endpoint to value <tt>SimpleConsumer</tt>:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Default; brush: java; gutter: false" style="font-size:12px; font-family:
ConfluenceInstalledFont,monospace;">
  from("cxfrs:bean:rsServer?bindingStyle=SimpleConsumer")
    .to("log:TEST?showAll=true");
</pre>
</div></div>

<h4><a name="CXFRS-Examplesofrequestbindingwithdifferentmethodsignatures"></a>Examples
of request binding with different method signatures</h4>

<p>Below is a list of method signatures along with the expected result from the Simple
binding.</p>

<p><b><tt>public Response doAction(BusinessObject request);</tt></b><br/>
Request payload is placed in IN message body, replacing the original MessageContentsList.</p>

<p><b><tt>public Response doAction(BusinessObject request, @HeaderParam("abcd")
String abcd, @QueryParam("defg") String defg);</tt></b><br/>
Request payload placed in IN message body, replacing the original MessageContentsList. Both
request params mapped as IN message headers with names abcd and defg.</p>

<p><b><tt>public Response doAction(@HeaderParam("abcd") String abcd, @QueryParam("defg")
String defg);</tt></b><br/>
Both request params mapped as IN message headers with names abcd and defg. The original MessageContentsList
is preserved, even though it only contains the 2 parameters.</p>

<p><b><tt>public Response doAction(@Multipart(value="body1") BusinessObject
request, @Multipart(value="body2") BusinessObject request2);</tt></b><br/>
The first parameter is transferred as a header with name body1, and the second one is mapped
as header body2. The original MessageContentsList is preserved as the IN message body.</p>

<p><b><tt>public Response doAction(InputStream abcd);</tt></b><br/>
The InputStream is unwrapped from the MessageContentsList and preserved as the IN message
body. </p>

<p><b><tt>public Response doAction(DataHandler abcd);</tt></b><br/>
The DataHandler is unwrapped from the MessageContentsList and preserved as the IN message
body. </p>

<h4><a name="CXFRS-MoreexamplesoftheSimpleBindingStyle"></a>More examples
of the Simple Binding Style</h4>

<p>Given a JAX-RS resource class with this method:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Default; brush: java; gutter: false" style="font-size:12px; font-family:
ConfluenceInstalledFont,monospace;">
    @POST @Path("/customers/{type}")
    public Response newCustomer(Customer customer, @PathParam("type") String type, @QueryParam("active")
@DefaultValue("true") boolean active) {
        return null;
    }
</pre>
</div></div>

<p>Serviced by the following route:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Default; brush: java; gutter: false" style="font-size:12px; font-family:
ConfluenceInstalledFont,monospace;">
    from("cxfrs:bean:rsServer?bindingStyle=SimpleConsumer")
        .recipientList(simple("direct:${header.operationName}"));

    from("direct:newCustomer")
        .log("Request: type=${header.type}, active=${header.active}, customerData=${body}");
</pre>
</div></div>

<p>The following HTTP request with XML payload (given that the Customer DTO is JAXB-annotated):</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Default; brush: java; gutter: false" style="font-size:12px; font-family:
ConfluenceInstalledFont,monospace;">
POST /customers/gold?active=true

Payload:
&lt;Customer&gt;
  &lt;fullName&gt;Raul Kripalani&lt;/fullName&gt;
  &lt;country&gt;Spain&lt;/country&gt;
  &lt;project&gt;Apache Camel&lt;/project&gt;
&lt;/Customer&gt;
</pre>
</div></div>

<p>Will print the message:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Default; brush: java; gutter: false" style="font-size:12px; font-family:
ConfluenceInstalledFont,monospace;">
Request: type=gold, active=true, customerData=&lt;Customer.toString() representation&gt;
</pre>
</div></div>

<p>For more examples on how to process requests and write responses can be found <a
href="https://svn.apache.org/repos/asf/camel/trunk/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/simplebinding/"
class="external-link" rel="nofollow">here</a>.</p>

<h3><a name="CXFRS-ConsumingaRESTRequestDefaultBindingStyle"></a>Consuming
a REST Request - Default Binding Style</h3>

<p><a href="http://cwiki.apache.org/CXF20DOC/jax-rs.html" class="external-link" rel="nofollow">CXF
JAXRS front end</a> implements the <a href="https://jsr311.dev.java.net/" class="external-link"
rel="nofollow">JAXRS(JSR311) API</a>, so we can export the resources classes as a
REST service. And we leverage the <a href="http://cwiki.apache.org/confluence/display/CXF20DOC/Invokers"
class="external-link" rel="nofollow">CXF Invoker API</a> to turn a REST request into
a normal Java object method invocation.<br/>
Unlike the <tt>camel-restlet</tt>, you don't need to specify the URI template
within your restlet endpoint, CXF take care of the REST request URI to resource class method
mapping according to the JSR311 specification. All you need to do in Camel is delegate this
method request to a right processor or endpoint.</p>

<p>Here is an example of a CXFRS route...</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Default; brush: java; gutter: false"><![CDATA[
private static final String CXF_RS_ENDPOINT_URI = "cxfrs://http://localhost:" + CXT + "/rest?resourceClasses=org.apache.camel.component.cxf.jaxrs.testbean.CustomerServiceResource";

protected RouteBuilder createRouteBuilder() throws Exception {
    return new RouteBuilder() {
        public void configure() {
            errorHandler(new NoErrorHandlerBuilder());
            from(CXF_RS_ENDPOINT_URI).process(new Processor() {

                public void process(Exchange exchange) throws Exception {
                    Message inMessage = exchange.getIn();                        
                    // Get the operation name from in message
                    String operationName = inMessage.getHeader(CxfConstants.OPERATION_NAME,
String.class);
                    if ("getCustomer".equals(operationName)) {
                        String httpMethod = inMessage.getHeader(Exchange.HTTP_METHOD, String.class);
                        assertEquals("Get a wrong http method", "GET", httpMethod);
                        String path = inMessage.getHeader(Exchange.HTTP_PATH, String.class);
                        // The parameter of the invocation is stored in the body of in message
                        String id = inMessage.getBody(String.class);
                        if ("/customerservice/customers/126".equals(path)) {             
              
                            Customer customer = new Customer();
                            customer.setId(Long.parseLong(id));
                            customer.setName("Willem");
                            // We just put the response Object into the out message body
                            exchange.getOut().setBody(customer);
                        } else {
                            if ("/customerservice/customers/400".equals(path)) {
                                // We return the remote client IP address this time
                                org.apache.cxf.message.Message cxfMessage = inMessage.getHeader(CxfConstants.CAMEL_CXF_MESSAGE,
org.apache.cxf.message.Message.class);
                                ServletRequest request = (ServletRequest) cxfMessage.get("HTTP.REQUEST");
                                String remoteAddress = request.getRemoteAddr();
                                Response r = Response.status(200).entity("The remoteAddress
is " + remoteAddress).build();
                                exchange.getOut().setBody(r);
                                return;
                            }
                            if ("/customerservice/customers/123".equals(path)) {
                                // send a customer response back
                                Response r = Response.status(200).entity("customer response
back!").build();
                                exchange.getOut().setBody(r);
                                return;
                            }
                            if ("/customerservice/customers/456".equals(path)) {
                                Response r = Response.status(404).entity("Can't found the
customer with uri " + path).build();
                                throw new WebApplicationException(r);
                            } else {
                                throw new RuntimeCamelException("Can't found the customer
with uri " + path);
                            }
                        }
                    }
                    if ("updateCustomer".equals(operationName)) {
                        assertEquals("Get a wrong customer message header", "header1;header2",
inMessage.getHeader("test"));
                        String httpMethod = inMessage.getHeader(Exchange.HTTP_METHOD, String.class);
                        assertEquals("Get a wrong http method", "PUT", httpMethod);
                        Customer customer = inMessage.getBody(Customer.class);
                        assertNotNull("The customer should not be null.", customer);
                        // Now you can do what you want on the customer object
                        assertEquals("Get a wrong customer name.", "Mary", customer.getName());
                        // set the response back
                        exchange.getOut().setBody(Response.ok().build());
                    }
                    
                }
                
            });
        }
    };
}
]]></script>
</div></div>

<p>And the corresponding resource class used to configure the endpoint...</p>

<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/information.gif" width="16"
height="16" align="absmiddle" alt="" border="0"></td><td><b>note about
the resource class</b><br />This class is used to configure the JAXRS properties
ONLY.  The methods will NOT be executed during the routing of messages to the endpoint, the
route itself is responsible for ALL processing instead.</td></tr></table></div>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Default; brush: java; gutter: false"><![CDATA[
@Path("/customerservice/")
public interface CustomerServiceResource {

    @GET
    @Path("/customers/{id}/")
    Customer getCustomer(@PathParam("id") String id);

    @PUT
    @Path("/customers/")
    Response updateCustomer(Customer customer);
}
]]></script>
</div></div>

<h3><a name="CXFRS-HowtoinvoketheRESTservicethroughcamelcxfrsproducer"></a>How
to invoke the REST service through camel-cxfrs producer</h3>

<p><a href="http://cwiki.apache.org/CXF20DOC/jax-rs.html" class="external-link" rel="nofollow">CXF
JAXRS front end</a> implements <a href="http://cwiki.apache.org/CXF20DOC/jax-rs.html#JAX-RS-ProxybasedAPI"
class="external-link" rel="nofollow">a proxy based client API</a>, with this API
you can invoke the remote REST service through a proxy.<br/>
<tt>camel-cxfrs</tt> producer is based on this <a href="http://cwiki.apache.org/CXF20DOC/jax-rs.html#JAX-RS-ProxybasedAPI"
class="external-link" rel="nofollow">proxy API</a>.<br/>
So, you just need to specify the operation name in the message header and prepare the parameter
in the message body, camel-cxfrs producer will generate right REST request for you.</p>

<p>Here is an example</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Default; brush: java; gutter: false"><![CDATA[
Exchange exchange = template.send("direct://proxy", new Processor() {
    public void process(Exchange exchange) throws Exception {
        exchange.setPattern(ExchangePattern.InOut);
        Message inMessage = exchange.getIn();
        setupDestinationURL(inMessage);
        // set the operation name 
        inMessage.setHeader(CxfConstants.OPERATION_NAME, "getCustomer");
        // using the proxy client API
        inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API, Boolean.FALSE);
        // set a customer header
        inMessage.setHeader("key", "value");
        // set the parameters , if you just have one parameter 
        // camel will put this object into an Object[] itself
        inMessage.setBody("123");
    }
});
     
// get the response message 
Customer response = (Customer) exchange.getOut().getBody();

assertNotNull("The response should not be null ", response);
assertEquals("Get a wrong customer id ", String.valueOf(response.getId()), "123");
assertEquals("Get a wrong customer name", response.getName(), "John");
assertEquals("Get a wrong response code", 200, exchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
assertEquals("Get a wrong header value", "value", exchange.getOut().getHeader("key"));
]]></script>
</div></div>
<p><a href="http://cwiki.apache.org/CXF20DOC/jax-rs.html" class="external-link" rel="nofollow">CXF
JAXRS front end</a> also provides <a href="http://cxf.apache.org/docs/jax-rs.html#JAX-RS-HTTPcentricclients"
class="external-link" rel="nofollow">a http centric client API</a>, You can also
invoke this API from <tt>camel-cxfrs</tt> producer. You need to specify the HTTP_PATH
and Http method and let the the producer know to use the http centric client by using the
URI option <b>httpClientAPI</b> or set the message header with CxfConstants.CAMEL_CXF_RS_USING_HTTP_API.
You can turn the response object to the type class that you specify with CxfConstants.CAMEL_CXF_RS_RESPONSE_CLASS.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Default; brush: java; gutter: false"><![CDATA[
Exchange exchange = template.send("direct://http", new Processor() {
    public void process(Exchange exchange) throws Exception {
        exchange.setPattern(ExchangePattern.InOut);
        Message inMessage = exchange.getIn();
        setupDestinationURL(inMessage);
        // using the http central client API
        inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API, Boolean.TRUE);
        // set the Http method
        inMessage.setHeader(Exchange.HTTP_METHOD, "GET");
        // set the relative path
        inMessage.setHeader(Exchange.HTTP_PATH, "/customerservice/customers/123");       
        
        // Specify the response class , cxfrs will use InputStream as the response object
type 
        inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_RESPONSE_CLASS, Customer.class);
        // set a customer header
        inMessage.setHeader("key", "value");
        // since we use the Get method, so we don't need to set the message body
        inMessage.setBody(null);                
    }
});
     
// get the response message 
Customer response = (Customer) exchange.getOut().getBody();

assertNotNull("The response should not be null ", response);
assertEquals("Get a wrong customer id ", String.valueOf(response.getId()), "123");
assertEquals("Get a wrong customer name", response.getName(), "John");
assertEquals("Get a wrong response code", 200, exchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE));
assertEquals("Get a wrong header value", "value", exchange.getOut().getHeader("key"));
]]></script>
</div></div>
<p>From Camel 2.1, we also support to specify the query parameters from cxfrs URI for
the CXFRS http centric client.<br/>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Default; brush: java; gutter: false"><![CDATA[
Exchange exchange = template.send("cxfrs://http://localhost:" + getPort2() + "/" + getClass().getSimpleName()
+ "/testQuery?httpClientAPI=true&amp;q1=12&amp;q2=13"
]]></script>
</div></div>To support the Dynamical routing, you can override the URI's query
parameters by using the CxfConstants.CAMEL_CXF_RS_QUERY_MAP header to set the parameter map
for it.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Default; brush: java; gutter: false"><![CDATA[
Map&lt;String, String&gt; queryMap = new LinkedHashMap&lt;String, String&gt;();
                   
queryMap.put("q1", "new");
queryMap.put("q2", "world");                    
inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_QUERY_MAP, queryMap);
]]></script>
</div></div>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;" class="grey">
                        <a href="https://cwiki.apache.org/confluence/users/removespacenotification.action?spaceKey=CAMEL">Stop
watching space</a>
            <span style="padding: 0px 5px;">|</span>
                <a href="https://cwiki.apache.org/confluence/users/editmyemailsettings.action">Change
email notification preferences</a>
</div>
        <a href="https://cwiki.apache.org/confluence/display/CAMEL/CXFRS">View Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=119513&revisedVersion=26&originalVersion=25">View
Changes</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message