Announcement Announcement Module
Collapse
No announcement yet.
Error channel/Service Activator Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Error channel/Service Activator

    My class is defined as follows:

    class MyClass
    {
    @Transactional
    public void doFunction(Data data) {
    ....
    }

    I have a service activator defined as:
    <bean id="myClass" class="MyClass"/>
    <service-activator ref="myClass" method="doFunction" input-channel="input"
    output-channel="output"/>

    I would like to extend the above so that if doFunction throws an exception then the exception is routed to another channel:

    <service-activator ref="myClass" method="doFunction" input-channel="input"
    ext:error-channel="errors" output-channel="output"/>

    I can use extensible XML authoring to add the new attribute to service-activator but how do I go about adding the exception handler?

  • #2
    Is the service-activator being invoked asynchronously?

    The reason I ask... in Spring Integration, Exceptions are sent to an error-channel from the TaskExecutor that is executing an asynchronous invocation of an endpoint (e.g. service activator). Otherwise, in a synchronous case, Exceptions are thrown directly back to the caller since the invocation is occurring in the caller's thread.

    As far as the error-channel, there is a default (called "errorChannel") that you may subscribe to, but if you want to control it based on a particular message flow, you can add a header to the Message prior to invocation of the Service Activator (e.g. using "header-enricher" or manually when a Message is constructed).

    Does that make sense?

    Comment


    • #3
      Originally posted by Mark Fisher View Post
      Is the service-activator being invoked asynchronously?

      The reason I ask... in Spring Integration, Exceptions are sent to an error-channel from the TaskExecutor that is executing an asynchronous invocation of an endpoint (e.g. service activator). Otherwise, in a synchronous case, Exceptions are thrown directly back to the caller since the invocation is occurring in the caller's thread.

      As far as the error-channel, there is a default (called "errorChannel") that you may subscribe to, but if you want to control it based on a particular message flow, you can add a header to the Message prior to invocation of the Service Activator (e.g. using "header-enricher" or manually when a Message is constructed).

      Does that make sense?
      Yes the service activator will be invoked asynchronously since somewhere in the message flow would be a task-executor.

      I would like to control the error channel based on the message flow.

      Your solution would entail adding a header enricher before invoking the service activator. The enricher would add a new key to the header which contains the custom error channel I would like to publish to. I would also have to add a header splitter to the errorChannel so that it sends the message to the correct channel?

      Seems a bit messy. Is there any way it can be accomplished by extensible XML authoring? I am trying to make this generic and as easy as possible for other developers to use.

      Comment


      • #4
        Originally posted by Stuff It View Post
        I would also have to add a header splitter to the errorChannel so that it sends the message to the correct channel?
        I'm not sure what you're asking here, but I don't think you need anything other than the header-enricher. You could do something like this:
        Code:
        <chain input-channel="in" output-channel="out">
           <header-enricher error-channel="someChannel"/>
           <service-activator ref="bean" method="x"/>
        </chain>

        Comment


        • #5
          Thanks I tried it and it worked

          Comment


          • #6
            By the way, this is one feature that will be changing slightly in Spring Integration 2.0. Basically, we are moving the attributes into sub-elements, since they otherwise produce some confusion.

            So, the following:
            Code:
            <header-enricher error-channel="someChannel"/>
            Would change to:
            Code:
            <header-enricher>
                <error-channel ref="someChannel">
            </header-enricher>
            For more detail, see the following JIRA issue:
            http://jira.springframework.org/browse/INT-712

            Comment


            • #7
              error-channel attribute

              Hello, I have a stupid question where is the error-channel attribute in the <int:header-enricher> ? in Version 2.0.0.M3

              how do I use it now?

              Comment


              • #8
                That's not a stupid question We moved it to a sub-element, because the top-level attributes were misleading (since that's where the input-channel and output-channel for the header-enricher AS an endpoint belong).

                Here's an example:
                Code:
                <header-enricher input-channel="input" output-channel="output">
                    <error-channel ref="someErrorChannel"/>
                </header-enricher>

                Comment


                • #9
                  failFOMessageChannel doesnt work.

                  What am I doing wrong? I'm trying to test a simple chain by adding a transformer - that throws an exception (see "mercuryWireTap" / "throwException") - this method just throws an exception. The code works apart from this.

                  I was assuming that the error channel ("failFOMessageChannel" would receive this Exception - and the ="foGatewayAdapter"/"fail" method would get called - but instead of this I see an exception.


                  So I guess I'm doing something wrong?

                  Regards

                  Robin



                  <int:chain input-channel="recvFOMessageChannel" output-channel="successFOMessageChannel">
                  <int:header-enricher>
                  <int:error-channel ref="failFOMessageChannel" />
                  </int:header-enricher>
                  <int:transformer ref="mercuryWireTap" method="throwException" />
                  <int:service-activator ref="messageQueueAdapter" method="queue"/>
                  </int:chain>
                  <int:channel id="successFOMessageChannel" />
                  <int:outbound-channel-adapter channel="successFOMessageChannel" ref="foGatewayAdapter" method="success"/>
                  <int:channel id="failFOMessageChannel" />
                  <int:outbound-channel-adapter channel="failFOMessageChannel" ref="foGatewayAdapter" method="fail"/>




                  2688 [main] ERROR org.springframework.integration.handler.LoggingHan dler - org.springframework.integration.transformer.Messag eTransformationException: org.springframework.integration.MessageHandlingExc eption: java.lang.Exception: BC601836:Equity
                  at org.springframework.integration.transformer.Messag eTransformingHandler.handleRequestMessage(MessageT ransformingHandler.java:73)
                  at org.springframework.integration.handler.AbstractRe plyProducingMessageHandler.handleMessageInternal(A bstractReplyProducingMessageHandler.java:98)
                  at org.springframework.integration.handler.AbstractMe ssageHandler.handleMessage(AbstractMessageHandler. java:78)
                  at org.springframework.integration.handler.MessageHan dlerChain$1.send(MessageHandlerChain.java:150)
                  at org.springframework.integration.core.MessagingTemp late.doSend(MessagingTemplate.java:288)
                  at org.springframework.integration.core.MessagingTemp late.send(MessagingTemplate.java:149)
                  ...
                  Caused by: org.springframework.integration.MessageHandlingExc eption: java.lang.Exception: BC601836:Equity
                  at org.springframework.integration.handler.MethodInvo kingMessageProcessor.processMessage(MethodInvoking MessageProcessor.java:76)
                  at org.springframework.integration.transformer.Abstra ctMessageProcessingTransformer.transform(AbstractM essageProcessingTransformer.java:56)
                  at org.springframework.integration.transformer.Messag eTransformingHandler.handleRequestMessage(MessageT ransformingHandler.java:67)
                  ...
                  Caused by: java.lang.Exception: BC601836:Equity
                  at com.xxxxxx.mercury.MercuryWireTap.throwException(M ercuryWireTap.java:82)
                  at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
                  at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)

                  Comment


                  • #10
                    In your case Exception will go to error-channel only if your flow is asynchronous. In your case it is synchronous. You can read more here http://static.springsource.org/sprin...e-errorhandler
                    In the nutshel the reason behind it is that in the sync flow the downstream execution is handled by the same thread as the caller (you in this case) so by re-throwing an exception we essentially communicating the error condition back to the caller. In the async flow the downstream thread is different then the caller thread so in order for caller to know if something went wrong downstream such caller needs to subscribe to some error-handling facility and this is where error-channel comes in.
                    Does that explain?

                    Comment


                    • #11
                      Yes - what I had to do was put the error-channel="failFOMessageChannel" right at the start of the message flow then it picked up on it.

                      <int:gateway id="foGateway" service-interface="com.xxxx.mercury.fo.FOGateway"
                      default-request-channel="recvFOMessageChannel"
                      error-channel="failFOMessageChannel" />

                      Comment


                      • #12
                        Well, this is a bit different.
                        You are using Gateway. Messaging Gateway is unique in the way that it actually by definition is bi-directional which means it expectes a reply (although we do allow void gateway methods, but that is a different topic). The fact that a typical gateway expects a reply means that it encapsulates both the producer and consumer in a single component. This means that while it sends Message to a default-request-channel it (the consumer part of it) actually waits for the reply from the reply channel which could be explicit or implicit. This contract must be preserved regardless if the downstream flow resulted in exception or if it was sync or async. So there is always an implicit error-channel when constructing gateway and all errors will be sent to that channel (it is anonymous temporary channel). Once the error message is received it wil be converted to a MessagingException and re-thrown. However, some times you don't want that and as I explained in the previous post you may want to always return successfully while communicating the error (e.g., SOAP Fault is a good example). In this case you can define an explicit error-channel (as you did) and what that does is allowing the ErrorMessage received on the anonymous errorChannel to be delegated to an explicit error-channel where user can subscribe to and handle the error. Handling could be done in two ways. 1. Receive ErrorMessage, process it (e.g., log) and return a new Successful message with some error code in the payload or simply re-throw an exception or different exception after processing original error etc...
                        Does that clarify?

                        Comment


                        • #13
                          Can I ask the question again - as it helps me to understand. If I have a gateway and a chain of other processes, I want those downstream processes to be able to throw an exception - then have the gateway receive the error - and keep the request/reply contract.

                          You say that the contract (to receive a reply) must be preserved regardless of a downstream exception - does this mean that a reply message must be sent down the receive-channel even if an exception has happened. My instinct is to think of Java method semantics ... and to say the reply message could be received down the reply-channel (like a return value in a method) *or* the error-channel (like an exception in a method).

                          So just to clarify (again) - if a down stream process throws an exception could I send that exception (indirectly) to the reply channel - and meet the contract that way?
                          Last edited by robin.sharp; Apr 14th, 2011, 02:52 AM.

                          Comment


                          • #14
                            When inbound gateway is created framework automatically creates two more anonymous and temporary channels (replyChannel and errorChannel). Actually its one channel which is used for errors and replies and then the reference to this channel travels with Message headers (replyChannel, errorChannel)
                            This happens regardless if you explicitly define reply-channel and/or error-channel.

                            When exception happens downstream it will be converted to an ErrorMessage and sent to the 'errorChannel' provided via 'errorChannel' header. Once the ErrorMessage is received two things may happen. If you did not define an explicit error-channel, then the payload of the ErrorMessage will be extracted (Throwable) and re-thrown back to the caller. If you DID define an explicit error-channel, then the ErrorMessage will be sent to that channel. Now the subscriber of that channel has two choices. 1. Handle exception and return successful Message or 2. Handle exception and return it so it could be re-thrown back to the caller.
                            So basically the error-channel on the gateway gives you one last chance to deal with the exception before such exception has been communicated back to the caller.

                            Comment


                            • #15
                              Hi,

                              I am using Spring Integration in my project.

                              Below is the part of the configuration that i am using in my project whenever there is an exception in the header enricher it is not propogated to the error channel


                              Code:
                              <header-enricher>
                                			<header name="Information" method="extractInformation" ref="infoExtractor" />
                                			<error-channel ref="InfoErrorChannel"/>
                                		</header-enricher>
                                		
                              		<transformer input-channel="InfoErrorChannel">
                              			<beans:bean class="com.test.integration.ErrorBuilder">
                              				<beans:property name="description" value="Error in info extractor" />
                              			</beans:bean>
                              		</transformer>
                              Kindly throw some light on this

                              Thanks,
                              Shekar

                              Comment

                              Working...
                              X