Monday, September 26, 2011

Handling SOAP Fault with Http Web Service

The sample XML configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesource.org/schema/mule/core/2.2"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:http="http://www.mulesource.org/schema/mule/http/2.2"
    xmlns:https="http://www.mulesource.org/schema/mule/https/2.2"
    xmlns:saaj="http://www.mulesource.org/schema/mule/saaj/2.2"
    xmlns:vm="http://www.mulesource.org/schema/mule/vm/2.2"
    xmlns:mule-xml="http://www.mulesource.org/schema/mule/xml/2.2"
    xmlns:management="http://www.mulesource.org/schema/mule/management/2.2"
    xmlns:spring="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="
          http://www.mulesource.org/schema/mule/http/2.2 http://www.mulesource.org/schema/mule/http/2.2/mule-http.xsd
          http://www.mulesource.org/schema/mule/https/2.2 http://www.mulesource.org/schema/mule/https/2.2/mule-https.xsd
          http://www.mulesource.org/schema/mule/saaj/2.2 http://www.mulesource.org/schema/mule/saaj/2.2/mule-saaj.xsd
          http://www.mulesource.org/schema/mule/core/2.2 http://www.mulesource.org/schema/mule/core/2.2/mule.xsd
          http://www.mulesource.org/schema/mule/vm/2.2 http://www.mulesource.org/schema/mule/vm/2.2/mule-vm.xsd
          http://www.mulesource.org/schema/mule/xml/2.2 http://www.mulesource.org/schema/mule/xml/2.2/mule-xml.xsd
          http://www.mulesource.org/schema/mule/management/2.2 http://www.mulesource.org/schema/mule/management/2.2/mule-management.xsd
          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!--

        Mule Management Console Configurations START............
        Register the Mx4j Console...............................
        Register the JMX Console................................
        Register Log4j Console..................................
    -->
    <management:jmx-default-config port="1098"
        registerMx4jAdapter="true">
        <management:credentials>
            <spring:entry key="vijay" value="vijay123" />
        </management:credentials>
    </management:jmx-default-config>

    <management:jmx-log4j />

    <!-- 
        Mule Management Console Configurations END.
     -->

    <spring:beans>
        <spring:import resource="transformers.xml" />
    </spring:beans>

    <custom-transformer
        class="com.restaurantsrevice.transformers.DocumentToSOAPFaultTransformer"
        name="faultTransformer">
        <spring:property name="propagateHeaders" value="false" />
    </custom-transformer>

    <model name="RestaurantServiceModel">

        <!-- Default Service Exception Strategy -->
        <default-service-exception-strategy>
            <vm:outbound-endpoint path="exception-channel" />
        </default-service-exception-strategy>

        <service name="RestaurantService">
            <inbound>
                <http:inbound-endpoint
                    address="http://localhost:8080/RestaurantService"
                    synchronous="true">
                    <transformers>

                        <!-- Transform Incoming Soap Message to XML String -->
                        <saaj:soap-message-to-document-transformer />
                        <mule-xml:dom-to-xml-transformer
                            returnClass="java.lang.String" />
                    </transformers>
                </http:inbound-endpoint>
            </inbound>
            <outbound>
                <pass-through-router>
                    <vm:outbound-endpoint path="router-channel"
                        synchronous="true" />
                </pass-through-router>
            </outbound>

            <async-reply>
                <vm:inbound-endpoint path="success-response-channel"
                    synchronous="true" />
                <vm:inbound-endpoint path="exception-response-channel"
                    synchronous="true" />
                <single-async-reply-router />
            </async-reply>
        </service>

        <service name="RouterService">
            <inbound>
                <vm:inbound-endpoint path="router-channel"
                    synchronous="true" />
            </inbound>
            <log-component />
            <outbound>
                <filtering-router>
                    <vm:outbound-endpoint path="request-processing-channel"
                        synchronous="true">
                        <transformer ref="addFoodRequestTransformer" />
                    </vm:outbound-endpoint>
                    <wildcard-filter pattern="*AddFoodRequest*" />
                </filtering-router>
            </outbound>
        </service>

        <service name="RequestProcessingService">
            <inbound>
                <vm:inbound-endpoint path="request-processing-channel"
                    synchronous="true" />
            </inbound>
            <component
                class="org.restaurantservice.RestaurantService"></component>
            <outbound>
                <filtering-router>
                    <vm:outbound-endpoint path="success-response-channel">
                        <transformers>
                            <transformer ref="addFoodResponseTransformer" />

                            <!-- Transform XML to SOAP response -->
                            <mule-xml:xml-to-dom-transformer
                                returnClass="org.w3c.dom.Document" />
                            <saaj:document-to-soap-message-transformer
                                propagateHeaders="false" />
                        </transformers>
                    </vm:outbound-endpoint>
                    <payload-type-filter
                        expectedType="com.services.restaurantservice.AddFoodResponse" />
                </filtering-router>
            </outbound>
        </service>

        <service name="ExceptionService">
            <inbound>
                <vm:inbound-endpoint path="exception-channel"
                    synchronous="true" />
            </inbound>
            <component
                class="com.services.restaurantservice.components.ExceptionHandler" />
            <outbound>
                <filtering-router>
                    <vm:outbound-endpoint path="exception-response-channel"
                        synchronous="true">

                        <transformers>
                            <transformer
                                ref="FoodAdditionFailedExceptionMap" />
                            <!-- Transform to Document Object -->
                            <mule-xml:xml-to-dom-transformer
                                returnClass="org.w3c.dom.Document" />

                            <!-- Transform to SOAP Fault -->
                            <transformer ref="faultTransformer" />
                        </transformers>

                    </vm:outbound-endpoint>
                    <payload-type-filter
                        expectedType="com.services.restaurantservice.webservice.FoodAdditionFailed" />
                </filtering-router>
                <filtering-router>
                    <vm:outbound-endpoint path="exception-response-channel"
                        synchronous="true">

                        <transformers>
                            <transformer ref="IncompleteRequestExceptionMap" />
                            <!-- Transform to Document Object -->
                            <mule-xml:xml-to-dom-transformer
                                returnClass="org.w3c.dom.Document" />

                            <!-- Transform to SOAP Fault -->
                            <transformer ref="faultTransformer" />
                        </transformers>

                    </vm:outbound-endpoint>
                    <payload-type-filter
                        expectedType="com.services.restaurantservice.webservice.IncompleteRequest" />
                </filtering-router>
            </outbound>
        </service>
    </model>
</mule> 
Java Code to transform to Soap Fault:
package com.restaurantsrevice.transformers;

import javax.xml.namespace.QName;
import javax.xml.soap.Detail;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPMessage;

import org.mule.api.MuleMessage;
import org.mule.api.transformer.TransformerException;
import org.mule.module.saaj.SaajUtils;
import org.mule.module.saaj.i18n.SaajMessages;
import org.mule.transformer.AbstractMessageAwareTransformer;
import org.w3c.dom.Document;

public class DocumentToSOAPFaultTransformer extends
        AbstractMessageAwareTransformer {

    private boolean propagateHeaders = true;
    private String headerURI = "http://www.mulesource.org/schema/mule/saaj/2.2";
    private String headerPrefix = "mule-saaj";

    private SOAPFactory soapFactory;
    private MessageFactory messageFactory;

    public DocumentToSOAPFaultTransformer() throws Exception {
        soapFactory = SOAPFactory.newInstance();
        messageFactory = MessageFactory.newInstance();
    }

    public void setPropagateHeaders(boolean propagateHeaders) {
        this.propagateHeaders = propagateHeaders;
    }

    public void setHeaderURI(String headerURI) {
        this.headerURI = headerURI;
    }

    public void setHeaderPrefix(String headerPrefix) {
        this.headerPrefix = headerPrefix;
    }

    public Object transform(MuleMessage muleMessage, String s)
            throws TransformerException {

        Document document = (Document) muleMessage.getPayload();
        SOAPMessage soapMessage;

        try {
            soapMessage = messageFactory.createMessage();
            SOAPBody body = soapMessage.getSOAPBody();

            addFault(body, document);

            if (propagateHeaders) {
                propagateHeaders(muleMessage, soapMessage);
            }
            soapMessage.saveChanges();
        } catch (SOAPException ex) {
            throw new TransformerException(SaajMessages
                    .failedToBuildSOAPMessage());
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Transformation result: "
                    + SaajUtils.getSOAPMessageAsString(soapMessage));
        }

        return SaajUtils.getSOAPMessageAsBytes(soapMessage);
    }

    void propagateHeaders(MuleMessage muleMessage, SOAPMessage soapMessage)
            throws SOAPException {
        for (Object n : muleMessage.getPropertyNames()) {
            String propertyName = (String) n;
            SOAPHeader header = soapMessage.getSOAPHeader();

            Name name = soapFactory.createName(propertyName, headerPrefix,
                    headerURI);
            SOAPHeaderElement headerElement = header.addHeaderElement(name);
            headerElement.addTextNode(muleMessage.getProperty(propertyName)
                    .toString());
        }
    }

    private void addFault(SOAPBody soapBody, Document document)
            throws SOAPException {

        org.w3c.dom.Element docElement = document.getDocumentElement();
        QName qName = new QName(docElement.getLocalName());

        SOAPFault soapFault = soapBody.addFault(qName, docElement
                .getTextContent());

        Detail detail = soapFault.addDetail();
        detail.addChildElement(soapFactory.createElement(docElement));
    }

}

No comments:

Post a Comment