First, let's see what information is available to find the correct operation. Let me show you a typical http request. We will limit the scope of this tutorial to http requests as other transport protocols do it the same way.
POST /axis2/services/EchoXMLService/echoOMElement HTTP/1.1 User-Agent: Axis2 Host: 127.0.0.1 Content-Type: application/soap+xml; charset=UTF-8;action="EchoOMElement"; ..................... <?xml version='1.0' encoding='UTF-8'?> <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing"> <soapenv:Header> <wsa:To>http://127.0.0.1:5556/axis2/services/EchoXMLService/echoOMElement</wsa:To> <wsa:ReplyTo> <wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address> </wsa:ReplyTo> <wsa:MessageID>urn:uuid:AD147449058471C81E11506120248601</wsa:MessageID> <wsa:Action>urn:EchoOMElement</wsa:Action> </soapenv:Header> <soapenv:Body> <ns1:echoOMElement xmlns:ns1="http://org.apache.axis2/xsd"> <ns1:myValue>Isaac Asimov, The Foundation Trilogy</ns1:myValue> </ns1:echoOMElement> </soapenv:Body> </soapenv:Envelope>
What is the information available to identify the service and the operation?
Information Example ValueHTTP request uri | /axis2/services/EchoXMLService/echoOMElement |
SOAPAction | action="EchoOMElement" |
QName of the first child of SOAP Body element | <ns1:echoOMElement xmlns:ns1="http://org.apache.axis2/xsd"> |
If WS-Addressing is enabled the address of To EPR (Endpoint Reference) and Action element | <wsa:To>http://127.0.0.1:5556/axis2/services/EchoXMLService/echoOMElement</ wsa:To> <wsa:Action>urn:EchoOMElement</wsa:Action> |
This is the exact information we use inside Axis2 in order to find the proper destination. The four "dispatchers" inside Axis2 takes care of each and every piece of information mentioned above.
Information Dispatcher NameHTTP request uri | org.apache.axis2.engine.RequestURIBasedDispatcher |
SOAPAction | org.apache.axis2.engine.SOAPActionBasedDispatcher |
QName of the first child of SOAP Body element | org.apache.axis2.engine.SOAPMessageBodyBasedDispatcher |
If WS-Addressing is enabled the address of To EPR (Endpoint Reference) and Action element | org.apache.axis2.engine.AddressingBasedDispatcher |
All the dispatchers first try to find the service with the information it has. They do this if the dispatchers invoked before it had not found a service. If the service is already found, the findService method of the dispatcher will just pass through. Then it tries to find an operation within the service, if a service is found by then. Again, the dispatcher will do this only if other dispatchers invoked prior to it had not found an operation. Likewise, all the dispatchers put a collaborative effort in doing this. This will enable one dispatcher to find a service and another dipatcher to later find the operation. For example, RequestURIBasedDispatcher could find the service, but it has no information to find the operation. Then RequestURIBasedDispatcher will set the service it found to the message context (message context is used to keep the run time information of each and every message received by the engine). The other dispatchers extract the service information from the message context and try to find an operation.
RequestURIBasedDispatcher - It will get the request URI and tries to find the operation. First, it will remove the /axis2/services part from the URI. (Remember, "/axis2/services" can also be changed support your desired pattern). Then Axis2 takes rest of the URIs ("EchoXMLService/echoOMElement"), tries to search for a service which has the name "EchoXMLService". If found, it tries to find an operation named "echoOMElement" within the found service. SOAPActionBasedDispatcher - This dispatcher can only find the relevant operation, if another dispatcher is invoked before it had found a service, this will check for a operation "echoOMElement" within the service it gets from the message context. SOAPMessageBodyBasedDispatcher - This will get the QName of the first child of the SOAP body element and search through Axis2 configuration for a service and an operation. AddressingBasedDispatcher - This dispatcher will work only if WS-Addressing header are on the SOAP envelope and Addressing module is engaged. This will search for a service and operation, just like the RequestURIBasedDispatcher, except that it gets the information from the WS-Addressing header in the message. This will use the value of <wsa:To> to find the service and the value of <wsa:Action> to find the operation. One particular message may not contain all the information listed above, but must have least amount of information to identify the operation. And as I mentioned earlier, it can be a combination of two dispatchers that will ultimately find the service and operation. Let's check out some samples in oder to further understand how this works with different SOAP messages. Let's assume we have EchoXMLService deployed and it has echoOMElement as an operation. Example 1
POST /axis2/services/EchoXMLService HTTP/1.1 User-Agent: Axis2 Host: 127.0.0.1 Content-Type: application/soap+xml; charset=UTF-8;action="EchoOMElement" ; ...................... <?xml version='1.0' encoding='UTF-8'?> <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing"> <soapenv:Header /> <soapenv:Body> <ns1:echo xmlns:ns1="http://org.apache.axis2/xsd"> <ns1:myValue>Isaac Asimov, The Foundation Trilogy</ns1:myValue> </ns1:echo> </soapenv:Body> </soapenv:Envelope>
Here the RequestURIBasedDispatcher will find the service, but it has no information to find the operation. It will set the EchoXMLService in to message context as the service and pass through. Once SOAPActionBasedDispatcher gets its chance, it will first see that some one had found a service. Then having seen that, the operation has not been found, it tries to search for a operation from the SOAP action that it has received within the EchoXMLService. Example 2
POST /other/proxy/url HTTP/1.1 User-Agent: Axis2 Host: 127.0.0.1 Content-Type: application/soap+xml; charset=UTF-8;action=""; ..................... <?xml version='1.0' encoding='UTF-8'?> <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing"> <soapenv:Header> <wsa:To>http://127.0.0.1:5556/axis2/services/EchoXMLService</wsa:To> <wsa:ReplyTo> <wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address> </wsa:ReplyTo> <wsa:MessageID>urn:uuid:AD147449058471C81E11506120248601</wsa:MessageID> <wsa:Action>urn:EchoOMElement</wsa:Action> </soapenv:Header> <soapenv:Body> <ns1:echoOMElement xmlns:ns1="http://org.apache.axis2/xsd"> <ns1:myValue>Isaac Asimov, The Foundation Trilogy</ns1:myValue> </ns1:echoOMElement> </soapenv:Body> </soapenv:Envelope>
Here we are trying to send this SOAP message to a proxy and thus the http request URI can not be used to find either the service or the operation. At the same time the SOAP action is empty. But the user had send WS-Addressing headers and Addressing module is engaged in the receiving end. As you can see, value of <wsa:To> and <wsa:Action> headers can be used to find the correct service and the operation, without other information Successfulness of dispatching depends on the proper order of dispatchers in the execution chain. Now lets see how these can be ordered.
Dispatchers can be ordered in any way an administrator prefers. And he can decide which dispatchers to be included for dispatching and to remove rest of the dispatchers. To do this, simply edit the <phaseOrder> element found within axis2.xml. Here is a sample section from the default axis2.xml
<phaseOrder type="inflow"> <!-- System pre defined phases --> <phase name="Transport"> <handler name="RequestURIBasedDispatcher " class="org.apache.axis2.engine.RequestURIBasedDispatcher "> <order phase="Dispatch"/> </handler> <handler name="SOAPActionBasedDispatcher " class="org.apache.axis2.engine.SOAPActionBasedDispatcher "> <order phase="Dispatch"/> </handler> </phase> ......................... ......................... <phase name="Dispatch" class="org.apache.axis2.engine.DispatchPhase"> <handler name="AddressingBasedDispatcher " class="org.apache.axis2.engine.AddressingBasedDispatcher "> <order phase="Dispatch"/> </handler> <handler name="SOAPMessageBodyBasedDispatcher " class="org.apache.axis2.engine.SOAPMessageBodyBasedDispatcher "> <order phase="Dispatch"/> </handler> ................ ................ </phase> ............................... ............................... </phaseOrder>
As you can see our dispatchers are put in to different phases of the IN pipe (Phase is a section of Axis2 engine's execution path. Please refer to Apache Axis2 Architecture guide for more information about Phases).
If Axis2 engine cannot find a service and an operation for a message, it immediately fails, sending a fault to the sender.
So when you see these errors next time, you know what to do.