在Spring集成中使用JSON转换器

在Spring集成中使用JSON转换器,spring,spring-integration,Spring,Spring Integration,在我能找到的任何例子中,我都有一个似乎没有解决的问题 我的应用程序读取JSON消息的ActiveMQ主题。它将基于此数据构建一个全新的出站REST调用。请注意,这不是一个转换。它被赋予X产生Y,即ServiceActivator 到目前为止,我的流量是 public IntegrationFlow splitInputFlow() { return IntegrationFlows.from("inboundJmsChannel") .split()

在我能找到的任何例子中,我都有一个似乎没有解决的问题

我的应用程序读取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。但我不明白为什么这会有帮助,而且这似乎不是正常的方法

这里的主要问题是集成调用healthcheckActivator.processString负载。有效负载本身是预期的有效JSON字符串

我有点惊讶它没有调用healtcheckActivator.processMessage负载,但这没有帮助,所以没什么关系

真正的问题是为什么它不调用healtcheckActivator.processHealthcheck 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 processString有效负载方法中包含的内容是:

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_目标头中的_type参数。但在我开始处理这个问题之前,因为它不起作用,这是其他团队提供的正确类名


我还没有实现JMS消息转换器。但是提供的SimpleMessageConverter似乎应该完全满足我的要求。

好吧,Spring集成是一个消息传递框架。它通过端点之间的通道将消息从端点传输到端点。这已经是目标端点的责任,以正确的方式处理已消耗的消息。框架不关心有效负载。它实际上是目标应用程序的业务部分。这就是我们如何使框架组件尽可能通用,为最终用户留下目标业务类型的空间

无论如何,框架提供了一些与有效负载交互的机制。我们称之为POJO方法调用。因此,您提供了一些具有任意契约的业务,但是遵循一些Spring集成规则:

因此,根据您的描述,它不适用于healtcheckActivator.processHealthcheck healthcheck,这真是令人惊讶。您的transformTransformers.fromJsonHealthcheck.class应该真正生成一条带有Healthcheck对象作为有效负载的消息。框架参考方法签名,并尝试将有效负载和/或头映射到方法调用参数,将整个消息作为数据容器委托给方法调用


从这里可以看到您的healtcheckActivator.process方法,以确定transformTransformers.fromJsonHealthcheck.class结果将映射到该方法参数的原因。您的理解是正确的;对我来说很好,所以还有别的事情

@SpringBoot应用程序 公共类SO56169938应用程序{ 公共静态无效字符串[]args{ SpringApplication.runSo56169938Application.class,args; } @豆子 公共集成流{ 返回IntegrationFlows.from->{\foo\:\bar\},e->e.pollerPollers.fixedDelay5000 .transformers.fromJsonFoo.class .handlemyBean,方法 收到 } @豆子 豆豉{ 返回新的MyBean; } 公共静态类MyBean{ 公开无效方法{ System.out.printlnfoo; } } 公共静态类Foo{ 私人字符串foo; 字符串getFoo{ 返回此.foo; } void setfoo字符串foo{ this.foo=foo; } @凌驾 公共字符串toString{ 返回Foo[Foo=+this.Foo+]; } } } 及


谢谢你的例子。我花了很长时间研究另一个团队给我的生成的类,但没有结果。但即使在我对它做了重大改变之后,我也没有取得任何进展。但我不喜欢人们在我试图回答他们的问题时从不承认。这是我的官方感谢!等我有时间的时候,我会再看看这个。但目前上述操作仍然失败,这与SA Healthcheck Healthcheck中的预期完全一样;ObjectMapper mapper=新的ObjectMapper;healthcheck=mapper.readValuepayload,healthcheck.class;很奇怪,想想Artem Bilan的反应也许我是
找错地方了。我添加了发布信息和队列中的日志行@加里·拉塞尔:现在这有什么意义了吗?没有;现在它的意义就更加渺茫了——SimpleMessageConverter对JSON一无所知,因此如果您正在获取JSON,就不能使用它。为什么不在JSONtobjectTransformer中设置一个断点呢?哇。这似乎是个超级好主意!我在实现中扎根并设置断点。他们都没有被绊倒。因此,SI似乎根本没有调用转换。我根本没想到它会这么做。即使映射失败了(我已经证明了它不会失败),我也希望它至少会调用它。我无法摆脱JMS头中缺少一些我不知道的东西的感觉。
Foo [foo=bar]
Foo [foo=bar]
Foo [foo=bar]
Foo [foo=bar]
Foo [foo=bar]
Foo [foo=bar]