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 > Custom Transport
Date Tue, 18 Sep 2012 16:36: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/Custom+Transport">Custom
Transport</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~ashakirin">Andrei
Shakirin</a>
    </h4>
        <br/>
                         <h4>Changes (38)</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" >* Step4: The CXF runtime invokes _Conduit.prepare()_
and passes the outgoing message as an argument <br>* Step5: Conduit sets own OutputStream
(normally extended CachedOutputStream) as the 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 the outgoing message, calls the interceptor chain and invokes
Conduit.close(Message) method for the outgoing message.  <br>* Step7: Finally, _OutputStream.doClose()_
for the outgoing message is invoked <br>* 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-added-lines" style="background-color: #dfd;">*
Step6: CXF runtime processes outgoing message, calls the interceptor chain and writes outgoing
message to conduit’s OutputStream stream. Messaging in CXF is stream-oriented; therefore
the message normally is proceed and sent not as one bunch, but as a stream. The last bytes
of the message can still be in processing by sender, but the first already sent to recipient.
Basically it is responsibility of Conduit how to send the message: using streaming or collecting
the whole message and send it at once <br>* Step7: When CXF runtime completely proceeded
outgoing message, it invokes _Conduit.close(Message)_ method. It means that the message is
completely written into _OutputStream_. Correspondingly, _OutputStream.doClose()_ method will
be called <br>* Step8: In the _doClose()_ method, Conduit sends the rest of the message
(or whole message) to recipient <br></td></tr>
            <tr><td class="diff-unchanged" >* Step9: In case of one-way communication
exchange will be closed. Skip to Step 14 <br>* Step10: In case of request-response communication,
the conduit will wait for the service response in a synchronous or asynchronous manner <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >* Step12: If a fault is instead received,
the Conduit creates a new Message, sets its context and places it as a fault message in exchange
as in-fault message <br>* Step13: Conduit notifies incomingObserver (that is ClientImpl
object) about the 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 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-added-lines" style="background-color: #dfd;">*
Step14: Conduit implementation decreases the reference count with the network connection,
potentially closing the connection if the count is zero <br></td></tr>
            <tr><td class="diff-unchanged" >* Step15: The JAX-WS client code receives
the response in sync or async style  <br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >* Step4: As soon as the CXF runtime
activates the endpoint (adds a listener, etc) the _Destination.activate()_ method will be
automatically invoked <br>* Step5: The implementation of _Destination.activate()_ normally
opens network transport connections and listens to incoming requests <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step6: When a request comes,
the destination creates a message, sets the content and notifies message observer (that is
<span class="diff-changed-words"><span class="diff-added-chars"style="background-color:
#dfd;">_</span>ChainInitializationObserver<span class="diff-added-chars"style="background-color:
#dfd;">_</span></span> object) via _incomingObserver.onMessage()_ about request.
<span class="diff-added-words"style="background-color: #dfd;">Message content is saved
as a stream; therefore runtime and business logic can start processing even not completely
received message.</span> Normally an incoming connection is saved in a correlation map
to be extracted for the <span class="diff-added-words"style="background-color: #dfd;">sending
of</span> appropriate <span class="diff-changed-words">response<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">.</span></span>
<br></td></tr>
            <tr><td class="diff-changed-lines" >* Step7: The business service
implementation will be called with the request <span class="diff-changed-words">message<span
class="diff-added-chars"style="background-color: #dfd;"> in stream form</span>.</span>
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 <span class="diff-changed-words">exception<span
class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">.</span></span>
<br></td></tr>
            <tr><td class="diff-unchanged" >* Step8: The CXF Runtime requests
a back-channel conduit from the destination via _Destination.getInbuiltBackChannel()_ <br>*
Step9: The Back-channel conduit&#39;s _prepare()_ method will be called with a response
message as argument <br>* Step10: Back-channel conduit sets its own OutputStream as
a message context <br></td></tr>
            <tr><td class="diff-changed-lines" >* Step11: CXF runtime processes
the response message, calls the interceptor chain and invokes _Conduit.close(Message)_ for
the response <span class="diff-changed-words">message<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">.</span></span>
<br></td></tr>
            <tr><td class="diff-unchanged" >* Step12. Finally _OutputStream.doClose()_
method for the response message is invoked <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">*
Step13: In _doClose()_ 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. An appropriate
incoming connection normally is extracted from a correlation map. <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">*
Step13: In _doClose()_ method the _OutputStream_ class has access to the marshaled response
message and will send this message through the network as a response to the client. In case
of streaming, the part of the message can be already sent to the network at this time, and
Conduit just sends the last part and closes the sending. Normally incoming connection for
specified protocol is cached and created only if necessary <br></td></tr>
            <tr><td class="diff-unchanged" > <br>h2. Registration of Transport
Factory <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >     DestinationFactoryManagerImpl
dfm = bus.getExtension(DestinationFactoryManagerImpl.class); <br>     CustomTransportFactory
customTransport = new CustomTransportFactory(); <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">dfm.registerDestinationFactory(&quot;http://cxf.apache.org/transports/TRANSPORT_PREFIX&quot;,</span>
<span class="diff-added-words"style="background-color: #dfd;">dfm.registerDestinationFactory(TRANSPORT_IDENTIFIER,</span>
customTransport); <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">
    dfm.registerDestinationFactory(&quot;http://cxf.apache.org/transports/TRANSPORT_PREFIX/configuration&quot;,
customTransport); <br></td></tr>
            <tr><td class="diff-unchanged" > <br>     ConduitInitiatorManager
extension = bus.getExtension(ConduitInitiatorManager.class); <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">extension.registerConduitInitiator(&quot;http://cxf.apache.org/transports/TRANSPORT_PREFIX&quot;,</span>
<span class="diff-added-words"style="background-color: #dfd;">extension.registerConduitInitiator(TRANSPORT_IDENTIFIER,</span>
customTransport); <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">
    extension.registerConduitInitiator(&quot;http://cxf.apache.org/transports/TRANSPORT_PREFIX/configuration&quot;,
customTransport); <br></td></tr>
            <tr><td class="diff-unchanged" >{code} <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Where
TRANSPORT_PREFIX is the protocol of the new transport (http, https, jms, udp). <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">TRANSPORT_IDENTIFIER
is unique transport id (normally in form “http://apache.org/transports/PROTOCOL_PREFIX”).
<br></td></tr>
            <tr><td class="diff-unchanged" > <br>For Spring configuration,
the following could be used instead: <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >		&lt;property name=&quot;transportIds&quot;&gt;
<br>			&lt;list&gt; <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">
		&lt;value&gt;http http://cxf.apache.org/transports/TRANSPORT_PREFIX&lt;/value&gt;
<br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">&lt;value&gt;http://cxf.apache.org/transports/TRANSPORT_PREFIX/configuration&lt;/value&gt;</span>
<span class="diff-added-words"style="background-color: #dfd;">&lt;value&gt;TRANSPORT_IDENTIFIER&lt;/value&gt;</span>
<br></td></tr>
            <tr><td class="diff-unchanged" >			&lt;/list&gt; <br>
	&lt;/property&gt; <br>	&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 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 (http://cxf.apache.org/transports/TRANSPORT_PREFIX)
<br>b) The Port address element should be bound to namespace equal to the transport
URL in the WSDL XML <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">h2.
TransportFactory selection <br>As far as binding TransportFactory is found, CXF looking
for protocol TransportFactory responsible for physical network communication. In this case
important is method _TransportFactory.getUriPrefixes()_. This method returns list of protocol
prefixes supported by this TransportFactory.  <br>When CXF client or service try to
communicate using URL with specified protocol prefix (http://, https://, jms://, local://),
CXF looks into registered transport factories map and gets the right one for this prefix.
If no TransportFactory for this protocol is found, CXF throws corresponded exception. <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">Sample:</span>
<span class="diff-added-words"style="background-color: #dfd;"> </span> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Client
configuration: <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-changed-words">{code<span
class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">:xml</span>}</span>
<br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">&lt;jaxws:client
id=&quot;FlightReservationClient&quot; <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">&lt;wsdl:definitions</span>
<span class="diff-added-words"style="background-color: #dfd;">xmlns:serviceNamespace=&quot;http://www.apache.org/cxf/samples/FlightReservation&quot;</span>
<br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">
   xmlns:transport=&quot;http://cxf.apache.org/transports/TRANSPORT_PREFIX&quot; …&gt;
… <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">
<br>serviceClass=&quot;org.apache.cxf.samples.flightreservation.FlightReservation&quot;
<br>	serviceName=&quot;serviceNamespace:FlightReservationService&quot; endpointName=&quot;serviceNamespace:FlightReservationSOAP&quot;&gt;
<br>	address=&quot;http://localhost:8040/services/FlightReservationService&quot;&gt;
<br>&lt;/jaxws:client&gt; <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;">&lt;wsdl:binding
name=&quot;GreeterPortBinding&quot; type=&quot;tns: GreeterPortType&quot;&gt;
<br>        &lt;soap:binding style=&quot;document&quot; transport=&quot;http://cxf.apache.org/transports/TRANSPORT_PREFIX&quot;/&gt;
<br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">{code}
<br> <br>TransportFactory class: <br>{code} <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;">&lt;wsdl:service
name=&quot;GreeterService&quot;&gt; <br>       &lt;wsdl:port binding=&quot;tns:GreeterPortBinding&quot;
name=&quot;GreeterPort&quot;&gt; <br>           &lt;transport:address
location=&quot;LOCATION_URL&quot;&gt; <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">
   private static final Set&lt;String&gt; URI_PREFIXES = new HashSet&lt;String&gt;();
<br>    static { <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">…</span>
<span class="diff-added-words"style="background-color: #dfd;">URI_PREFIXES.add(&quot;http://&quot;);</span>
<br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">
       URI_PREFIXES.add(&quot;https:&quot;); <br>    }     <br>    public
Set&lt;String&gt; getUriPrefixes() { <br>        return URI_PREFIXES; <br>
   } <br></td></tr>
            <tr><td class="diff-unchanged" >{code} <br> <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;">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-added-lines" style="background-color: #dfd;">Destinations
are normally created by service on startup and released by shutdown. Conduits can be either
recreated for each request or cached based on endpoint information for whole client life time.
Clients can make concurrent calls to endpoints using different protocols and bound them to
different conduits. <br></td></tr>
            <tr><td class="diff-unchanged" > <br>h2. Concurrency Aspects
<br></td></tr>
            <tr><td class="diff-changed-lines" >Conduit and destination objects
can by concurrently accessed by multiple threads. Implementations should care about <span
class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">concurrent
correlations maps and/or synchronization primitives.</span> <span class="diff-added-words"style="background-color:
#dfd;">thread safety of the class.</span> <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">h2.
Streaming <br>It is strongly recommended to don’t break streaming in Conduit and Destination
implementations, if physical protocol supports it. CXF is completely streaming oriented –
it causes high performance and scalability. <br> <br></td></tr>
            <tr><td class="diff-unchanged" >h2. References <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">CXF
transport implementations: package _org.apache.cxf.transport.*_ <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">What
is the start point to understand the CXF transport layer and implement own transport? I would
recommend to read CXF documentation [CXF transports overview#http://cxf.apache.org/docs/transports.html]
and analyze source code of existing CXF transports (Local and JMS once are more straightforward).
They are located into packages: org.apache.cxf.transport.local and org.apache.cxf.transport.jms
correspondingly <br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <p>This page summarizes an experience and use cases of implementing a new custom
CXF transport.</p>


<h2><a name="CustomTransport-UseCases"></a>Use Cases</h2>
<p>Basically there are two main use cases for implementing a new CXF transport:</p>
<ol>
	<li>Providing a new physical protocol not yet supported by CXF (udp or ftp, for example).
Some such cases can be solved by using integration with a corresponding Camel component, but
if no such component is available or workable creating a new custom CXF transport should be
considered.</li>
	<li>Supporting tight integration with another framework (like JBI or Camel).  In this
case integration would be kept transparent for CXF applications - they would just speak directly
with the target framework on the transport level. Here, the Transport implementation would
be responsible for converting and transferring CXF exchange, messages and faults to target
framework.</li>
</ol>


<p>Presently the CXF distribution provides a transport implementation for the following
protocols: HTTP(S), JBI, JMS and Local(inside one JVM). Camel additionally implements a CXF
transport for Camel exchanges.</p>

<h2><a name="CustomTransport-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 would be to use a subclass of OutputStream extending CachedOutputStream.
The custom stream will be fed the message and provided the 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/27839372/cxf-transport-class-diagram.jpg?version=1&amp;modificationDate=1330266014000"
style="border: 0px solid black" /></span></p>


<h2><a name="CustomTransport-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/27839372/cxf-transport-view.jpg?version=1&amp;modificationDate=1330266062000"
style="border: 0px solid black" /></span></p>


<h3><a name="CustomTransport-SimplifiedClientWorkflow%3A"></a>Simplified
Client Workflow:</h3>
<ul>
	<li>Step1: The 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: The CXF runtime selects the correct TransportFactory based on some criteria
(described below)</li>
	<li>Step3: The CXF runtime calls <em>TransportFactory.getConduit()</em>
method to obtain the conduit</li>
	<li>Step4: The CXF runtime invokes <em>Conduit.prepare()</em> and passes
the outgoing message as an argument</li>
	<li>Step5: Conduit sets own OutputStream (normally extended CachedOutputStream) as
the outgoing message content</li>
	<li>Step6: CXF runtime processes outgoing message, calls the interceptor chain and
writes outgoing message to conduit’s OutputStream stream. Messaging in CXF is stream-oriented;
therefore the message normally is proceed and sent not as one bunch, but as a stream. The
last bytes of the message can still be in processing by sender, but the first already sent
to recipient. Basically it is responsibility of Conduit how to send the message: using streaming
or collecting the whole message and send it at once</li>
	<li>Step7: When CXF runtime completely proceeded outgoing message, it invokes <em>Conduit.close(Message)</em>
method. It means that the message is completely written into <em>OutputStream</em>.
Correspondingly, <em>OutputStream.doClose()</em> method will be called</li>
	<li>Step8: In the <em>doClose()</em> method, Conduit sends the rest of
the message (or whole message) to recipient</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 a synchronous or asynchronous manner</li>
	<li>Step11: If a successful 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: If a fault is instead received, the Conduit creates a new Message, sets
its context and places it as a fault message in exchange as in-fault message</li>
	<li>Step13: Conduit notifies incomingObserver (that is ClientImpl object) about the
response using <em>incomingObserver.onMessage()</em> call</li>
	<li>Step14: Conduit implementation decreases the reference count with the network connection,
potentially closing the connection if the count is zero</li>
	<li>Step15: The JAX-WS client code receives the response in sync or async style</li>
</ul>


<h3><a name="CustomTransport-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: The CXF runtime selects correct TransportFactory based on some criteria
(described below)</li>
	<li>Step3: The CXF runtime calls <em>TransportFactory.getDestination()</em>
method to obtain the destination</li>
	<li>Step4: As soon as the CXF runtime activates the endpoint (adds a listener, etc)
the <em>Destination.activate()</em> method will be automatically invoked</li>
	<li>Step5: The implementation of <em>Destination.activate()</em> normally
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 message observer (that is <em>ChainInitializationObserver</em> object)
via <em>incomingObserver.onMessage()</em> about request. Message content is saved
as a stream; therefore runtime and business logic can start processing even not completely
received message. Normally an incoming connection is saved in a correlation map to be extracted
for the sending of appropriate response</li>
	<li>Step7: The business service implementation will be called with the request message
in stream form. 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 <em>OutputStream</em>
class has access to the marshaled response message and will send this message through the
network as a response to the client. In case of streaming, the part of the message can be
already sent to the network at this time, and Conduit just sends the last part and closes
the sending. Normally incoming connection for specified protocol is cached and created only
if necessary</li>
</ul>


<h2><a name="CustomTransport-RegistrationofTransportFactory"></a>Registration
of Transport Factory</h2>
<p>There are two ways to register a 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(TRANSPORT_IDENTIFIER, customTransport);

     ConduitInitiatorManager extension = bus.getExtension(ConduitInitiatorManager.class);
     extension.registerConduitInitiator(TRANSPORT_IDENTIFIER, customTransport);
</pre>
</div></div>
<p>TRANSPORT_IDENTIFIER is unique transport id (normally in form “<a href="http://apache.org/transports/PROTOCOL_PREFIX"
class="external-link" rel="nofollow">http://apache.org/transports/PROTOCOL_PREFIX</a>”).</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>TRANSPORT_IDENTIFIER<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>

<h2><a name="CustomTransport-TransportFactoryselection"></a>TransportFactory
selection</h2>
<p>As far as binding TransportFactory is found, CXF looking for protocol TransportFactory
responsible for physical network communication. In this case important is method <em>TransportFactory.getUriPrefixes()</em>.
This method returns list of protocol prefixes supported by this TransportFactory. <br/>
When CXF client or service try to communicate using URL with specified protocol prefix (<a
href="http://" class="external-link" rel="nofollow">http://</a>, <a href="https://"
class="external-link" rel="nofollow">https://</a>, jms://, local://), CXF looks into
registered transport factories map and gets the right one for this prefix. If no TransportFactory
for this protocol is found, CXF throws corresponded exception.</p>

<p>Client configuration:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
&lt;jaxws:client id=<span class="code-quote">"FlightReservationClient"</span>
	xmlns:serviceNamespace=<span class="code-quote">"http:<span class="code-comment">//www.apache.org/cxf/samples/FlightReservation"</span>
</span>
serviceClass=<span class="code-quote">"org.apache.cxf.samples.flightreservation.FlightReservation"</span>
	serviceName=<span class="code-quote">"serviceNamespace:FlightReservationService"</span>
endpointName=<span class="code-quote">"serviceNamespace:FlightReservationSOAP"</span>&gt;
	address=<span class="code-quote">"http:<span class="code-comment">//localhost:8040/services/FlightReservationService"</span>&gt;
</span>&lt;/jaxws:client&gt;
…
</pre>
</div></div>

<p>TransportFactory class:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
…
    <span class="code-keyword">private</span> <span class="code-keyword">static</span>
<span class="code-keyword">final</span> Set&lt;<span class="code-object">String</span>&gt;
URI_PREFIXES = <span class="code-keyword">new</span> HashSet&lt;<span class="code-object">String</span>&gt;();
    <span class="code-keyword">static</span> {
        URI_PREFIXES.add(<span class="code-quote">"http:<span class="code-comment">//"</span>);
</span>        URI_PREFIXES.add(<span class="code-quote">"https:"</span>);
    }    
    <span class="code-keyword">public</span> Set&lt;<span class="code-object">String</span>&gt;
getUriPrefixes() {
        <span class="code-keyword">return</span> URI_PREFIXES;
    }
</pre>
</div></div>

<h2><a name="CustomTransport-ConduitandDestinationLifecycle"></a>Conduit
and Destination Lifecycle</h2>
<p>Destinations are normally created by service on startup and released by shutdown.
Conduits can be either recreated for each request or cached based on endpoint information
for whole client life time. Clients can make concurrent calls to endpoints using different
protocols and bound them to different conduits.</p>

<h2><a name="CustomTransport-ConcurrencyAspects"></a>Concurrency Aspects</h2>
<p>Conduit and destination objects can by concurrently accessed by multiple threads.
Implementations should care about thread safety of the class.</p>

<h2><a name="CustomTransport-Streaming"></a>Streaming</h2>
<p>It is strongly recommended to don’t break streaming in Conduit and Destination
implementations, if physical protocol supports it. CXF is completely streaming oriented –
it causes high performance and scalability.</p>

<h2><a name="CustomTransport-References"></a>References</h2>
<p>What is the start point to understand the CXF transport layer and implement own transport?
I would recommend to read CXF documentation <span class="error">&#91;CXF transports
overview#http://cxf.apache.org/docs/transports.html&#93;</span> and analyze source
code of existing CXF transports (Local and JMS once are more straightforward). They are located
into packages: org.apache.cxf.transport.local and org.apache.cxf.transport.jms correspondingly</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/Custom+Transport">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=27839372&revisedVersion=4&originalVersion=3">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CXF20DOC/Custom+Transport?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message