Page 2 of 2 FirstFirst 12
Results 11 to 17 of 17

Thread: tcp-inbound-gateway error-channel assistance

  1. #11
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,147

    Default

    Let me explain the replyChannel stuff a little more, in the context of an error channel.

    Many inbound gateways extend MessagingGatewaySupport; in turn, that class uses a MessagingTemplate sendAndReceive() method to send the request and wait for the reply. In this method, the MessagingTemplate inserts a new temporary reply channel into the message header and sends it off. If the flow completes ok, it receive()s the result from that channel. Note: if the reply is sent to the gateway's 'reply-channel' instead, that channel is automatically bridged to the temporary channel. In both cases, the messaging template gets its reply from that channel.

    Now, when an exception occurs, that exception is caught by the gateway code; by this time the old reply channel is no longer any use - nobody will ever receive() from it; it will simply be garbage-collected once all references go out of scope. The method that declared it is already out of scope because the exception propagates down to MessagingGatewaySupport.

    After catching the exception, the gateway tries to send the ErrorMessage to the error channel; again using the MessagingTemplate which, again, inserts a new Temporary reply channel, from which it will receive() the result. Again, the result can be returned automatically by the ultimate consumer not declaring an output-channel or the message can be sent to the gateway's reply-channel and it will, again, be bridged to the temporary reply channel on which the template will do a receive().

    I hope that clarifies the process.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  2. #12
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,147

    Default

    Actually, let me revise my suggestion for the method signature - you don't need the entire ErrorMessage...

    Code:
        public MUMessage onErrorMessage(MessagingException exception) {
            ...
            return <MUMessage with error content>
        }
    The framework will unwrap the payload for you.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  3. #13

    Default

    Quote Originally Posted by Gary Russell View Post
    Actually, let me revise my suggestion for the method signature - you don't need the entire ErrorMessage...

    Code:
        public MUMessage onErrorMessage(MessagingException exception) {
            ...
            return <MUMessage with error content>
        }
    The framework will unwrap the payload for you.
    Gary, you are wonderful! This now works for me as intended. Many thanks!

  4. #14

    Default

    Quote Originally Posted by Gary Russell View Post
    Let me explain the replyChannel stuff a little more, in the context of an error channel.
    [stuff removed for brevity]
    I hope that clarifies the process.
    This is starting to make sense, I will need to read it a few times and look at logs to fully understand it.

    One question comes up now. Should a service-activator, which has a response message to send back, have its "output-channel":
    - set to the gateway "reply-channel" (which I do now)
    - set to the message's header "replyChannel"
    - set to a service-activator specific channel (for wire tap, etc) and bridge this channel to gateway "reply-channel"
    - not set at all, so SI (assumes its a response) figures it out?

  5. #15
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,147

    Default

    Right, for the most part, you shouldn't have to deal with the header directly yourself; so I would stay away from your second option.

    The general recommendation is...

    Leave off the output-channel from the last (ultimate) consumer - service-activator, transformer, whatever; when there's no output-channel we route directly to the replyChannel header.

    The only time it's necessary to declare a reply-channel, and specifically route to it, is when you want to do something like...

    1. Log the result via a wire tap or otherwise intercept the response.
    2. Make the reply-channel a <publish-subscribe-channel/> so that you can send a copy of the response someplace else (e.g. to a LoggingChannelAdapter, or to some auditing service, or whatever), in addition to sending it to the gateway.

    Some people prefer to always use a reply-channel "just because" they prefer too; that's OK too. Logically, it makes no difference.

    The other main recommendation is to code POJOs wherever possible; that way you can rely on the framework to do the right thing; you don't have to worry about the messaging infrastructure. It also makes for testable units without any dependencies on the framework.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  6. #16

    Default

    Wrangler, I was going through this thread, Could you please share the final code snippet along with the wiring snap shot please. Thanks.

  7. #17

    Default

    Quote Originally Posted by JeevanSpring View Post
    Wrangler, I was going through this thread, Could you please share the final code snippet along with the wiring snap shot please. Thanks.
    It has been a while since I looked at this thread, or the code. My exception handling starts at the gateway, which has the property error-channel="inboundGatewayErrorChannel", which is just a channel definition.

    At one time I started to look into the channel having a queue:
    Code:
    <!--The gateway error channel is a queue channel so it runs in a separate thread form the source-->
        <int:channel id="inboundGatewayErrorChannel">
            <!--<int:queue capacity="25"/>-->
        </int:channel>
    My next step wqas to set up a service activtor, so a POJO can do some useful business logic, which for me is building a proper SOAP fault as a String of XML.
    Code:
        <int:service-activator id="gatewayErrorHandler"
                               input-channel="inboundGatewayErrorChannel"
                               output-channel="outboundGatewayErrorChannel"
                               method="onErrorMessage">
            <beans:bean class="com...audit.DefaultErrorMessageHandler"/>
        </int:service-activator>
    The XML string is placed in a Message<String> for the service activator response, which goes to the service activator's output-channel:
    Code:
    responseMessage = MessageBuilder.withPayload(stringMessage)
                    .setReplyChannel((MessageChannel) errorMessage.getHeaders().getReplyChannel())
                    .copyHeadersIfAbsent(failedMessage.getHeaders())
                    .setHeader("errorMessage", "DefaultErrorMessageHandler")
                    .build();
    The service activator's output-channel, is intercepted with a wiretap:
    Code:
    <int:channel id="outboundGatewayErrorChannel" datatype="java.lang.String">
            <int:interceptors>
                <int:wire-tap channel="gatewayExceptionAuditChannel"/>
            </int:interceptors>
        </int:channel>
    Since we have a particular way to do async audit logging with a POJO, I use a wiretap POJO, for which the output is then bridged to the gateway output channel. Our audut logging can toggled to enabled/disabled using an external property file value.
    Code:
        <int:bridge id="bridgeErrorToClient" 
                    input-channel="outboundGatewayErrorChannel"
                    output-channel="outboundChannel"/>
    
        <int:channel id="gatewayExceptionAuditChannel"  datatype="java.lang.String"/>
        <int:header-enricher input-channel="gatewayExceptionAuditChannel" 
                                    output-channel="auditLoggingChannel">
            <int:header name="sequenceName" value="0000 Exception caught at gateway"/>
            <int:header name="keyword" value="gateway error"/>
            <int:header name="loggingEnabled" value="${gateway.logging.enabled}"/>
            <int:header name="auditDirection" expression="T(com...audit.AuditLoggingDirection).ERROR"/>
        </int:header-enricher>

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •