使用jdbc出站通道适配器从xml负载插入记录

使用jdbc出站通道适配器从xml负载插入记录,jdbc,spring-integration,Jdbc,Spring Integration,我们将JDBC出站通道适配器与insert查询语句一起使用。消息负载是XML。 我们希望从有效负载中提取某些元素,以便在insert语句中使用: 如何做到这一点 1-一种尝试是使用带有#xpath spEL函数的标头enricher(参见下面的代码)。但这导致了这一例外: org.springframework.expression.spel.SpelEvaluationException:EL1023E:(位置0):尝试调用函数“xpath”:“null”时出现问题。 你知道这里怎么了吗 2-

我们将JDBC出站通道适配器与insert查询语句一起使用。消息负载是XML。 我们希望从有效负载中提取某些元素,以便在insert语句中使用: 如何做到这一点

1-一种尝试是使用带有#xpath spEL函数的标头enricher(参见下面的代码)。但这导致了这一例外: org.springframework.expression.spel.SpelEvaluationException:EL1023E:(位置0):尝试调用函数“xpath”:“null”时出现问题。 你知道这里怎么了吗

2-如果可能的话,我希望避免同时使用头文件,而只是在 ExpressionEvaluationSqlParameterSourceFactorybean。这可能吗?如何实现

3-有没有关于实现这一目标的最佳方法的建议

<int-jdbc:outbound-channel-adapter
 query="insert into foo(xmlElement1,xmlElement2, xmlMessage) values(:elementVal1,:elementVal2, :payload)"
 data-source="dataSource"
 sql-parameter-source-factory="spelSource"
 channel="jdbcOutputChannel"/>


<bean id="spelSource" class="org.springframework.integration.jdbc.ExpressionEvaluatingSqlParameterSourceFactory">
  <property name="parameterExpressions">
      <map>
          <entry key="elementVal1" value="headers['elementVal1']"/>
      <entry key="elementVal2" value="headers['elementVal2']"/>
      </map>
  </property>
</bean>

<int:header-enricher input-channel="jdbcOutputEnricherChannelPO" output-channel="jdbcOutputChannelPO">
    <int:header name="elementVal1" expression="#xpath(payload, '/order/element1')"/>
    <int:header name="elementVal2" expression="#xpath(payload, '/order/element2')"/>
</int:header-enricher>

谢谢你的支持

现在我们可以看到它告诉你:

Caused by: org.springframework.messaging.MessagingException: unsupported payload type [[B]
        at org.springframework.integration.xml.DefaultXmlPayloadConverter.convertToDocument(DefaultXmlPayloadConverter.java:91)
        at org.springframework.integration.xml.DefaultXmlPayloadConverter.convertToNode(DefaultXmlPayloadConverter.java:110)
        at org.springframework.integration.xml.xpath.XPathUtils.evaluate(XPathUtils.java:93)
实际上,从
XPathUtils
使用的
DefaultXmlPayloadConverter
具有以下代码:

public Node convertToNode(Object object) {
    Node node = null;
    if (object instanceof Node) {
        node = (Node) object;
    }
    else if (object instanceof DOMSource) {
        node = ((DOMSource) object).getNode();
    }
    else {
        node = convertToDocument(object);
    }
    return node;
}
其中
convertToDocument(object)类似于:

if (object instanceof Document) {
        return (Document) object;
    }
    if (object instanceof Node) {
        return nodeToDocument((Node) object);
    }
    else if (object instanceof DOMSource) {
        Node node = ((DOMSource) object).getNode();
        if (node instanceof Document) {
            return (Document) node;
        }
        else {
            return nodeToDocument(node);
        }
    }
    if (object instanceof File) {
        try {
            return getDocumentBuilder().parse((File) object);
        }
        catch (Exception e) {
            throw new MessagingException("failed to parse File payload '" + object + "'", e);
        }
    }
    if (object instanceof String) {
        try {
            return getDocumentBuilder().parse(new InputSource(new StringReader((String) object)));
        }
        catch (Exception e) {
            throw new MessagingException("failed to parse String payload '" + object + "'", e);
        }
    }
    throw new MessagingException("unsupported payload type [" + object.getClass().getName() + "]");
用于xPath计算的
字节[]
无效

因此,在调用存储过程之前,请确保您确实拥有正确的XML
负载


是的:您不需要
标题enricher
,只需要使用
表达式EvaluationSqlParameterSourceFactory
定义中的任何SpEL表达式。

请使用XML示例和异常的完整堆栈跟踪编辑您的问题。XML有效负载的源是入站HTTP网关,该网关设置为使用application/xml。因此,有效负载是字节[]。我求助于使用ServiceActivator将负载转换为字符串,并将其发送回JDBC出站适配器。有了它,我可以使用SpEL表达式expressionEvaluationSqlParameterSourceFactory定义。问题解决了。谢谢阿泰姆和加里,你的意见帮我找到了正确的方向。那很好。但是我向您展示了限制,您应该看到,
byte[]
不会被接受,您应该将其转换为适合
DefaultXmlPayloadConverter
的格式。我认为
反对串变压器
最适合您。尽管您可以使用
DocumentBuilderFactory
直接将其转换为
文档
:。OTOH不清楚为什么不能从
入站HTTP网关
返回比原始
字节[]
更有用的内容……哦,是的。这就是我一直在寻找的。我之前试过一个普通的变压器。我的搜索并没有导致我反对串联变压器。我喜欢这个框架的另一个原因是:)没有编码。很高兴听到这个消息。但我仍然认为您可以从HTTP网关返回一些有意义的内容。它完全基于Spring MVC,因此您可以配置例如
request payload type=“javax.xml.transform.dom.DOMSource”
,适当的
SourceHttpMessageConverter
将为您提供一个实例作为下游流的
有效负载。摆脱了变压器。我使用的是请求有效负载类型。这太棒了。谢谢
public Node convertToNode(Object object) {
    Node node = null;
    if (object instanceof Node) {
        node = (Node) object;
    }
    else if (object instanceof DOMSource) {
        node = ((DOMSource) object).getNode();
    }
    else {
        node = convertToDocument(object);
    }
    return node;
}
if (object instanceof Document) {
        return (Document) object;
    }
    if (object instanceof Node) {
        return nodeToDocument((Node) object);
    }
    else if (object instanceof DOMSource) {
        Node node = ((DOMSource) object).getNode();
        if (node instanceof Document) {
            return (Document) node;
        }
        else {
            return nodeToDocument(node);
        }
    }
    if (object instanceof File) {
        try {
            return getDocumentBuilder().parse((File) object);
        }
        catch (Exception e) {
            throw new MessagingException("failed to parse File payload '" + object + "'", e);
        }
    }
    if (object instanceof String) {
        try {
            return getDocumentBuilder().parse(new InputSource(new StringReader((String) object)));
        }
        catch (Exception e) {
            throw new MessagingException("failed to parse String payload '" + object + "'", e);
        }
    }
    throw new MessagingException("unsupported payload type [" + object.getClass().getName() + "]");