当前位置: 首页 > 知识库问答 >
问题:

如何在Spring集成中解组其Xml负载后保留JMS Headers

岳浩穰
2023-03-14

我正在使用Jmeter发送带有XML有效负载的JMS消息和一些带有值text/jsontext/XML的自定义头contentType

我的Spring集成配置如下所示:

<jms:message-driven-channel-adapter channel="jmsInChannel" destination-name="queue.demo" connection-factory="jmsConnectionFactory1" />
<int:channel id="jmsInChannel" />

<int:header-value-router input-channel="jmsInChannel" header-name="contentType" default-output-channel="nullChannel">
    <int:mapping value="text/json" channel="jsonTransformerChannel" />
    <int:mapping value="text/xml" channel="xmlTransformerChannel" />
</int:header-value-router>

到目前为止,一切工作都很完美,消息被成功地路由到各自的转换器。

我的问题是,当它是XML负载时,我首先使用了JAXB解组器和

我可以得到有效载荷,但是它不能将消息处理为JMS消息,它变成了纯粹的POJO。所以我失去了头,我不能使用

我找到了一个解决方法,在这里我用java定义了自己的解组bean,如下所示:

<int:channel id="xmlTransformerChannel" />
<int:transformer input-channel="xmlTransformerChannel" ref="xmlMsgToCustomerPojoTransformer" output-channel="enrichInChannel" />

方法:

@SuppressWarnings("rawtypes")
public Message transform(String message) {

    logger.info("Message Received \r\n" + message);

    try {
        MyModel myModel = (MyModel) unmarshaller.unmarshal(new StreamSource(new StringReader(message)));
        return MessageBuilder.withPayload(myModel).build();

    } catch (XmlMappingException e) {
        return MessageBuilder.withPayload(e).build();
    } catch (Exception e) {
        return MessageBuilder.withPayload(e).build();
    }
}

我可以成功地将该消息作为Spring集成消息处理,但是我丢失了原始的定制JMS头。

相比之下,我所要做的就是转换json有效负载、保持消息格式并保留自定义标题,这就是xml配置:

<int:channel id="jsonTransformerChannel" />
<int:json-to-object-transformer input-channel="jsonTransformerChannel" output-channel="enrichInChannel" type="com.alrawas.ig5.MyModel" />

我的问题是,在解组xml负载后,如何保留原始的自定义JMS头?

更新:

我确实尝试以这种方式编写xml变压器,将Message作为输入,而不仅仅是字符串,它没有在这个方法中抛出异常,但它在路由阶段的后期做到了

public Message<?> transform(Message<String> message) {

    logger.info("Message Received \r\n" + message);

    try {
        MyModel myModel = (MyModel) unmarshaller.unmarshal(new StreamSource(new StringReader(message.getPayload())));
        return (Message<MyModel>) MessageBuilder.withPayload(myModel).copyHeaders(message.getHeaders()).build();

    } catch (XmlMappingException e) {
        return MessageBuilder.withPayload(e).build();
    } catch (Exception e) {
        return MessageBuilder.withPayload(e).build();
    }
}

我在本流程后面使用的组件中遇到问题:

<int:object-to-json-transformer input-channel="outr" output-channel="outch" />
<int:router method="route" input-channel="outch" default-output-channel="nullChannel">
    <bean class="com.alrawas.ig5.MyCustomRouter" />
</int:router>

在我的路由方法抛出不能铸造字符串com.alrawas.ig5.MyModel异常:

public class MyCustomRouter {

    public String route(Message<MyModel> myModel) {

    Integer tenNumber = myModel.getPayload().getNumber(); // <-- Cast Exception here
    System.out.println(myModel);
    return (tenNumber % 10 == 0) ? "stayLocal" : "goRemote";

    }
}

此强制转换异常仅在解组xml后发生,JSON有效负载工作正常,不会丢失头或引发强制转换异常。

更新:

检查我下面的答案:contentType并不是一个真正的自定义标题


共有2个答案

傅志文
2023-03-14

会议内容如下:

ClassCastException稍后发生在最后一个路由器中,因为我将自定义头命名为contentType。这是内部使用的默认jms头。当我将其值更改为text/xml时,最后一个路由器字符串路由(消息

所以我去掉了定制的xml解组逻辑bean。我重命名了我的自定义标题。并使用

它使用xml配置工作,无需额外的定制JavaBean。

司马高韵
2023-03-14

当您开发自定义变压器时,您需要记住返回消息

当转换器函数返回Message时,它不会填充任何请求标头。

因此,您的公共消息转换(字符串消息){必须将消息作为输入,并且您需要将请求消息中的所有头复制到回复消息中。在消息生成器上有适当的方法。

另一方面,完全不清楚为什么需要在此处返回消息,因为Spring集成中的所有内容都将在发送到输出通道之前包装到消息

 类似资料:
  • 我们想将Spring集成配置拆分为几个文件,例如和。在每个这样的文件中,我们都希望有一个通道。 Spring Integr是否可以自动为通道id加上XML文件名的前缀,即和? 否则,您将如何处理XML配置(不诉诸于一个大的XML文件)?

  • null 如何在transform()步骤中添加Jaxb2Marshaller?

  • 问题内容: 我在pandas数据框上使用来删除没有特定列的最小值的所有行。像这样: 但是,如果我不止这两列,其他列(例如在我的示例中)将被删除。我可以使用保留这些列,还是必须找到一种不同的方式删除行? 我的数据如下: 并应以如下形式结束: 但是我得到的是: 我一直在浏览文档,找不到任何东西。我试过了: 但是这些都不起作用(我在最后一个中意识到,语法是在创建组后进行聚合的)。 问题答案: 方法1:使

  • 问题内容: 当前使用Python 2.4.3,并且不允许升级 我想更改一个或多个标记中给定属性的值,以及更新文件中的XML注释。 我设法创建了一个以XML文件作为参数的Python脚本,并且为每个指定的标签更改了一个属性,如下所示 一切都很好,属性“ initialState”已更新,除了我的原始XML也包含许多XML注释的事实,但它们早已消失了,这是不好的。 怀疑只能解析XML结构,但我认为XM

  • 我正试图找到一种方法,将请求负载平衡到一组相似配置的activemq代理。假设,我有3个activemq代理(A,B,C),每个代理都有两个队列(X,Y)在运行。 每个活动 mq 代理都有相同的队列,即。X 现在,我想对我的3个队列的负载平衡请求进行循环负载平衡。即第一个请求应该去队列A,然后下一个请求去队列B,然后下一个请求去队列C,依此类推。 请指导。

  • 我正在我的项目中使用spring批处理spring集成sftp。我不希望在应用程序启动时触发下载。我希望下载过程在步骤1中触发,并在所有文件下载到本地后继续执行步骤2,不确定如何实现这一点