在我能找到的任何示例中,我都有一个似乎未解决的问题。
我的应用程序读取JSON消息的ActiveMQ主题。它将基于此数据构建一个全新的出站REST调用。请注意,这不是“转换”。赋予它“ X”产生“ Y”,即ServiceActivator。
到目前为止,我的流量是
public IntegrationFlow splitInputFlow() {
return IntegrationFlows.from("inboundJmsChannel")
.split()
.log(LoggingHandler.Level.DEBUG)
.route(Message.class, m -> m.getHeaders().get("x-bn-class").equals("Healthcheck.class") ? "healthcheckChannel" : "metricChannel")
.get();
}
public IntegrationFlow healthcheckFlow() {
return IntegrationFlows.from("healthcheckChannel")
.log(LoggingHandler.Level.DEBUG)
.transform(Transformers.fromJson(Healthcheck.class))
.handle("healthcheckActivator", "process")
.get();
}
关于如何使用弹簧变压器的例子有很多。我什至考虑过尝试使用MessageConverter。但是我不知道为什么会有帮助,而且这也不是正常的方法。
这里的主要问题是Integration调用healthcheckActivator.process(String payload)。有效负载本身是预期的有效JSON字符串。
令我有些惊讶的是它没有调用healtcheckActivator.process(Messagepayload),但是那没有帮助,所以没什么大不了的。
真正的问题是,为什么不调用healtcheckActivator.process(Healthcheck healthcheck)?
实际上我理解“为什么”。这是因为DSL生成了一个内部通道来将各个步骤捆绑在一起,据我所知,通道上的任何内容都是spring.messaging.Message。
一旦进入SA,我就可以轻松实例化Healthcheck对象。但这留下了一个棘手的问题:整个转换步骤可能有什么好处?如果它总是将对象“序列化”回一条消息中,那有什么意义。
就像我说的那样,我认为我在这里缺少一些基本的东西。
编辑 我的新想法(可能也是最后一个想法)可能是我发布的错误。
要发布它,我正在使用
jmsTemplate.convertAndSend(topicName, healthcheck, messagePostProcessor -> {
messagePostProcessor.setJMSType("TextMessage");
messagePostProcessor.setStringProperty("x-bn-class", "Healthcheck.class");
messagePostProcessor.setStringProperty("x-bn-service-name", restEndpoint.getServiceName());
messagePostProcessor.setStringProperty("x-bn-service-endpoint-name", restEndpoint.getEndpointName());
messagePostProcessor.setLongProperty("x-bn-heathcheck-timestamp", queryDate);
messagePostProcessor.setStringProperty("x-bn-healthcheck-status", subsystemStatus.getStatus(subsystemStatus));
messagePostProcessor.setIntProperty("httpStatus", httpStatus.value());
return messagePostProcessor;
});
SI处理(字符串有效负载)方法的结果是:
LoggingHandler - GenericMessage [payload={"healthcheckType":"LOCAL","outcome":"PASS","dependencyType":"DB","endpoint":"NODE TABLE","description":"Read from DB","durationSecs":0.025}, headers={x-bn-service-name=TG10-CS2, x-bn-service-endpoint-name=TG Q10-CS2 Ready Check, jms_destination=topic://HEALTH_MONITOR, _type=com.healthcheck.response.Healthcheck, x-bn-heathcheck-timestamp=1558356538000, priority=4, jms_timestamp=1558356544244, x-bn-healthcheck-status=SEV0, jms_redelivered=false, x-bn-class=Healthcheck.class, httpStatus=200, jms_type=TextMessage, id=b29ffea7-7128-c543-9a14-8bab450f0ac6, jms_messageId=ID:39479-1558356520091-1:2:1:1:1, timestamp=1558356544409}]
我之前在jms_destination标头中没有注意到_type参数。但是在我开始解决这个问题之前(因为它没有用),这是其他团队提供的正确的类名。
我尚未实现JMS消息转换器。但是提供的SimpleMessageConverter似乎完全可以完成我想要的操作。
答案 0 :(得分:1)
嗯,Spring Integration是一个 Messaging 框架。它通过之间的通道将消息从端点传输到端点。这已经是目标端点负责以正确方式处理消耗的消息的职责。该框架不关心payload
。它实际上是目标应用程序的业务部分。这样,我们就可以使框架组件尽可能通用,从而为最终用户留出目标业务类型的空间。
无论如何,框架提供了一些与有效载荷进行交互的机制。我们称其为 POJO方法调用。因此,您需要为某些业务提供任意合同,但是要遵循一些Spring Integration规则:https://docs.spring.io/spring-integration/docs/current/reference/html/#service-activator。
因此,根据您的描述,它对healtcheckActivator.process(Healthcheck healthcheck)
不起作用确实令人惊讶。您的transform(Transformers.fromJson(Healthcheck.class))
实际上应该产生一个Message
对象作为负载的Healthcheck
。该框架会查询方法签名,并尝试将有效负载和/或标头映射到方法调用参数,并将整个消息作为用于将数据委派给方法调用的容器。
从这里开始,很高兴看到您的healtcheckActivator.process()
方法确定为什么transform(Transformers.fromJson(Healthcheck.class))
结果炮被映射到该方法参数。
答案 1 :(得分:1)
您的理解是正确的;对我来说效果很好,所以还有其他事情发生...
@SpringBootApplication
public class So56169938Application {
public static void main(String[] args) {
SpringApplication.run(So56169938Application.class, args);
}
@Bean
public IntegrationFlow flow() {
return IntegrationFlows.from(() -> "{\"foo\":\"bar\"}", e -> e.poller(Pollers.fixedDelay(5000)))
.transform(Transformers.fromJson(Foo.class))
.handle("myBean", "method")
.get();
}
@Bean
public MyBean myBean() {
return new MyBean();
}
public static class MyBean {
public void method(Foo foo) {
System.out.println(foo);
}
}
public static class Foo {
private String foo;
String getFoo() {
return this.foo;
}
void setFoo(String foo) {
this.foo = foo;
}
@Override
public String toString() {
return "Foo [foo=" + this.foo + "]";
}
}
}
和
Foo [foo=bar]
Foo [foo=bar]
Foo [foo=bar]
Foo [foo=bar]
Foo [foo=bar]
Foo [foo=bar]