Web service request processing flow in CXF

Source: Internet
Author: User

Web services are essentially HTTP requests, except for Web service-specific specifications, such as the XML file format in which the server communicates with both clients to complete a description of a Web service invocation. Of course, this XML also has a specific format, as to what this particular format depends on which data binding method is used. In CXF, this is data binding, which the individual feels is more understandable than the serialization and deserialization of a Java object.

This article analyzes how CXF completes the processing of a Web service (SOAP type) request from the source code (CXF version 2.7.6), noting that the processing of the request is analyzed, and does not include how the request was generated, and that the analysis will begin with a request received from the CXF server. In CXF, the processing of an HTTP request is implemented using jetty, whose processing request is handler to Org.apache.cxf.transport.http_jetty. The Jettyhttphandler is called Org.apache.cxf.transport.http_jetty in its handle method. Jettyhttpdestination's Doservice () method, one of the most important lines of code is to invoke the Servicerequest (context, req, resp) method, below is the source:

protected void Servicerequest (final ServletContext context, final httpservletrequest req , final HttpServletResponse resp) throws IOException {Request baserequest = (req instanc EOF Request)? (Request) Req:getcurrentrequest (), if (Log.isloggable (Level.fine)) {log.fine ("Service http Request on thread:" + Thread. CurrentThread ());} Message inmessage = retrievefromcontinuation (req), if (inmessage = = null) {inmessage = new Messageimpl (); Exchangeimpl Exchange = new Exchangeimpl (); Exchange.setinmessage (inmessage); Setupmessage (inmessage, context, req, RESP);((Messageimpl) inmessage). Setdestination (this); Exchange.setsession (new HTTPSession (req));} The real class of try {//Processing message//incomingobserver is Org.apache.cxf.transport.ChainInitiationObserverincomingObserver.onMessage ( Inmessage); Resp.flushbuffer (); baserequest.sethandled (true);} catch (Suspendedinvocationexception ex) {//omit ...}//Omit ...}

In this method, the creation of the message, the initialization setting (Setupmessage), the creation of exchange, session, and the placement of the message and session into the Exchange object are completed. The initialization setting of the Message object (in the Setupmessage method) is very important, and a lot of information is placed into the message, such as the HTTP request object, the response object, the requested address, and so on, see the Setupmessage method, Call the Chaininitiationobserver.onmessage () method when the required object creation is complete, with the following source code:

public void OnMessage (Message m) {Bus Origbus = Busfactory.getandsetthreaddefaultbus (bus); Classloaderholder Origloader = null;try {if (loader! = null) {Origloader = Classloaderutils.setthreadcontextclassloader ( loader);} Interceptorchain Phasechain = null;//If the interceptor chain is not empty, check its status if it is stopped or suspended to restore if (m.getinterceptorchain ()! = null) {Phasechain = M.getinterceptorchain ();/To make sure the phase chain are run by one thread oncesynchronized (phasechain) {if (Phasecha In.getstate () = = InterceptorChain.State.PAUSED | | Phasechain.getstate () = = InterceptorChain.State.SUSPENDED) {phasechain.resume (); return;}}} Re-create the message object, M is the Messageimpl object, and CXF supports the SOAP protocol service with RESTful services//So to create a more specific message object depending on which type is used, here, If it is the SOAP protocol, the SoapMessage object is created//if the RESTful service creates a Xmlmessage object, message message = Getbinding (). CreateMessage (m); Exchange Exchange = Message.getexchange (), if (exchange = = NULL) {exchange = new Exchangeimpl (); M.setexchange (Exchange);} Exchange.setinmessage (message);//Populate the Exchage object with information setexchangeproperties (Exchange,message); Interceptorprovider DBP = Null;if (Endpoint.getservice (). getdatabinding () instanceof Interceptorprovider) {/ /data-bound object is not null for DBP = (interceptorprovider) endpoint.getservice (). getdatabinding (); Setup chainif (DBP = = null) {Phasechain = Chaincache.get (Bus.getextension (Phasemanager.class). Getinphases (), Bus.getininterceptors (), Endpoint.getservice (). Getininterceptors (), Endpoint.getininterceptors (), getBinding (). Getininterceptors ());} else {//the bus, Service, Endpoint, protocol bindings, all input interceptors in data binding are aggregated into the interceptor chain Phasechain = Chaincache.get (Bus.getextension ( Phasemanager.class). Getinphases (), Bus.getininterceptors (), Endpoint.getservice (). Getininterceptors (), Endpoint.getininterceptors (), getbinding (). Getininterceptors (), dbp.getininterceptors ());} Set the interceptor chain into message Message.setinterceptorchain (Phasechain);p Hasechain.setfaultobserver ( Endpoint.getoutfaultobserver ()); Addtochain (phasechain, message);//Dointercept method of invoking the Interceptor chain, In this method, the Handmessage method of each interceptor in the chain is called sequentially. phasechain.dointercept (message);} finally {if (Origbus! = Bus) {BuSfactory.setthreaddefaultbus (Origbus);} if (Origloader! = null) {Origloader.reset ();}}}

Here we know how the interceptor is called, but it is strange that we have not seen the invocation of the service, and when the dointercept execution completes the OnMessage () method exits, the Servicerequest method is basically done. As you can guess, the invocation of the service is done in the Dointercept method, and the exact point is done in the Handmessage () method of an interceptor in the Interceptor link. Using interceptors to implement certain features of the framework itself is somewhat similar to interceptors in struts2 (not the way interceptors are implemented).

The real situation is that the interceptor chain obtains a Org.apache.cxf.interceptor.ServiceInvokerInterceptor object from the service registered interceptor, and the invocation of the services is done by the interceptor.


public void Handlemessage (final message message) {Final Exchange exchange = Message.getexchange (); final Endpoint Endpoint = Exchange.get (endpoint.class); final Service service = Endpoint.getservice ();//        Gets the Call object org.apache.cxf.jaxws.JAXWSMethodInvokerfinal Invoker Invoker = Service.getinvoker (); Create a Runnable executable object Runnable invocation = new Runnable () {public void run () {Exchange Runableex = Message.getexchange ();// Call the Invoke method of Jaxwsmethodinvoker, whose return value is the result of the Messagecontentslist object objects result = Invoker.invoke (Runableex, Getinvokee (message)); if (!exchange.isoneway ()) {//If it is not one-way exchange, that is bidirectional, that is, the output Endpoint EP = Exchange.get (Endpoint.class);// Create output Messagemessage outmessage = Runableex.getoutmessage (), if (outmessage = = null) {outmessage = new Messageimpl (); O Utmessage.setexchange (Exchange); outmessage = Ep.getbinding (). CreateMessage (Outmessage); Exchange.setoutmessage ( Outmessage);} Copyjaxwsproperties (message, Outmessage), if (result! = null) {Messagecontentslist reslist = null;if (Result InstanCeof messagecontentslist) {reslist = (messagecontentslist) result;} else if (result instanceof List) {reslist = new Message Contentslist ((list<?>) result); else if (Result.getclass (). IsArray ()) {reslist = new Messagecontentslist ((object[]) result);} else {                            Outmessage.setcontent (Object.class, result);                   }if (reslist! = null) {//Place the result in Outmessage outmessage.setcontent (List.class, reslist);}} }}};//get executor from service, not nullexecutor executor = getexecutor (endpoint);//Get executor from exchange for Nullexecutor Executor2 = Exchange.get (Executor.class), if (Executor2 = = Executor | | Executor = = NULL) {//already executing on the Appro Priate Executorinvocation.run ();} else {//execute Exchange.put (Executor.class, Executor); futuretask<object> o = new futuretask<object> (invocation, null) {@Overrideprotected void done () {Super.done (); synchronized (this) {This.notifyall ();}}; Synchronized (o) {//executes futuretask, and finally executes the Run method just created runnable, returning to the Run method Executor.execute (o);//Omit ...}} 

Invoke Jaxwsmethodinvoker's Invoke (Exchange Exchange, Object O) inherits from the Abstractinvoker class, as follows:

public object Invoke (Exchange Exchange, Object O) {//Get Service Implementation class object, default using Singleton factory to create final object serviceobject = Getserviceobject ( Exchange); try {//Get method information Bindingoperationinfo bop = Exchange.get (Bindingoperationinfo.class); Methoddispatcher MD = (methoddispatcher) exchange.get (Service.class). Get (MethodDispatcher.class.getName ());// Find out how to execute method m = Bop = = null? Null:md.getMethod (BOP), if (M = = NULL && BOP = = null) {Log.severe (New Message ("Missing_binding_operation", LOG). t Ostring ()); throw new Fault ("Exception_invoking_object", "LOG", "No binding operation Info", "Unknown Method", " Unknown "));} list<object> params = null;if (o instanceof List) {params = Castutils.cast ((list<?>) o);} else if (o! = null) { params = new Messagecontentslist (o);} m = Adjustmethodandparams (M, Exchange, params);//method m = (Method) bop.getoperationinfo (). GetProperty ( Method.class.getName ()); m = Matchmethod (M, serviceobject);//re-match the method//To pass the service object, method, method parameter to the return invoke (Exchange, Serviceobject, M, params);} Finally {releaseserviceobject (Exchange, Serviceobject);}}

The service object, method, and method parameters are passed in to the overloaded protected object invoke (Exchange Exchange, Final Object Serviceobject, Methods M, list< Object> Params Method The method is located in the Jaxwsmethodinvoker class, and the call method of the parent class is called, and finally the Performinvocation method of Abstractinvoker is called, as follows:

Protected object Performinvocation (Exchange Exchange, Final Object Serviceobject, Method m, object[] paramArray) throws Ex ception {ParamArray = Insertexchange (M, ParamArray, Exchange);//Omit ... return M.invoke (Serviceobject, ParamArray);// Implement object methods by reflection call service}

Here, you should know how the service is invoked, and then how does the service return after it is called? Now go back to the Runnable object created in the Serviceinvokerinterceptor interceptor, because Exchange is bidirectional, so Outmessage is created. The result of the service execution is then encapsulated into a Messagecontentslist object placed in the content of the outmessage.

Another Org.apache.cxf.interceptor.OutgoingChainInterceptor interceptor is also registered in the input interceptor chain:


public void Handlemessage (Message message) {Exchange ex = Message.getexchange (); Bindingoperationinfo binding = Ex.get (Bindingoperationinfo.class); if (null! = Binding && NULL! = Binding.getoperationinfo () && binding.getoperationinfo (). IsOneWay ()) {closeinput (message); return;} Message out = Ex.getoutmessage (), if (out! = null) {getbackchannelconduit (message); if (binding! = null) {Out.put (Messagein Fo.class, Binding.getoperationinfo (). GetOutput ()); Out.put (Bindingmessageinfo.class, Binding.getoutput ());} Interceptorchain Outchain = Out.getinterceptorchain (), if (Outchain = = null) {//For output messages, the output interceptor chain is its input, which is similar to the collection of input interceptors, This only over here is//Get bus, Service, Endpoint, protocol binding, output interceptor in data binding Outchain = Outgoingchaininterceptor.getchain (ex, chaincache); o Ut.setinterceptorchain (Outchain);} Responsible for collecting the output interceptor and creating the output interceptor chain, then calling its Dointercept method outchain.dointercept (out);}}

There are several interceptors in the output interceptor chain that are output to the client:

1. Org.apache.cxf.interceptor.MessageSenderInterceptor

A getconduit (message) is executed in its Handlemessage method. Prepare (message), and OutputStream is set in the Prepare method to the message, And passed in the HttpServletResponse object.


public void prepare (Message message) throws IOException {Message.put (http_response, RESPONSE); OutputStream OS = Message.getcontent (Outputstream.class), if (OS = = null) {message.setcontent (Outputstream.class,    new Wrappedoutputstream (message, Response));}}

conduit Implementation class is Org.apache.cxf.transport.http.AbstractHTTPDestination.BackChannelConduit


2. Org.apache.cxf.interceptor.StaxOutInterceptor
Creates a Xmlstreamwriter object and sets it into the message


3. Org.apache.cxf.interceptor.BareOutInterceptor
Gets the return result of the service call, using the Xmlstreamwriter object to write the wrapped return result in XML format to Wrappedoutputstream. And Wrappedoutputstream is wrapping the Httpservletrespone.getoutputstream () object
That is, the results are returned to the client.

When the output interceptor chain executes, it returns to the Jettyhttpdestination Servicerequest () method, refreshes the httpservletrespone and marks the request processing complete.

Web service request processing flow in CXF

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.