Skip to Main Content

WSO2 EI Tutorial: Creating SOAP Faults with Makefault Mediator

The example we are going to study today consists of a Client sending a request to a backend through a middleware\Enterprise Integrator (EI). In the middle of processing in the WSO2 EI a problem appears and an error response needs to be sent back to the client. To do so, a makefault mediator is the best option. Using this, a custom SOAP fault is generated changing the direction of the message, in this example, as a response message. The direction changes thanks to the TO header property that indicates where the message is being sent.

In section 2,3,4 y 5 we will talk about  example 1 and 2 respectively, referring to the diagram that is attached at those same points.

We will follow the table below:

1. MakeFault Mediator

With the Make Fault Mediator, that can be named Makefault Mediator too, the current message is transformed to a fault message that is sent back to the client. After this mediator, a send mediator is needed to respond to the client with the fault message, Fault Mediator does not send the response back to the client by default. The original request coming from the client can have a Fault-To header whose content is used on the TO header of the fault response message, as discussed only if Fault-To exists on the original request. The fault message can be created using SOAP 1.1, SOAP 1.2 or plain-old XML (POX)

Example:

<makefault version=”soap12”>
   <code xmlns:tns="http://www.w3.org/2003/05/soap-envelope" value="tns:Receiver"/>
   <reason expression="get-property('ERROR_MESSAGE')"/>
</makefault>

The code returned by the error message. It specifies the fault string for server side errors or errors related with the Server:

<code xmlns:tns="http://www.w3.org/2003/05/soap-envelope" value="tns:Receiver"/>

The fault string is specified as an expression. The property ERROR_MESSAGE can be edited with a custom error message.

<reason expression="get-property('ERROR_MESSAGE')"/>

Note: tns:Receiver – For Server side errors. tns:Sender– For Client side errors.

2. Configuration example 1 with MSFT

All this code is located within the EI. The request coming from the client side goes through the main sequence. In that sequence, if an error arises, the myFaultHandler sequence is in charge to processing the error, as indicated by onError in the main sequence. Now the message goes to the IN mediator. There is a switch mediator that looks for the value symbol in the request. It can have two values MSFT or SUN. If the value matches MSFT then the message is sent to an endpoint whose name has been incorrectly spelled. While if the value is SUN the request is sent to the correct endpoint in localhost.

When the message is sent to the incorrectly spelled endpoint (our error condition), an error is launched. This error event is caught by the myFaultHandler sequence that processes the message. Inside that sequence there is a makefault mediator that builds for us a SOAP fault message. The property RESPONSE is set to ‘true’ after the makefault mediator. This instructs the EI to change the direction of messages to ‘response’ as messages are transformed into SOAP faults. The value of

ReplyTo: http://www.w3.org/2005/08/addressing/anonymous

means that the answer is sent to the Client that sent the request.

Code:

<definitions xmlns="http://ws.apache.org/ns/synapse">

    <sequence name="myFaultHandler">
        <makefault response="true">
            <code xmlns:tns="http://www.w3.org/2003/05/soap-envelope" value="tns:Receiver"/>
            <reason expression="get-property('ERROR_MESSAGE')"/>
        </makefault> 
       <property name=”RESPONSE” value=”true”/>
       <header name=”To” expression=”get-property(‘ReplayTo’)”/>
       <send/>
    </sequence>

    <sequence name="main" onError="myFaultHandler">
        <in>
            <switch xmlns:m0="http://services.samples" source="//m0:getQuote/m0:request/m0:symbol">
                <case regex="MSFT">
                    <send>
                        <endpoint>
                            <address uri="http://bogus:9000/services/NonExistentStockQuoteService"/>
                        </endpoint>
                    </send>
                </case>
                <case regex="SUN">
                    <send>
                        <endpoint>
                            <address uri="http://localhost:9009/services/NonExistentStockQuoteService"/>
                        </endpoint>
                    </send>
                </case>
            </switch>
            <drop/>
        </in>

        <out>
            <send/>
        </out>
    </sequence>

</definitions>

3. Running example 1 with MSFT

To run this example, start the Axis2 server with the back-end service SimpleStockQuoteService. There is an explanation on how to do it on the first blog dedicated to the ESB. On the other hand the client used to send requests is the Stock Quote Client. SOAPUI can be used to send the requests to the EI too.

The client sends a stock quote request with the symbol MSFT, the one with the wrong endpoint, and the backend responds with an unknown host response. EI catches the error and builds a fault error message, SOAP fault response, sent back to the client. If the client sends another request the backend responds with a connection refused exception as another SOAP fault response.

To trigger a MSFT stock request to the EI run the following command from the <ESB_HOME>/samples/axis2Client directory.

Request:

ant stockquote -Daddurl=http://localhost:9000/services/SimpleStockQuoteService -Dtrpurl=http://localhost:8280/

-Dsymbol=MSFT

This is the request that is sent by the client (SOAPUI or Stock Quote Client):

Response from EI:

A connection refused exception would be generated for the SUN stock request. Run the following command from the <ESB_HOME>/samples/axis2Client directory to trigger a SUN stock quote request to the back-end service.

Request:

ant stockquote -Daddurl=http://localhost:9000/services/SimpleStockQuoteService -Dtrpurl=http://localhost:8280/ -Dsymbol=SUN

This is the request that is sent to the EI and it can be used with SOAPUI too.

Request to EI:

Response from EI:

4. Configuration example 2 using file WSDL

The client sends a request that passes through a proxy. inSequence processes the request. There is a log mediator that displays the content type of the message that is a property that travels on the transport level of the message. Next, there is a filter mediator. If the content type of the message is not text/xml then it returns a fault error message sent to the client. Otherwise, send the message to an endpoint. In then part of the filter mediator, there is another log mediator to display the content type and an error message indicating a wrong content type.

The next mediator is a makefault. That build an error message indicating that the error comes from the client side, soap11Env:client. After that, the TO header is removed, indicating that it is a request message. Because now it is a response fault message. And finally a send mediator returns the fault response message to the client. On the other hand, the outSequence redirects the responses from the backend to the client side. PublishWSDL publishes the WSDL file.  

<proxy xmlns="http://ws.apache.org/ns/synapse" name="CheckContentType" transports="https http" startOnLoad="true" trace="disable">
<description/>
<target>
    <inSequence>
        <log level="custom">
            <property name="_______Content-Type" expression="get-property('transport','Content-Type')"/>
        </log>
        <filter source="get-property('transport','Content-Type')" regex="application/xhtml\+xml">
        <then>
            <log>
                <property name="Content-Type" expression="get-property('transport','Content-Type')"/>
                <property name="Decision" value="Exception, due to unexpected Content-Type."/>
            </log>
            <makefault version="soap11">
                <code xmlns:soap11Env="http://schemas.xmlsoap.org/soap/envelope/" value="soap11Env:Client"/>
                <reason value="Content-Type Error"/>
                <role/>
                <detail>Content-Type: application/xhtml+xml is not a valid content type.</detail>
            </makefault>
            <header name="To" scope="default" action="remove"/>
            <send/>
        </then>
        <else>
            <log>
                <property name="Content-Type" expression="get-property('transport','Content-Type')"/>
                <property name="Decision" value="Continue the mediation flow..."/>
            </log>
            <send>
                <endpoint>
                    <address uri="http://localhost:9000/services/SimpleStockQuoteService"/>
                </endpoint>
            </send>
        </else>
    </filter>
</inSequence>
<outSequence>
    <send/>
</outSequence>
</target>
<publishWSDL uri="http://localhost:9000/services/SimpleStockQuoteService?wsdl"/>
</proxy>

5. Running example 2 using file WSDL

We can use the WSDL file published by the proxy to generate client requests. To do so, import that wsdl file into SOAPUI, for example, using the url that contains the proxy adding “?wsdl” at the end of the url, as shown on the top of the following image. The proxy publishes for us the methods used by the service. It is visible through a browser:

The same URI is used in SOAPUI to generate the requests:

This is an example of a SOAP request against the service using a correct Content-Type (text/xml):

The message is sent to the backend. Now I am going to send the same request but with an invalid Content-Type (application/xhtml+xml):

As you can see, and according to the ESB configuration, a fault message is sent to the Client.

6. Conclusion

As it has been demonstrated, the use of fault mediator, manages the fault generation of messages following the good practices. On the other hand it is very handy because the user can personalize the error message, indicating if the error comes from the server side or client side.