cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache CXF > Custom CXF Transport
Date Tue, 01 Feb 2011 12:04:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2036/9/15/_/styles/combined.css?spaceKey=CXF&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/CXF/Custom+CXF+Transport">Custom
CXF Transport</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~mazzag">Glen
Mazza</a>
    </h4>
        <div id="versionComment">
        <b>Comment:</b>
        Editorial cleanup.<br />
    </div>
        <br/>
                         <h4>Changes (49)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-changed-lines" >This page <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">tries
to summarize</span> <span class="diff-added-words"style="background-color: #dfd;">summarizes
an</span> experience of implementing <span class="diff-added-words"style="background-color:
#dfd;">a</span> new CXF transport. <br></td></tr>
            <tr><td class="diff-unchanged" > <br> <br>h2. Use Cases
<br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Normally
implementation of custom transport is required to provide new physical protocol not yet supported
by CXF(for instance udp, ftp). New CXF transport can be also a solution to support legacy
ESB participants that have to be interoperable with JAX-WS services and clients. <br>Actually
CXF 2.3.x distribution provides transport implementation for following protocols: HTTP(S),
JBI, JMS and Local(inside one JVM). Camel additionally implements CXF transport for camel
exchanges. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Normally
implementing a custom transport is required when providing a new physical protocol not yet
supported by CXF (udp or ftp, for example). New CXF transports can be also a solution to support
legacy ESB participants that have to be interoperable with JAX-WS services and clients.  Presently
the CXF 2.3.x distribution provides a transport implementation for the following protocols:
HTTP(S), JBI, JMS and Local(inside one JVM). Camel additionally implements CXF transport for
Camel exchanges. <br></td></tr>
            <tr><td class="diff-unchanged" > <br>h2. Architecture and Design
<br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">The
transport functionality is based on two fundamental definitions: Conduit and Destination.
Conduit is responsible to send a message to recipient and Destination – to receive a message
from the sender. In order to send a response, Destination needs own back-channel Conduit (in
case of request-response communication). Conduit and Destination are created by TransportFactory.
CXF selects a correct TransportFactory based on transport URL. SOAP is also considered as
high level transport and has own Conduit and Destination in CXF. <br>To send message
into physical channel Conduit should access the message context. Normal practice in this case
is own implementation of OutputStream extending CachedOutputStream. The custom stream will
be set to message and provides a possibility to access context in streaming or buffered way
depending on transport requirements and to send message to physical channel. CachedOutputStream
is configured to keep message in memory only up to limited size. If size is exceeded, message
is swapped to disk. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">The
transport functionality is based on two fundamental definitions: conduit and destination.
Conduits are responsible for sending a message to recipients and destinations for receiving
a message from the sender. In order to send a response, a destination needs its own back-channel
conduit (in case of request-response communication). Conduits and destinations are created
by a TransportFactory. CXF selects the correct TransportFactory based on the transport URL.
SOAP is also considered a high level transport and has its own conduit and destination in
CXF. <br>To send a message into a physical channel, the conduit should access the message
context. Normal practice in this case is to use a subclass of OutputStream extending CachedOutputStream.
The custom stream will be fed the message and provides a possibility to access context in
streaming or buffered form depending on the transport requirements. CachedOutputStream is
configured to keep message in memory only up to a predefined size. If this size is exceeded,
the message is swapped to disk. <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">Class</span>
<span class="diff-added-words"style="background-color: #dfd;">A class</span> diagram
of TransportFactory, Conduit, Destination and OutputStream is shown <span class="diff-changed-words">bel<span
class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">l</span>ow:</span>
<br></td></tr>
            <tr><td class="diff-unchanged" >!cxf-transport-class-diagram.jpg!
<br> <br> <br>h2. How it Works <br></td></tr>
            <tr><td class="diff-changed-lines" >Interaction between JAX-WS client
and service using CXF transport is represented <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">on</span>
<span class="diff-added-words"style="background-color: #dfd;">in the</span> following
figure: <br></td></tr>
            <tr><td class="diff-unchanged" >!cxf-transport-view.jpg! <br>
<br>h3. Simplified Client Workflow: <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">*
Step1: JAX-WS client invokes a service for example in this way: <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">*
Step1: JAX-WS client invokes a service, in this manner for example: <br></td></tr>
            <tr><td class="diff-unchanged" >{code:|borderStyle=solid} <br>
       URL wsdlURL = this.getClass().getResource(&quot;/HelloWorld.wsdl&quot;); <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >        String result = hw.sayHi(TEST_REQUEST);
}} <br>{code} <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step2: CXF runtime <span
class="diff-changed-words">select<span class="diff-added-chars"style="background-color:
#dfd;">s the</span></span> correct TransportFactory based on some criteria
(described <span class="diff-changed-words">bel<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">l</span>ow)</span>
<br></td></tr>
            <tr><td class="diff-changed-lines" >* Step3: CXF runtime calls _TransportFactory.getConduit()_
method to obtain <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">Conduit</span>
<span class="diff-added-words"style="background-color: #dfd;">the conduit</span>
<br></td></tr>
            <tr><td class="diff-unchanged" >* Step4: CXF runtime invokes _Conduit.prepare()_
and passes outgoing message as argument <br>* Step5: Conduit sets own OutputStream (normally
extended CachedOutputStream) as outgoing message content <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">*
Step6: CXF runtime processes outgoing message, calls interceptors chain and invokes Conduit.close(Message)
method is invoked for outgoing message.  <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">*
Step6: CXF runtime processes outgoing message, calls the interceptor chain and invokes Conduit.close(Message)
method for the outgoing message.  <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step7: Finally, _OutputStream.doClose()_
<span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">method</span>
for <span class="diff-added-words"style="background-color: #dfd;">the</span> outgoing
message is invoked <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">*
Step8: In _doClose()_ method OutputStream class has access to marshalled outgoing message
and exchange and will send this message through network to service using corresponded transport
protocol <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">*
Step8: In the _doClose()_ method, the OutputStream class has access to the marshalled outgoing
message and exchange and will send this message to the service using the corresponding transport
protocol <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step9: In case of one-way communication
exchange will be closed. <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">Go</span>
<span class="diff-added-words"style="background-color: #dfd;">Skip</span> to <span
class="diff-changed-words"><span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">s</span><span
class="diff-added-chars"style="background-color: #dfd;">S</span>tep</span>
14 <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">*
Step10: In case of request-response communication Conduit waits for service response in synchronies
or asynchronies manner <br>* Step11: When response is received, Conduit creates a new
Message, set it’s context and puts it as In-Message in exchange as incoming message <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">*
Step10: In case of request-response communication, the conduit will wait for the service response
in synchronous or asynchronous manner <br>* Step11: When response is received, the conduit
creates a new message, sets its context and puts it as In-Message in the exchange as an incoming
message <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step12: When fault is received,
Conduit creates a new Message, sets <span class="diff-changed-words">it<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">’</span>s</span>
context and puts it as fault message in exchange as in-fault message <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step13: Conduit notifies <span
class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">incomingObesrver</span>
<span class="diff-added-words"style="background-color: #dfd;">any incomingObserver</span>
about <span class="diff-added-words"style="background-color: #dfd;">the</span>
response using _incomingObserver.onMessage()_ call <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">*
Step14: _Conduit.close(Message)_ method is invoked for incoming message. Normally Conduit
implementation decreases the reference or closes network connection with the service. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">*
Step14: _Conduit.close(Message)_ method is invoked for incoming message. Normally the conduit
implementation decreases the reference count with the service, potentially closing the network
connection if the count is zero. <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step15: JAX-WS client code receives
<span class="diff-added-words"style="background-color: #dfd;">the</span> response
in sync or async style <br></td></tr>
            <tr><td class="diff-unchanged" > <br>h3. Simplified Service
Workflow: <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >	Endpoint.publish(&quot;udp://localhost:9000/hello&quot;,
serverImpl); <br>{code} <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step2: CXF runtime selects correct
TransportFactory based on some criteria (described <span class="diff-changed-words">bel<span
class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">l</span>ow)</span>
<br></td></tr>
            <tr><td class="diff-changed-lines" >* Step3: CXF runtime calls _TransportFactory.getDestination()_
method to obtain <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">Destination</span>
<span class="diff-added-words"style="background-color: #dfd;">the destination</span>
<br></td></tr>
            <tr><td class="diff-changed-lines" >* Step4: As far as service is
registered <span class="diff-changed-words"><span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">D</span><span
class="diff-added-chars"style="background-color: #dfd;">d</span>estination</span>
will be activated using _Destination.activate()_ method <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step5: _Destination.activate()_
opens network transport connections and <span class="diff-changed-words">listen<span
class="diff-added-chars"style="background-color: #dfd;">s to</span></span>
incoming requests <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">*
Step6: When request comes, Destination creates message, sets content and notifies message
observer getMessageObserver.onMessage(). Normally incoming connection is saved in correlation
map to be extracted for appropriate response. <br>* Step7: Service Implementation will
be called with request message. In case of one-way communication it is end of exchange. In
case of request-response business implementation returns response or throws fault exception.
<br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">*
Step6: When a request comes, the destination creates a message, sets the content and notifies
any message observers via getMessageObserver.onMessage(). Normally an incoming connection
is saved in a correlation map to be extracted for the appropriate response. <br>* Step7:
The service implementation will be called with the request message. In case of one-way communication
the exchange is now finished. In case of request-response, the business implementation either
returns a response or throws a fault exception. <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step8: <span class="diff-added-words"style="background-color:
#dfd;">The</span> CXF Runtime requests <span class="diff-added-words"style="background-color:
#dfd;">a</span> back-channel conduit from <span class="diff-added-words"style="background-color:
#dfd;">the</span> destination via _Destination.getInbuiltBackChannel()_ <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step9: <span class="diff-added-words"style="background-color:
#dfd;">The</span> Back-channel <span class="diff-changed-words">conduit<span
class="diff-added-chars"style="background-color: #dfd;">&#39;s</span></span>
_prepare()_ <span class="diff-added-words"style="background-color: #dfd;">method</span>
will be called with <span class="diff-added-words"style="background-color: #dfd;">a</span>
response message as argument <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step10: Back-channel conduit
sets <span class="diff-added-words"style="background-color: #dfd;">its</span>
own OutputStream as <span class="diff-added-words"style="background-color: #dfd;">a</span>
message context <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">*
Step11: CXF runtime processes response message, calls interceptors chain and invokes _Conduit.close(Message)_
method is invoked for response message. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">*
Step11: CXF runtime processes the response message, calls the interceptor chain and invokes
_Conduit.close(Message)_ for the response message. <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step12. Finally _OutputStream.doClose()_
method for <span class="diff-added-words"style="background-color: #dfd;">the</span>
response message is invoked <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step13: In _doClose()_ method
<span class="diff-added-words"style="background-color: #dfd;">the</span> OutputStream
class has access to <span class="diff-added-words"style="background-color: #dfd;">the</span>
marshalled response message and will send this message through the network as <span class="diff-added-words"style="background-color:
#dfd;">a</span> response to the client. Appropriate incoming connection normally
is extracted from correlation map. <br></td></tr>
            <tr><td class="diff-unchanged" > <br>h2. Registration of Transport
Factory <br></td></tr>
            <tr><td class="diff-changed-lines" >There are two ways to register
transport factory: <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">programmatic
and</span> <span class="diff-added-words"style="background-color: #dfd;">programmatically
or</span> via <span class="diff-changed-words"><span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">s</span><span
class="diff-added-chars"style="background-color: #dfd;">S</span>pring</span>
configuration. <br></td></tr>
            <tr><td class="diff-changed-lines" >To register transport factory
programmatically it is necessary to execute <span class="diff-added-words"style="background-color:
#dfd;">the</span> following code: <br></td></tr>
            <tr><td class="diff-unchanged" >{code:|borderStyle=solid} <br>
    Bus bus = BusFactory.getThreadDefaultBus(); <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >     extension.registerConduitInitiator(&quot;http://cxf.apache.org/transports/TRANSPORT_PREFIX/configuration&quot;,
customTransport); <br>{code} <br></td></tr>
            <tr><td class="diff-changed-lines" >Where TRANSPORT_PREFIX is <span
class="diff-added-words"style="background-color: #dfd;">the</span> protocol of <span
class="diff-added-words"style="background-color: #dfd;">the</span> new transport
(http, https, jms, udp). <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Alternatively
it is also possible to register transport factory using spring configuration: <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">For
Spring configuration, the following could be used instead: <br></td></tr>
            <tr><td class="diff-unchanged" >{code:xml} <br>	&lt;bean
class=&quot;org.company.cxf.transport.CustomTransportFactory&quot; <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >	&lt;/bean&gt; <br>{code}
<br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">To
define new transport endpoint in WSDL document it is necessary: <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">To
define a new transport endpoint in the WSDL document follow these two steps: <br></td></tr>
            <tr><td class="diff-changed-lines" >a) Set <span class="diff-added-words"style="background-color:
#dfd;">the</span> soap:binding transport attribute to <span class="diff-added-words"style="background-color:
#dfd;">the</span> transport URL value (http://cxf.apache.org/transports/TRANSPORT_PREFIX)
<br></td></tr>
            <tr><td class="diff-changed-lines" >b) <span class="diff-added-words"style="background-color:
#dfd;">The</span> Port address element should be bound to namespace equals to transport
URL in WSDL XML <br></td></tr>
            <tr><td class="diff-unchanged" > <br>Sample: <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" > <br>h2. Conduit and Destination
Lifecycle <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Conduit
and Destination lifecycle is requested from TransportFactory by every client or service creation.
TransportFactory can either create Conduit and Destination for each request or cache them
based on service endpoint information <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">The
conduit and destination lifecycle can be started by the TransportFactory during every client
or service creation. The TransportFactory can either create a conduit and destination for
each request or cache them based on service endpoint information. <br></td></tr>
            <tr><td class="diff-unchanged" > <br>h2. Concurrency Aspects
<br></td></tr>
            <tr><td class="diff-changed-lines" >Conduit and <span class="diff-changed-words"><span
class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">D</span><span
class="diff-added-chars"style="background-color: #dfd;">d</span>estination</span>
objects can by concurrently accessed by multiple threads. Implementations should care about
concurrent correlations maps and/or synchronization primitives. <br></td></tr>
            <tr><td class="diff-unchanged" > <br>h2. References <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <p>This page summarizes an experience of implementing a new CXF transport.</p>


<h2><a name="CustomCXFTransport-UseCases"></a>Use Cases</h2>
<p>Normally implementing a custom transport is required when providing a new physical
protocol not yet supported by CXF (udp or ftp, for example). New CXF transports can be also
a solution to support legacy ESB participants that have to be interoperable with JAX-WS services
and clients.  Presently the CXF 2.3.x distribution provides a transport implementation for
the following protocols: HTTP(S), JBI, JMS and Local(inside one JVM). Camel additionally implements
CXF transport for Camel exchanges.</p>

<h2><a name="CustomCXFTransport-ArchitectureandDesign"></a>Architecture
and Design</h2>
<p>The transport functionality is based on two fundamental definitions: conduit and
destination. Conduits are responsible for sending a message to recipients and destinations
for receiving a message from the sender. In order to send a response, a destination needs
its own back-channel conduit (in case of request-response communication). Conduits and destinations
are created by a TransportFactory. CXF selects the correct TransportFactory based on the transport
URL. SOAP is also considered a high level transport and has its own conduit and destination
in CXF.<br/>
To send a message into a physical channel, the conduit should access the message context.
Normal practice in this case is to use a subclass of OutputStream extending CachedOutputStream.
The custom stream will be fed the message and provides a possibility to access context in
streaming or buffered form depending on the transport requirements. CachedOutputStream is
configured to keep message in memory only up to a predefined size. If this size is exceeded,
the message is swapped to disk.</p>

<p>A class diagram of TransportFactory, Conduit, Destination and OutputStream is shown
below:<br/>
<span class="image-wrap" style=""><img src="/confluence/download/attachments/25200212/cxf-transport-class-diagram.jpg?version=2&amp;modificationDate=1296397054000"
style="border: 0px solid black" /></span></p>


<h2><a name="CustomCXFTransport-HowitWorks"></a>How it Works</h2>
<p>Interaction between JAX-WS client and service using CXF transport is represented
in the following figure:<br/>
<span class="image-wrap" style=""><img src="/confluence/download/attachments/25200212/cxf-transport-view.jpg?version=1&amp;modificationDate=1296397054000"
style="border: 0px solid black" /></span></p>

<h3><a name="CustomCXFTransport-SimplifiedClientWorkflow%3A"></a>Simplified
Client Workflow:</h3>
<ul>
	<li>Step1: JAX-WS client invokes a service, in this manner for example:
<div class="code panel" style="border-style: solid;border-width: 1px;"><div class="codeContent
panelContent">
<pre class="code-java">
        URL wsdlURL = <span class="code-keyword">this</span>.getClass().getResource(<span
class="code-quote">"/HelloWorld.wsdl"</span>);
        HelloWorldService service = <span class="code-keyword">new</span> HelloWorldService(wsdlURL,
SERVICE_NAME);        
        HelloWorld hw = service.getHelloWorldPort();       
        <span class="code-object">String</span> result = hw.sayHi(TEST_REQUEST);
}}
</pre>
</div></div></li>
	<li>Step2: CXF runtime selects the correct TransportFactory based on some criteria
(described below)</li>
	<li>Step3: CXF runtime calls <em>TransportFactory.getConduit()</em> method
to obtain the conduit</li>
	<li>Step4: CXF runtime invokes <em>Conduit.prepare()</em> and passes outgoing
message as argument</li>
	<li>Step5: Conduit sets own OutputStream (normally extended CachedOutputStream) as
outgoing message content</li>
	<li>Step6: CXF runtime processes outgoing message, calls the interceptor chain and
invokes Conduit.close(Message) method for the outgoing message.</li>
	<li>Step7: Finally, <em>OutputStream.doClose()</em> for the outgoing message
is invoked</li>
	<li>Step8: In the <em>doClose()</em> method, the OutputStream class has
access to the marshalled outgoing message and exchange and will send this message to the service
using the corresponding transport protocol</li>
	<li>Step9: In case of one-way communication exchange will be closed. Skip to Step 14</li>
	<li>Step10: In case of request-response communication, the conduit will wait for the
service response in synchronous or asynchronous manner</li>
	<li>Step11: When response is received, the conduit creates a new message, sets its
context and puts it as In-Message in the exchange as an incoming message</li>
	<li>Step12: When fault is received, Conduit creates a new Message, sets its context
and puts it as fault message in exchange as in-fault message</li>
	<li>Step13: Conduit notifies any incomingObserver about the response using <em>incomingObserver.onMessage()</em>
call</li>
	<li>Step14: <em>Conduit.close(Message)</em> method is invoked for incoming
message. Normally the conduit implementation decreases the reference count with the service,
potentially closing the network connection if the count is zero.</li>
	<li>Step15: JAX-WS client code receives the response in sync or async style</li>
</ul>


<h3><a name="CustomCXFTransport-SimplifiedServiceWorkflow%3A"></a>Simplified
Service Workflow:</h3>
<ul>
	<li>Step1: JAX-WS service is registered for example in this way:
<div class="code panel" style="border-style: solid;border-width: 1px;"><div class="codeContent
panelContent">
<pre class="code-java">
	HelloWorldImpl serverImpl = <span class="code-keyword">new</span> HelloWorldImpl();
	Endpoint.publish(<span class="code-quote">"udp:<span class="code-comment">//localhost:9000/hello"</span>,
serverImpl);</span>
</pre>
</div></div></li>
	<li>Step2: CXF runtime selects correct TransportFactory based on some criteria (described
below)</li>
	<li>Step3: CXF runtime calls <em>TransportFactory.getDestination()</em>
method to obtain the destination</li>
	<li>Step4: As far as service is registered destination will be activated using <em>Destination.activate()</em>
method</li>
	<li>Step5: <em>Destination.activate()</em> opens network transport connections
and listens to incoming requests</li>
	<li>Step6: When a request comes, the destination creates a message, sets the content
and notifies any message observers via getMessageObserver.onMessage(). Normally an incoming
connection is saved in a correlation map to be extracted for the appropriate response.</li>
	<li>Step7: The service implementation will be called with the request message. In case
of one-way communication the exchange is now finished. In case of request-response, the business
implementation either returns a response or throws a fault exception.</li>
	<li>Step8: The CXF Runtime requests a back-channel conduit from the destination via
<em>Destination.getInbuiltBackChannel()</em></li>
	<li>Step9: The Back-channel conduit's <em>prepare()</em> method will be
called with a response message as argument</li>
	<li>Step10: Back-channel conduit sets its own OutputStream as a message context</li>
	<li>Step11: CXF runtime processes the response message, calls the interceptor chain
and invokes <em>Conduit.close(Message)</em> for the response message.</li>
	<li>Step12. Finally <em>OutputStream.doClose()</em> method for the response
message is invoked</li>
	<li>Step13: In <em>doClose()</em> method the OutputStream class has access
to the marshalled response message and will send this message through the network as a response
to the client. Appropriate incoming connection normally is extracted from correlation map.</li>
</ul>


<h2><a name="CustomCXFTransport-RegistrationofTransportFactory"></a>Registration
of Transport Factory</h2>
<p>There are two ways to register transport factory: programmatically or via Spring
configuration.<br/>
To register transport factory programmatically it is necessary to execute the following code:</p>
<div class="code panel" style="border-style: solid;border-width: 1px;"><div class="codeContent
panelContent">
<pre class="code-java">
     Bus bus = BusFactory.getThreadDefaultBus();
     DestinationFactoryManagerImpl dfm = bus.getExtension(DestinationFactoryManagerImpl.class);
     CustomTransportFactory customTransport = <span class="code-keyword">new</span>
CustomTransportFactory();
     dfm.registerDestinationFactory(<span class="code-quote">"http:<span class="code-comment">//cxf.apache.org/transports/TRANSPORT_PREFIX"</span>,
customTransport);
</span>     dfm.registerDestinationFactory(<span class="code-quote">"http:<span
class="code-comment">//cxf.apache.org/transports/TRANSPORT_PREFIX/configuration"</span>,
customTransport);
</span>
     ConduitInitiatorManager extension = bus.getExtension(ConduitInitiatorManager.class);
     extension.registerConduitInitiator(<span class="code-quote">"http:<span class="code-comment">//cxf.apache.org/transports/TRANSPORT_PREFIX"</span>,
sbbTransport);
</span>     extension.registerConduitInitiator(<span class="code-quote">"http:<span
class="code-comment">//cxf.apache.org/transports/TRANSPORT_PREFIX/configuration"</span>,
customTransport);</span>
</pre>
</div></div>
<p>Where TRANSPORT_PREFIX is the protocol of the new transport (http, https, jms, udp).</p>

<p>For Spring configuration, the following could be used instead:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
	&lt;bean class=<span class="code-quote">"org.company.cxf.transport.CustomTransportFactory"</span>
		lazy-init=<span class="code-quote">"false"</span>&gt;
		<span class="code-tag">&lt;property name=<span class="code-quote">"transportIds"</span>&gt;</span>
			<span class="code-tag">&lt;list&gt;</span>
			<span class="code-tag">&lt;value&gt;</span>http http://cxf.apache.org/transports/TRANSPORT_PREFIX<span
class="code-tag">&lt;/value&gt;</span>
                	<span class="code-tag">&lt;value&gt;</span>http://cxf.apache.org/transports/TRANSPORT_PREFIX/configuration<span
class="code-tag">&lt;/value&gt;</span>
			<span class="code-tag">&lt;/list&gt;</span>
		<span class="code-tag">&lt;/property&gt;</span>
	<span class="code-tag">&lt;/bean&gt;</span>
</pre>
</div></div>
<p>To define a new transport endpoint in the WSDL document follow these two steps:<br/>
a) Set the soap:binding transport attribute to the transport URL value (<a href="http://cxf.apache.org/transports/TRANSPORT_PREFIX"
class="external-link" rel="nofollow">http://cxf.apache.org/transports/TRANSPORT_PREFIX</a>)<br/>
b) The Port address element should be bound to namespace equals to transport URL in WSDL XML</p>

<p>Sample:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
&lt;wsdl:definitions 
    <span class="code-keyword">xmlns:transport</span>=<span class="code-quote">"http://cxf.apache.org/transports/TRANSPORT_PREFIX"</span>
…&gt; …
…
<span class="code-tag">&lt;wsdl:binding name=<span class="code-quote">"GreeterPortBinding"</span>
type=<span class="code-quote">"tns: GreeterPortType"</span>&gt;</span>
        <span class="code-tag">&lt;soap:binding style=<span class="code-quote">"document"</span>
transport=<span class="code-quote">"http://cxf.apache.org/transports/TRANSPORT_PREFIX"</span>/&gt;</span>
…
<span class="code-tag">&lt;wsdl:service name=<span class="code-quote">"GreeterService"</span>&gt;</span>
       <span class="code-tag">&lt;wsdl:port binding=<span class="code-quote">"tns:GreeterPortBinding"</span>
name=<span class="code-quote">"GreeterPort"</span>&gt;</span>
           &lt;transport:address
…
</pre>
</div></div>

<h2><a name="CustomCXFTransport-ConduitandDestinationLifecycle"></a>Conduit
and Destination Lifecycle</h2>
<p>The conduit and destination lifecycle can be started by the TransportFactory during
every client or service creation. The TransportFactory can either create a conduit and destination
for each request or cache them based on service endpoint information.</p>

<h2><a name="CustomCXFTransport-ConcurrencyAspects"></a>Concurrency Aspects</h2>
<p>Conduit and destination objects can by concurrently accessed by multiple threads.
Implementations should care about concurrent correlations maps and/or synchronization primitives.</p>

<h2><a name="CustomCXFTransport-References"></a>References</h2>
<ol>
	<li>CXF transport implementations: package <em>org.apache.cxf.transport.*</em></li>
	<li>CXF Local Transport: <a href="http://cxf.apache.org/docs/local-transport.html"
class="external-link" rel="nofollow">http://cxf.apache.org/docs/local-transport.html</a></li>
</ol>

    </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/CXF/Custom+CXF+Transport">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=25200212&revisedVersion=8&originalVersion=7">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CXF/Custom+CXF+Transport?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message