Wajih Haider
Wajih Haider

Reputation: 197

Getting Class Mediation error when content-type is application/xml

I am getting an error :

ErrorCode = 0, ErrorMessage = Error occured in the mediation of the class mediator, 
ErrorDetail = org.apache.synapse.SynapseException: Error occured in the mediation of the class mediator

Below is my proxy service used for consumption:

<?xml version="1.0" encoding="UTF-8"?>
<proxy name="UnicaProvConsumer" startOnLoad="true" transports="jms" xmlns="http://ws.apache.org/ns/synapse">
    <target>
        <inSequence>
            <sequence key="MainSequence"/>
        </inSequence>
        <outSequence/>
        <faultSequence>
            <sequence key="Hello"/>
        </faultSequence>
    </target>
    <parameter name="transport.jms.Destination">REQ</parameter>
    <parameter name="transport.jms.ContentType">application/xml</parameter>
    <parameter name="transport.jms.ConnectionFactory">Listener</parameter>
</proxy>

For info: This works fine if Content Type is put 'text/xml'.

<?xml version="1.0" encoding="UTF-8"?>
<sequence name="UnicaProvMainSequence" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
    <class description="UnicaProvSenderMediator" name="com.safaricom.mediator.UnicaProvSenderMediator"/>
</sequence>

Any guidance that why is it occurring ?

EDIT:

Below is the class code for the reference:

public class UnicaProvSenderMediator extends AbstractMediator implements ManagedLifecycle {

    private static final Logger logger = LogManager.getLogger(UnicaProvSenderMediator.class.getName());
    private static final Logger Errorlogger = LogManager.getLogger(ErrorHandling.class.getName());
    private static JDBCConnectionPool jdbcPool = new JDBCConnectionPool(Utility.getProperty(Constant.EAI_JDBC_DRIVER), Utility.getProperty(Constant.EAI_JDBC_STRING), Utility.getProperty(Constant.EAI_JDBC_USER_NAME), Utility.getProperty(Constant.EAI_JDBC_PASSWORD));

    static {
        System.setProperty("httpclient.hostnameVerifier", "AllowAll");
    }

    public boolean mediate(MessageContext context) {
        // TODO Implement your mediation logic here
        Connection connection = null;
        try {
            SOAPEnvelope envelope = context.getEnvelope();
            OMElement provNode = (OMElement) envelope.getBody().getFirstChildWithName(new QName("prov")).detach();
            String retryCount = (provNode.getFirstChildWithName(new QName("retryCount")) == null) ? null : provNode.getFirstChildWithName(new QName("retryCount")).getText();
            if (retryCount == null) {
                provNode.addChild(createOMElement("retryCount", "0"));
                context.setProperty("retryCount", "0");
            } else {
                provNode.getFirstChildWithName(new QName("retryCount")).detach();
                provNode.addChild(createOMElement("retryCount", String.valueOf(Integer.parseInt(retryCount) + 1)));
                context.setProperty("retryCount", String.valueOf(Integer.parseInt(retryCount) + 1));
            }
            String incomingTimestamp = (provNode.getFirstChildWithName(new QName("incomingTimestamp")) == null) ? null : provNode.getFirstChildWithName(new QName("incomingTimestamp")).getText();
            if (incomingTimestamp == null) {
                provNode.addChild(createOMElement("incomingTimestamp", String.valueOf(System.currentTimeMillis())));
            } else {
                provNode.getFirstChildWithName(new QName("incomingTimestamp")).detach();
                provNode.addChild(createOMElement("incomingTimestamp", String.valueOf(System.currentTimeMillis())));
            }
            envelope.getBody().addChild(provNode);
            context.setProperty("orgMessage", getPayloadText(context));
            msisdn = Utility.formatMSISDN(msisdn);
            String provisioningType = (provNode.getFirstChildWithName(new QName("provisioningType")) == null) ? null : provNode.getFirstChildWithName(new QName("provisioningType")).getText();
            context.setProperty("provisioningType", provisioningType);
            context.setProperty("msisdn", msisdn);

            logger.info("Incoming prov request|rowID:" + rowID + "|msisdn:" + msisdn + "|provisioningType:" + provisioningType);
            logger.debug("Incoming prov request|rowID:" + rowID + "|msisdn:" + msisdn + "|provisioningType:" + provisioningType + "|orgMessage:" + getPayloadText(context));
 

            return true;
        } catch (Exception ex) {
            logger.error(ErrorHandling.getMessage(ex));
            Errorlogger.error(ErrorHandling.getStackTrace(ex));
            jdbcPool.releaseConnection(connection);
            handleException(ex.getClass().getName(), ex, context);
        }
        return false;
    }

}

Upvotes: 1

Views: 144

Answers (1)

ycr
ycr

Reputation: 14574

The issue seems the way you are reading to Payload in your Class Mediator, it seems tightly coupled to a SOAP message structure. In order to get around the issue, add the following before your Class Mediator. This will allow you to consume both SOAP1.1 and 1.2 messages with the Content-Type application/xml

<enrich>
  <source clone="true" xpath="//prov"/>
  <target type="body"/>
</enrich>
<?xml version="1.0" encoding="UTF-8"?>
<proxy name="UnicaProvConsumer" startOnLoad="true" transports="jms" xmlns="http://ws.apache.org/ns/synapse">
    <target>
        <inSequence>
            <enrich>
              <source clone="true" xpath="//prov"/>
              <target type="body"/>
            </enrich>
            <sequence key="MainSequence"/>
        </inSequence>
        <outSequence/>
        <faultSequence>
            <sequence key="Hello"/>
        </faultSequence>
    </target>
    <parameter name="transport.jms.Destination">REQ</parameter>
    <parameter name="transport.jms.ContentType">application/xml</parameter>
    <parameter name="transport.jms.ConnectionFactory">Listener</parameter>
</proxy>

Explanation

Enrich mediator will allow you to have a proper SOAP message structure when you go into the Class mediator. To elaborate, all the messages that comes into WSO2 will be stored internally as SOAP messages. I assume your problem is with this line. OMElement provNode = (OMElement) envelope.getBody().getFirstChildWithName(new QName("prov")).detach(); You expect the first child of the SOAP message to be prov. When you build the message with application/xml builder the payload will be slightly different(There would be additional nesting happening since the message is processed as an XML not a SOAP message), hence the Enrich will extract the content of prov and place it in a proper SOAP body.

Upvotes: 1

Related Questions