You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Content-Type设为application/xml时出现Class Mediation错误求助

问题分析:Class Mediator 中介处理报错

错误信息

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

代理服务配置(消费端)

<?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>

说明:将transport.jms.ContentType设置为**'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>

补充:相关Java类代码

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;
    }

}

报错原因分析

  1. SOAP信封处理逻辑差异:当Content-Type设为application/xml时,WSO2 ESB不会自动将消息包装为SOAP信封;而设为text/xml时,ESB会默认把消息封装成SOAP结构。
  2. 代码依赖SOAP结构:你的UnicaProvSenderMediator类中直接调用context.getEnvelope()获取SOAP信封,然后操作envelope.getBody()下的prov节点。如果消息没有被封装为SOAP信封,context.getEnvelope()会返回null,或者envelope.getBody()中不存在预期的节点,直接调用getFirstChildWithName(new QName("prov"))会抛出空指针或节点不存在的异常,最终触发SynapseException。
  3. 变量未初始化问题:代码中msisdn和rowID变量没有初始化逻辑,在msisdn = Utility.formatMSISDN(msisdn);和日志打印时直接使用,这也会导致空指针异常,尤其是当消息结构不符合预期时,这个问题会被触发。

解决建议

  • 若要使用application/xml作为Content-Type,需要在序列中先添加<envelope/>中介器,手动将XML消息封装为SOAP信封,确保context.getEnvelope()能获取到有效对象。
  • 修复代码中未初始化的msisdn和rowID变量,添加空值检查逻辑,避免空指针异常。
  • 在操作OM节点前,先检查节点是否存在,比如在调用detach()前判断getFirstChildWithName()的返回值是否为null。

内容的提问来源于stack exchange,提问作者Wajih Haider

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 03:05:26