Error handling Spring集成-如何使用TCP适配器从service activator引发错误

Error handling Spring集成-如何使用TCP适配器从service activator引发错误,error-handling,spring-integration,Error Handling,Spring Integration,我需要(我的应用程序)通过TCP连接在Spring集成通道中接收命令(字符串值)。当我收到命令时,应用程序将其发送到路由器,将请求路由到不同的通道,以便使用服务激活器激活服务 路由器首先验证该命令。如果命令无效,路由器不允许进一步处理,需要将自定义错误消息发送回发送方(TCP客户端)。 我想要一个解决方案,在路由之前或路由过程中,我可以分析我的命令并发送错误响应,而无需任何进一步处理 以下是配置和代码 Spring集成配置 <ip:tcp-connection-factory id

我需要(我的应用程序)通过TCP连接在Spring集成通道中接收命令(字符串值)。当我收到命令时,应用程序将其发送到路由器,将请求路由到不同的通道,以便使用服务激活器激活服务

路由器首先验证该命令。如果命令无效,路由器不允许进一步处理,需要将自定义错误消息发送回发送方(TCP客户端)。 我想要一个解决方案,在路由之前或路由过程中,我可以分析我的命令并发送错误响应,而无需任何进一步处理

以下是配置和代码

Spring集成配置

    <ip:tcp-connection-factory id="server"
    type="server"
    port="${port}"
    using-nio="true"
    serializer="stxEtxSerializer"
    deserializer="stxEtxSerializer" />

<ip:tcp-inbound-channel-adapter id="inAdapter.server"
    channel="adiIncomingChannel"
    connection-factory="server" />

<channel id="adiIncomingChannel" datatype="java.lang.String" />

<channel id="toSA" datatype="java.lang.String" />
<service-activator input-channel="toSA"
                   ref="tcpMessageReceiver"
                   method="receiveTcpMessageBytes" />

<beans:bean id="tcpMessageReceiver"
      class="com.gcaa.adi.tcp.socket.TcpMessageReceiver" />

<channel id="toObAdapter" />

<ip:tcp-outbound-channel-adapter id="outAdapter.server"
    channel="toObAdapter"
    connection-factory="server" />


<router input-channel="adiIncomingChannel" ref="cmdRouter"></router>    



<beans:bean id="cmdRouter" class="com.gcaa.adi.messaging.router.CommandRouter">
</beans:bean>

您需要显示其余的(上游)配置,但是,如果入站请求是通过网关的,则通常会在路由器中引发异常并处理网关错误通道流上的错误。

您需要显示其余的(上游)配置,但是,如果入站请求是通过网关的,您通常会在路由器中抛出异常,并在网关的错误通道流上处理错误。

谢谢Garry。我已经用配置文件和路由器类更新了这个问题。我正在考虑如下解决这个问题。收到消息后,首先将其发送到验证程序ServiceActivator。如果输入无效,serviceactivator将向错误通道发送错误消息。否则,如果输入有效,validator service activator会将收到的消息转发到其他通道,从而导致进一步处理。请告诉我这是否是验证Spring-integration中接收到的输入的好方法。是,一般来说,最好将验证与路由分开。您好,Gary,您能看到我问题的最后一部分吗?我在这里编辑了它,但有一个异常,如果我从service activator抛出异常,我会得到该异常。我最好的猜测是,您没有将
ip\u connectionId
头复制到出站消息中。我需要查看此错误日志以确认:`logger.ERROR(“无法找到“+消息”的出站套接字)`您正在丢失此处的标题:
抛出新的MessaginException(新的GenericMessage(validCmd Model.getValdationMsg())msg
中的
MessageBuilder
.copyHeaders()
。谢谢Garry。我已经用配置文件和路由器类更新了这个问题。我正在考虑如下解决这个问题。收到消息后,首先将其发送到验证程序ServiceActivator。如果输入无效,serviceactivator将向错误通道发送错误消息。否则,如果输入有效,validator service activator会将收到的消息转发到其他通道,从而导致进一步处理。请告诉我这是否是验证Spring-integration中接收到的输入的好方法。是,一般来说,最好将验证与路由分开。您好,Gary,您能看到我问题的最后一部分吗?我在这里编辑了它,但有一个异常,如果我从service activator抛出异常,我会得到该异常。我最好的猜测是,您没有将
ip\u connectionId
头复制到出站消息中。我需要查看此错误日志以确认:`logger.ERROR(“无法找到“+消息”的出站套接字)`您正在丢失此处的标题:
抛出新的MessaginException(新的GenericMessage(validCmd Model.getValdationMsg())使用
MessageBuilder
.copyHeaders()
来自
msg
public class CommandRouter{

public String contentRouter(byte[] cmdBytes){
    String channelName = null;
    String cmd = new String(cmdBytes);

    //Data Requests
    if(cmd.startsWith(AdiCommandType.DATA_REQUEST.getCode())){

        AdiCommandValidationModel validCmdModel = validateDataCommand(cmd);

        if(! validCmdModel.isValidCmd()){
            // TODO: Send the error to  requesting client. Error = "<ERROR::<DATA::REQUEST>::001>"
        }
        channelName = "toSA";


    } // Health Check Response
    else if(cmd.startsWith("<HEALTH::ACK>")){
        channelName = "toSA";
    }

    return channelName;
}

private AdiCommandValidationModel validateDataCommand(String cmd){
    AdiCommandValidationModel validModel = new AdiCommandValidationModel();
    validModel.setCmd(cmd);

    List<MatchedGroup> matchedCmdItems = GcaaUtil.matchByGroups("^<DATA::(\\d[1-31]-\\d[1-12]-20\\d\\d)::(\\d+)>", cmd);

    if(null != matchedCmdItems && matchedCmdItems.size() > 0){

        // 1. Check if request date is valid
        if(!GcaaUtil.isEmptyString(matchedCmdItems.get(0).getGroup())){
            boolean isValidCmd = GcaaUtil.isDateValid(matchedCmdItems.get(0).getGroup(), "DD-MM-YYYY");
            validModel.setValidCmd(isValidCmd);             
        }else{              
            validModel.setValidCmd(false);
        }

        // return if date is not valid
        if(! validModel.isValidCmd()){
            validModel.setErrorCode(AdiErrorCode.DATA_INVALID_DATE);
            return validModel;
        }

        // 2. Check that DI value is >=0. It should not be less than 0 or NULL
        if(!GcaaUtil.isEmptyString(matchedCmdItems.get(1).getGroup())){
            Integer di = null;
            try{
                di = Integer.parseInt(matchedCmdItems.get(1).getGroup());
            }catch(NumberFormatException nfe){

            }
            if(di== null || di < 0){validModel.setErrorCode(AdiErrorCode.DATA_INVALID_DATE);
            return validModel;}
        }else{
            validModel.setErrorCode(AdiErrorCode.INVALID_COMMAND);
            return validModel;
        }
    }


    if(! validModel.isValidCmd()){
        validModel.setErrorCode(AdiErrorCode.INVALID_COMMAND);
        return validModel;
    }
    return validModel;
}
}
public void validate(Message<byte[]> msg){
    String channelName = null;
    String cmd = new String(msg.getPayload());

    AdiCommandValidationModel validCmdModel = validateDataCommand(cmd);

    if(! validCmdModel.isValidCmd()){
        // TODO: Send to error channel 
        String err = "<ERROR::"+validCmdModel.getCmd()+"::"+validCmdModel.getErrorCode().getCode()+">";
        Message<String> mb = MessageBuilder.createMessage(err, msg.getHeaders());
        throw new MessagingException(mb);
    }

    //Data Requests
    if(cmd.startsWith(AdiCommandType.DATA_REQUEST.getCode())){

        validCmdModel = validateDataCommand(cmd);

        if(! validCmdModel.isValidCmd()){
            // TODO: Send to error channel
            throw new MessagingException(new GenericMessage<String>(validCmdModel.getValdationMsg()));
        }
        channelName = "toSA";


    } // Health Check Response
    else if(cmd.startsWith("<HEALTH::ACK>")){
        channelName = "toSA";   
    }

}
  <!-- Server side -->
    <ip:tcp-connection-factory id="server"
        type="server"
        port="${port}"
        using-nio="true"
        serializer="stxEtxSerializer"
        deserializer="stxEtxSerializer" />

    <ip:tcp-inbound-channel-adapter id="inAdapter.server"
        channel="adiIncomingChannel"
        connection-factory="server" 
        error-channel="inputErrorChannel"/>


    <!-- <object-to-string-transformer input-channel="adiIncomingChannel" output-channel="adiIncomingChannelStr"/> -->

    <service-activator input-channel="adiIncomingChannel"
                       ref="adiInputValidator"
                       method="validate" />

    <channel id="adiIncomingChannel"/>
    <!-- <channel id="adiIncomingChannel" datatype="java.lang.String" /> -->
    <channel id="inputErrorChannel" />

    <channel id="toObAdapter" />

    <ip:tcp-outbound-channel-adapter id="outAdapter.server"
        channel="toObAdapter"
        connection-factory="server" />

    <transformer input-channel="inputErrorChannel"
    output-channel="toObAdapter"
    expression="payload.failedMessage.payload"/>

<!-- dataType attribute invokes the conversion service -->
    <channel id="toSA" datatype="java.lang.String" />

    <service-activator input-channel="toSA"
                       ref="tcpMessageReceiver"
                       method="receiveTcpMessageBytes" />

<!-- output-channel="toObAdapter" -->
    <beans:bean id="tcpMessageReceiver"
          class="com.gcaa.adi.tcp.socket.TcpMessageReceiver" />

    <beans:bean id="adiInputValidator"
          class="com.gcaa.adi.validation.AdiInputValidator" />
TcpConnectionFailedCorrelation -*-*-*-*-*-*-*-*-*-*-**-*
     Connection Correlation ID: null
     Connection Source: org.springframework.integration.ip.tcp.TcpSendingMessageHandler#0
     Connection time: 1486465992372
     Cause = : org.springframework.messaging.MessageHandlingException: Unable to find outbound socket
2017-02-07 15:13:13.183 ERROR 4444 --- [pool-2-thread-3] o.s.i.i.tcp.connection.TcpNioConnection  : Exception sending message: GenericMessage [payload=byte[10], headers={ip_tcp_remotePort=59521, ip_connectionId=127.0.0.1:59521:5677:9a7fd07e-716b-4d1c-8be6-c73223cea9db, ip_localInetAddress=/127.0.0.1, ip_address=127.0.0.1, id=ca87761a-4a39-5869-ad53-7e078cf40508, ip_hostname=127.0.0.1, timestamp=1486465989192}]

org.springframework.messaging.MessageHandlingException: Unable to find outbound socket
    at org.springframework.integration.ip.tcp.TcpSendingMessageHandler.handleMessageInternal(TcpSendingMessageHandler.java:123) ~[spring-integration-ip-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:148) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:423) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:373) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115) ~[spring-messaging-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45) ~[spring-messaging-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:105) ~[spring-messaging-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutput(AbstractMessageProducingHandler.java:292) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.handler.AbstractMessageProducingHandler.produceOutput(AbstractMessageProducingHandler.java:212) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutputs(AbstractMessageProducingHandler.java:129) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:115) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:148) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:423) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:373) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115) ~[spring-messaging-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45) ~[spring-messaging-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:105) ~[spring-messaging-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.integration.endpoint.MessageProducerSupport.sendMessage(MessageProducerSupport.java:176) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.ip.tcp.TcpReceivingChannelAdapter.onMessage(TcpReceivingChannelAdapter.java:88) ~[spring-integration-ip-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.ip.tcp.connection.TcpNioConnection.sendToChannel(TcpNioConnection.java:371) [spring-integration-ip-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.ip.tcp.connection.TcpNioConnection.run(TcpNioConnection.java:240) [spring-integration-ip-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_74]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_74]
    at java.lang.Thread.run(Unknown Source) [na:1.8.0_74]