如何在 Spring 集成中为 TCP 服务器设置 XML 编组?
How to set up XML marshalling for a TCP server in Spring integration?
我想使用 spring 集成创建一个使用 XML 消息进行通信的简单 TCP 服务器。我尝试使用 TcpInboundGateway 并在输入和输出通道上设置适当的编组,如下所示。
@Bean
TcpNetServerConnectionFactory cf () {
TcpNetServerConnectionFactory tcf = new TcpNetServerConnectionFactory(7017);
tcf.setSerializer(new ByteArrayLfSerializer());
return tcf;
}
@Bean
TcpInboundGateway tcpGate() {
TcpInboundGateway gateway = new TcpInboundGateway();
gateway.setConnectionFactory(cf());
gateway.setRequestChannel(requestChannel());
gateway.setReplyChannel(replyChannel());
return gateway;
}
@Bean
public MessageChannel requestChannel() {
return new DirectChannel();
}
@Bean
public MessageChannel replyChannel() {
return new DirectChannel();
}
@Bean
Jaxb2Marshaller marshaller()
{
final Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("uk.ac.man.jb.emerlin.emms.corrcontrol.messages");
return marshaller;
}
@Bean
@org.springframework.integration.annotation.Transformer(inputChannel="requestChannel", outputChannel="requestChannel")
public Transformer unmarshallingTransformer()
{
final UnmarshallingTransformer unmarshallingTransformer = new UnmarshallingTransformer(marshaller());
unmarshallingTransformer.setSourceFactory(msourceFactory());
return unmarshallingTransformer;
}
@Bean
@org.springframework.integration.annotation.Transformer(inputChannel="replyChannel", outputChannel="replyChannel")
public Transformer marshallingTransformer() throws ParserConfigurationException
{
final MarshallingTransformer marshallingTransformer = new MarshallingTransformer(marshaller());
marshallingTransformer.setResultType(AbstractXmlTransformer.STRING_RESULT);
return marshallingTransformer;
}
@Bean
public SourceFactory msourceFactory() {
return new SourceFactory() {
@Override
public Source createSource(Object payload) {
Source source = null;
if (payload instanceof String) {
source = new StreamSource(new StringReader((String) payload));
}
else if (payload instanceof byte[]) {
source = new StreamSource(new StringReader(new String((byte[])payload)));
}
if (source == null) {
throw new MessagingException("failed to create Source for payload type [" +
payload.getClass().getName() + "]");
}
return source;
}
};
}
//FIXME
@MessageEndpoint
public static class CorrelatorEmControl {
@ServiceActivator(inputChannel = "requestChannel" , outputChannel="replyChannel")
public CorrelatorResponse service(@Payload CorrelatorRequest in) {
logger.info("command {}", in.getCommand().getName());
return new CorrelatorResponse();
}
}
我的问题是,尽管传入消息已正确解组,但我似乎无法将响应编组为适当的形式 - 例如用于响应通道传递它的字符串 - 如以下跟踪所示。
14:20:37.277 [pool-3-thread-2] INFO u.a.m.j.e.e.c.d.CorrelatorEndpoint - command silly
14:20:37.277 [pool-3-thread-2] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'replyChannel'
14:20:37.277 [pool-3-thread-2] DEBUG o.s.i.t.MessageTransformingHandler - correlatorEndpoint.marshallingTransformer.transformer.handler received message: GenericMessage [payload=uk.ac.man.jb.emerlin.emms.corrcontrol.messages.CorrelatorResponse@74056889, headers={timestamp=1429881637277, id=d745c519-ddd3-a92c-260f-22e91fdcc5d1, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_tcp_remotePort=55208, ip_address=0:0:0:0:0:0:0:1, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_hostname=localhost, ip_connectionId=localhost:55208:7017:8d710c70-ed34-4b3a-bdb6-d3ae9ce7142c}]
14:20:37.292 [pool-3-thread-2] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'replyChannel'
14:20:37.292 [pool-3-thread-2] DEBUG o.s.i.handler.BridgeHandler - org.springframework.integration.handler.BridgeHandler@304044a3 received message: GenericMessage [payload=<?xml version="1.0" encoding="UTF-8" standalone="yes"?><emcc:correlatorResponse xmlns:emcc="http://jb.man.ac.uk/schema/emerlincorrelator" xmlns:eop="http://jb.man.ac.uk/schema/eop"><errorStatus>false</errorStatus></emcc:correlatorResponse>, headers={timestamp=1429881637292, id=20e4eaf1-f6d0-de23-c14b-1dde7df5939d, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_address=0:0:0:0:0:0:0:1, ip_tcp_remotePort=55208, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_hostname=localhost, ip_connectionId=localhost:55208:7017:8d710c70-ed34-4b3a-bdb6-d3ae9ce7142c}]
14:20:37.293 [pool-3-thread-2] DEBUG o.s.i.channel.DirectChannel - postSend (sent=true) on channel 'replyChannel', message: GenericMessage [payload=<?xml version="1.0" encoding="UTF-8" standalone="yes"?><emcc:correlatorResponse xmlns:emcc="http://jb.man.ac.uk/schema/emerlincorrelator" xmlns:eop="http://jb.man.ac.uk/schema/eop"><errorStatus>false</errorStatus></emcc:correlatorResponse>, headers={timestamp=1429881637292, id=20e4eaf1-f6d0-de23-c14b-1dde7df5939d, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_address=0:0:0:0:0:0:0:1, ip_tcp_remotePort=55208, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_hostname=localhost, ip_connectionId=localhost:55208:7017:8d710c70-ed34-4b3a-bdb6-d3ae9ce7142c}]
14:20:37.293 [pool-3-thread-2] DEBUG o.s.i.channel.DirectChannel - postSend (sent=true) on channel 'replyChannel', message: GenericMessage [payload=uk.ac.man.jb.emerlin.emms.corrcontrol.messages.CorrelatorResponse@74056889, headers={timestamp=1429881637277, id=d745c519-ddd3-a92c-260f-22e91fdcc5d1, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_tcp_remotePort=55208, ip_address=0:0:0:0:0:0:0:1, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_hostname=localhost, ip_connectionId=localhost:55208:7017:8d710c70-ed34-4b3a-bdb6-d3ae9ce7142c}]
14:20:37.293 [pool-3-thread-2] DEBUG o.s.i.channel.DirectChannel - postSend (sent=true) on channel 'requestChannel', message: GenericMessage [payload=uk.ac.man.jb.emerlin.emms.corrcontrol.messages.CorrelatorRequest@44391778, headers={timestamp=1429881637275, id=862128b7-9754-124b-e6a2-407f87d0407c, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_address=0:0:0:0:0:0:0:1, ip_tcp_remotePort=55208, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_hostname=localhost, ip_connectionId=localhost:55208:7017:8d710c70-ed34-4b3a-bdb6-d3ae9ce7142c}]
14:20:37.293 [pool-3-thread-2] DEBUG o.s.i.channel.DirectChannel - postSend (sent=true) on channel 'requestChannel', message: GenericMessage [payload=byte[254], headers={timestamp=1429881637257, id=963a80b6-ac0f-35db-51d1-a52593f9b78c, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_tcp_remotePort=55208, ip_address=0:0:0:0:0:0:0:1, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_hostname=localhost, ip_connectionId=localhost:55208:7017:8d710c70-ed34-4b3a-bdb6-d3ae9ce7142c}]
14:20:37.294 [pool-3-thread-2] DEBUG o.s.i.i.t.s.ByteArrayCrLfSerializer - Available to read:0
14:20:37.293 o.s.i.ip.tcp.TcpInboundGateway - Failed to send reply
org.springframework.messaging.MessageHandlingException: When using a byte array serializer, the socket mapper expects either a byte array or String payload, but received: class org.springframework.xml.transform.StringResult
我如何配置转换器以产生适当的输出 - StringResult 似乎没有被正确解释?
默认情况下,编组转换器会生成一个 javax.xml.transform.Result
对象;转换器有一个可选的 ResultTransformer
作为第二个构造函数参数。
将其配置为使用 ResultToStringTransformer
将 Result
转换为 String
。
我想使用 spring 集成创建一个使用 XML 消息进行通信的简单 TCP 服务器。我尝试使用 TcpInboundGateway 并在输入和输出通道上设置适当的编组,如下所示。
@Bean
TcpNetServerConnectionFactory cf () {
TcpNetServerConnectionFactory tcf = new TcpNetServerConnectionFactory(7017);
tcf.setSerializer(new ByteArrayLfSerializer());
return tcf;
}
@Bean
TcpInboundGateway tcpGate() {
TcpInboundGateway gateway = new TcpInboundGateway();
gateway.setConnectionFactory(cf());
gateway.setRequestChannel(requestChannel());
gateway.setReplyChannel(replyChannel());
return gateway;
}
@Bean
public MessageChannel requestChannel() {
return new DirectChannel();
}
@Bean
public MessageChannel replyChannel() {
return new DirectChannel();
}
@Bean
Jaxb2Marshaller marshaller()
{
final Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("uk.ac.man.jb.emerlin.emms.corrcontrol.messages");
return marshaller;
}
@Bean
@org.springframework.integration.annotation.Transformer(inputChannel="requestChannel", outputChannel="requestChannel")
public Transformer unmarshallingTransformer()
{
final UnmarshallingTransformer unmarshallingTransformer = new UnmarshallingTransformer(marshaller());
unmarshallingTransformer.setSourceFactory(msourceFactory());
return unmarshallingTransformer;
}
@Bean
@org.springframework.integration.annotation.Transformer(inputChannel="replyChannel", outputChannel="replyChannel")
public Transformer marshallingTransformer() throws ParserConfigurationException
{
final MarshallingTransformer marshallingTransformer = new MarshallingTransformer(marshaller());
marshallingTransformer.setResultType(AbstractXmlTransformer.STRING_RESULT);
return marshallingTransformer;
}
@Bean
public SourceFactory msourceFactory() {
return new SourceFactory() {
@Override
public Source createSource(Object payload) {
Source source = null;
if (payload instanceof String) {
source = new StreamSource(new StringReader((String) payload));
}
else if (payload instanceof byte[]) {
source = new StreamSource(new StringReader(new String((byte[])payload)));
}
if (source == null) {
throw new MessagingException("failed to create Source for payload type [" +
payload.getClass().getName() + "]");
}
return source;
}
};
}
//FIXME
@MessageEndpoint
public static class CorrelatorEmControl {
@ServiceActivator(inputChannel = "requestChannel" , outputChannel="replyChannel")
public CorrelatorResponse service(@Payload CorrelatorRequest in) {
logger.info("command {}", in.getCommand().getName());
return new CorrelatorResponse();
}
}
我的问题是,尽管传入消息已正确解组,但我似乎无法将响应编组为适当的形式 - 例如用于响应通道传递它的字符串 - 如以下跟踪所示。
14:20:37.277 [pool-3-thread-2] INFO u.a.m.j.e.e.c.d.CorrelatorEndpoint - command silly
14:20:37.277 [pool-3-thread-2] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'replyChannel'
14:20:37.277 [pool-3-thread-2] DEBUG o.s.i.t.MessageTransformingHandler - correlatorEndpoint.marshallingTransformer.transformer.handler received message: GenericMessage [payload=uk.ac.man.jb.emerlin.emms.corrcontrol.messages.CorrelatorResponse@74056889, headers={timestamp=1429881637277, id=d745c519-ddd3-a92c-260f-22e91fdcc5d1, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_tcp_remotePort=55208, ip_address=0:0:0:0:0:0:0:1, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_hostname=localhost, ip_connectionId=localhost:55208:7017:8d710c70-ed34-4b3a-bdb6-d3ae9ce7142c}]
14:20:37.292 [pool-3-thread-2] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'replyChannel'
14:20:37.292 [pool-3-thread-2] DEBUG o.s.i.handler.BridgeHandler - org.springframework.integration.handler.BridgeHandler@304044a3 received message: GenericMessage [payload=<?xml version="1.0" encoding="UTF-8" standalone="yes"?><emcc:correlatorResponse xmlns:emcc="http://jb.man.ac.uk/schema/emerlincorrelator" xmlns:eop="http://jb.man.ac.uk/schema/eop"><errorStatus>false</errorStatus></emcc:correlatorResponse>, headers={timestamp=1429881637292, id=20e4eaf1-f6d0-de23-c14b-1dde7df5939d, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_address=0:0:0:0:0:0:0:1, ip_tcp_remotePort=55208, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_hostname=localhost, ip_connectionId=localhost:55208:7017:8d710c70-ed34-4b3a-bdb6-d3ae9ce7142c}]
14:20:37.293 [pool-3-thread-2] DEBUG o.s.i.channel.DirectChannel - postSend (sent=true) on channel 'replyChannel', message: GenericMessage [payload=<?xml version="1.0" encoding="UTF-8" standalone="yes"?><emcc:correlatorResponse xmlns:emcc="http://jb.man.ac.uk/schema/emerlincorrelator" xmlns:eop="http://jb.man.ac.uk/schema/eop"><errorStatus>false</errorStatus></emcc:correlatorResponse>, headers={timestamp=1429881637292, id=20e4eaf1-f6d0-de23-c14b-1dde7df5939d, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_address=0:0:0:0:0:0:0:1, ip_tcp_remotePort=55208, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_hostname=localhost, ip_connectionId=localhost:55208:7017:8d710c70-ed34-4b3a-bdb6-d3ae9ce7142c}]
14:20:37.293 [pool-3-thread-2] DEBUG o.s.i.channel.DirectChannel - postSend (sent=true) on channel 'replyChannel', message: GenericMessage [payload=uk.ac.man.jb.emerlin.emms.corrcontrol.messages.CorrelatorResponse@74056889, headers={timestamp=1429881637277, id=d745c519-ddd3-a92c-260f-22e91fdcc5d1, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_tcp_remotePort=55208, ip_address=0:0:0:0:0:0:0:1, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_hostname=localhost, ip_connectionId=localhost:55208:7017:8d710c70-ed34-4b3a-bdb6-d3ae9ce7142c}]
14:20:37.293 [pool-3-thread-2] DEBUG o.s.i.channel.DirectChannel - postSend (sent=true) on channel 'requestChannel', message: GenericMessage [payload=uk.ac.man.jb.emerlin.emms.corrcontrol.messages.CorrelatorRequest@44391778, headers={timestamp=1429881637275, id=862128b7-9754-124b-e6a2-407f87d0407c, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_address=0:0:0:0:0:0:0:1, ip_tcp_remotePort=55208, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_hostname=localhost, ip_connectionId=localhost:55208:7017:8d710c70-ed34-4b3a-bdb6-d3ae9ce7142c}]
14:20:37.293 [pool-3-thread-2] DEBUG o.s.i.channel.DirectChannel - postSend (sent=true) on channel 'requestChannel', message: GenericMessage [payload=byte[254], headers={timestamp=1429881637257, id=963a80b6-ac0f-35db-51d1-a52593f9b78c, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_tcp_remotePort=55208, ip_address=0:0:0:0:0:0:0:1, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@110ed52e, ip_hostname=localhost, ip_connectionId=localhost:55208:7017:8d710c70-ed34-4b3a-bdb6-d3ae9ce7142c}]
14:20:37.294 [pool-3-thread-2] DEBUG o.s.i.i.t.s.ByteArrayCrLfSerializer - Available to read:0
14:20:37.293 o.s.i.ip.tcp.TcpInboundGateway - Failed to send reply
org.springframework.messaging.MessageHandlingException: When using a byte array serializer, the socket mapper expects either a byte array or String payload, but received: class org.springframework.xml.transform.StringResult
我如何配置转换器以产生适当的输出 - StringResult 似乎没有被正确解释?
默认情况下,编组转换器会生成一个 javax.xml.transform.Result
对象;转换器有一个可选的 ResultTransformer
作为第二个构造函数参数。
将其配置为使用 ResultToStringTransformer
将 Result
转换为 String
。