Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • Step1: The JAX-WS client invokes a service, in this manner for example:
    Code Block
    borderStylesolid
            URL wsdlURL = this.getClass().getResource("/HelloWorld.wsdl");
            HelloWorldService service = new HelloWorldService(wsdlURL, SERVICE_NAME);        
            HelloWorld hw = service.getHelloWorldPort();       
            String result = hw.sayHi(TEST_REQUEST); }}
    
  • Step2: The CXF runtime selects the correct TransportFactory based on some criteria (described below)
  • Step3: The CXF runtime calls TransportFactory.getConduit() method to obtain the conduit
  • Step4: The CXF runtime invokes Conduit.prepare() and passes the outgoing message as an argument
  • Step5: Conduit sets own OutputStream (normally extended CachedOutputStream) as the outgoing message content
  • Step6: CXF runtime processes the 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
  • Step7: When CXF runtime completely proceeded outgoing message, it invokes Conduit.close(Message) method for . It means that the outgoing message .Step7: Finallyis completely written into OutputStream. Correspondingly, OutputStream.doClose() for the outgoing message is invoked method will be called
  • 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 protocolConduit sends the rest of the message (or whole message) to recipient
  • Step9: In case of one-way communication exchange will be closed. Skip to Step 14
  • Step10: In case of request-response communication, the conduit will wait for the service response in a synchronous or asynchronous manner
  • 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
  • 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
  • Step13: Conduit notifies incomingObserver (that is ClientImpl object) about the response using incomingObserver.onMessage() call
  • Step14: Conduit .close(Message) method is invoked for incoming message. Normally the conduit implementation decreases the reference count with the servicenetwork connection, potentially closing the network connection if the count is zero.
  • Step15: The JAX-WS client code receives the response in sync or async style

...

  • Step1: JAX-WS service is registered for example in this way:
    Code Block
    borderStylesolid
    	HelloWorldImpl serverImpl = new HelloWorldImpl();
    	Endpoint.publish("udp://localhost:9000/hello", serverImpl);
    
  • Step2: The CXF runtime selects correct TransportFactory based on some criteria (described below)
  • Step3: The CXF runtime calls TransportFactory.getDestination() method to obtain the destination
  • Step4: As soon as the CXF runtime activates the endpoint (adds a listener, etc) the Destination.activate() method will be automatically invoked
  • Step5: The implementation of Destination.activate() normally opens network transport connections and listens to incoming requests
  • Step6: When a request comes, the destination creates a message, sets the content and notifies message observer (that is ChainInitializationObserver object) via incomingObserver.onMessage() 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.
  • 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.
  • Step8: The CXF Runtime requests a back-channel conduit from the destination via Destination.getInbuiltBackChannel()
  • Step9: The Back-channel conduit's prepare() method will be called with a response message as argument
  • Step10: Back-channel conduit sets its own OutputStream as a message context
  • Step11: CXF runtime processes the response message, calls the interceptor chain and invokes Conduit.close(Message) for the response message.
  • Step12. Finally OutputStream.doClose() method for the response message is invoked
  • Step13: In doClose() method the OutputStream class has access to the marshalled marshaled 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.. 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

Registration of Transport Factory

...

Code Block
borderStylesolid
     Bus bus = BusFactory.getThreadDefaultBus();
     DestinationFactoryManagerImpl dfm = bus.getExtension(DestinationFactoryManagerImpl.class);
     CustomTransportFactory customTransport = new CustomTransportFactory();
     dfm.registerDestinationFactory("http://cxf.apache.org/transports/TRANSPORT_PREFIX"IDENTIFIER, customTransport);
     dfm.registerDestinationFactory("http://cxf.apache.org/transports/TRANSPORT_PREFIX/configuration", customTransport);

     ConduitInitiatorManager extension = bus.getExtension(ConduitInitiatorManager.class);
     extension.registerConduitInitiator("http://cxf.apache.org/transports/TRANSPORT_PREFIX"IDENTIFIER, customTransport);
     extension.registerConduitInitiator("

TRANSPORT_IDENTIFIER is unique transport id (normally in form “http://

...

apache.org/transports/

...

Where TRANSPORT_PREFIX is the protocol of the new transport (http, https, jms, udp)PROTOCOL_PREFIX

...

Image Added”).

For Spring configuration, the following could be used instead:

Code Block
xml
xml
	<bean class="org.company.cxf.transport.CustomTransportFactory"
		lazy-init="false">
		<property name="transportIds">
			<list>
			<value>http http://cxf.apache.org/transports/TRANSPORT_PREFIX</value>
                	<value>http://cxf.apache.org/transports/TRANSPORT_PREFIX/configuration<  <value>TRANSPORT_IDENTIFIER</value>
			</list>
		</property>
	</bean>

To define a new transport endpoint in the WSDL document follow these two steps:
a) Set the soap:binding transport attribute to the transport URL value (http://cxf.apache.org/transports/TRANSPORT_PREFIXImage Removed)
b) The Port address element should be bound to namespace equal to the transport URL in the WSDL XML

Sample:

TransportFactory selection

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.
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.

Client configuration:

Code Block

<jaxws:client id="FlightReservationClient"
	xmlns:serviceNamespace
Code Block
xmlxml

<wsdl:definitions 
    xmlns:transport="http://cxfwww.apache.org/cxf/transportssamples/TRANSPORT_PREFIX" …> …
…
<wsdl:binding name="GreeterPortBinding" type="tns: GreeterPortType">
        <soap:binding style="document" transportFlightReservation"

serviceClass="org.apache.cxf.samples.flightreservation.FlightReservation"
	serviceName="serviceNamespace:FlightReservationService" endpointName="serviceNamespace:FlightReservationSOAP">
	address="http://cxf.apache.org/transports/TRANSPORT_PREFIX"/>
…
<wsdl:service name="GreeterService">localhost:8040/services/FlightReservationService">
</jaxws:client>
…

TransportFactory class:

Code Block

…
    private static final Set<String> URI_PREFIXES = new HashSet<String>();
    static {
        URI_PREFIXES.add("http://");
       <wsdl:port binding="tns:GreeterPortBinding" name="GreeterPort">
      URI_PREFIXES.add("https:");
    }    
    public Set<String> getUriPrefixes() {
      <transport:address location="LOCATION_URL">
…  return URI_PREFIXES;
    }

Conduit and Destination Lifecycle

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 Destinations are normally created by service on startup and released by shutdown. Conduits can be either recreated for each request or cache them cached based on service endpoint information for whole client life time. Clients can make concurrent calls to endpoints using different protocols and bound them to different conduits.

Concurrency Aspects

Conduit and destination objects can by concurrently accessed by multiple threads. Implementations should care about concurrent correlations maps and/or synchronization primitivesthread safety of the class.

Streaming

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.

References

CXF transport implementations: package What is the start point to understand the CXF transport layer and implement own transport? I would recommend to read CXF documentation //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