Announcement Announcement Module
Collapse
No announcement yet.
Exception propagation to the client from Spring integration Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Exception propagation to the client from Spring integration

    Hi,
    I am new to Spring integration. I have developed a sample service using spring integration using gateway and service activator. I have use xml payloads, for this I have JIBX marshaller/unmarshaller. It is working fine as expected.
    I have below few questions regarding exception handling:
    1. If there is any exception in the Service activator method, will I be propagate the exception to the client code which consume this service? I have tried with global error handling as below:
    <http:inbound-gateway request-channel="inChannel"
    reply-channel="outChannel"
    name="/inGateway" error-channel="exceptionChannel"
    supported-methods="POST"/>
    <int:transformer input-channel="exceptionChannel"
    ref="exceptionTransformer" method="createErrorResponse" output-channel="stringChannel"/>
    <bean id="exceptionTransformer" class="com.test.exception.ExceptionTransformer" />
    <int:channel id="exceptionChannel" />
    <int:object-to-string-transformer input-channel="stringChannel" output-channel="outChannel"/>
    But here also, I need to return a Message<?>?

    2. If propagating the exception to the client is not possible, then how will client handle the exception?

    Basically, I need the same functionality like SOAPFAULT exception in spring integration.
    It would be great, if you can provide the clarification for the above questions.
    Last edited by Mission; Mar 20th, 2012, 02:02 AM.

  • #2
    Hello

    Actually you're not right.
    In the first: if you don't declare error-channel on the <http:inbound-gateway> and do not setup convert-exceptions="true", then your Exception will be thrown back to the FrameworkServlet, where you can use some configuration of the instance of org.springframework.web.servlet.HandlerExceptionRe solver

    In the second: if you don't declare error-channel and use convert-exceptions="true", then your Exception will be converted with some declared by default org.springframework.integration.http.converter.Ser ializingHttpMessageConverter.

    In third: if you declare error-channel="exceptionChannel" and handle it in some Transformer, then result of it will be used as responseContent. Here you haven't to have output-channel="outChannel" on the last object-to-string-transforme: error-flow just simple request/reply and result will be returned to the caller - <http:inbound-gateway>.
    Well, and here you may build your a-la SOAPFault logic.

    And answer to your second question:
    If you use <http:inbound-gateway> your client just receive HttpResponse, but not Exception.
    He can check HttpStatus and of course parse response body.

    I hope I was clear,
    Artem Bilan

    Comment


    • #3
      Thanks for your quick reply.

      I have tried with the third approach, where I set up the error-channel and an exception transformer as below:
      <http:inbound-gateway request-channel="inChannel"
      reply-channel="outboundChannel" convert-exceptions="true"
      name="/inGateway" error-channel="exceptionTransformationChannel"
      supported-methods="POST"/>

      <int:transformer input-channel="exceptionTransformationChannel"
      ref="exceptionTransformer" method="createErrorResponse" output-channel="exceptionConvertorChannel" />
      <bean id="exceptionTransformer" class="com.test.exception.ExceptionTransformer" />
      <int:object-to-string-transformer input-channel="exceptionConvertorChannel"/>

      The method signature of my exception transformer method:
      public Message<?> createErrorResponse(Message<?> m);

      From the transformer also, it returns Message<?> of Message<Throwable> type. Now in both the scenario, whether there is an exception or not, I am getting the response code as 200 in the client. That is why I am not able distinguished the exception from the normal flow in the client code.
      Can you please provide some more information on this?

      Thanks
      Last edited by Mission; Mar 20th, 2012, 04:36 AM.

      Comment


      • #4
        That is why I am not able distinguished the exception from the normal flow in the client code
        Well, you just need to put into your transformer's returned Message header:
        org.springframework.integration.http.HttpHeaders.S TATUS_CODE with some value from org.springframework.http.HttpStatus

        Off topic.
        In the future: please, use [ CODE ] [ /CODE ] (without whitespaces) notations to wrap your sample sources.

        Comment


        • #5
          Thanks you very much. I have implemented as per your suggestion and it is working fine.

          Can you please validate the Exception Transformer class that I have built? Below is the logic:
          1. The message that is received in the exception transformer is of the payload "org.springframework.integration.dispatcher.Aggreg ateMessageDeliveryException"
          2. Need to iterate this and find out the "org.springframework.integration.MessageHandlingEx ception" type. The method getCause() of this exception, will give the exact exception that is thrown from the Service Activator method.
          3. Create a org.springframework.integration.message.ErrorMessa ge object with the real exception extracted in step 2.
          4. The final step is to build the Message<Throwable> object with the payload of step 3. Place the proper http status code and reply channel in the header.
          5. Return this message to the caller.

          Comment


          • #6
            Yes, your logic is correct.
            However you can return to the response not only Throwable.
            In your transformer you may return anything you want: some String, XML, JSON etc.

            Comment


            • #7
              Cleric

              I am trying to get exception from outbound TCP gateway, but I am unsuccessful.

              Here is tcp outbound gateway configurations.

              <int-ip:tcp-outbound-gateway id="myTCPOutGateway"
              request-channel="tcpIn"
              reply-channel="tcpOut"
              connection-factory="myTCPClient"
              request-timeout="2000"
              reply-timeout="2000"/>
              Then I define the error channel


              <beans:bean id="myChannelException"
              class="org.test.ChannelException" />
              <beans:bean id="myErrorLogger"
              class="org.test.ChannelErrorLogger" />

              <intoller default="true" fixed-rate="500"
              max-messages-per-poll="10" />

              <int:channel id="myErrorChannel" />


              <int:channel id="errorChannel">
              <int:queue capacity="50" />
              </int:channel>


              <int:chain input-channel="errorChannel">
              <int:header-enricher>
              <int:error-channel ref="myErrorChannel" />
              </int:header-enricher>
              <int:service-activator ref="myChannelException"
              method="processChannelMessage" />
              </int:chain>

              <int:service-activator input-channel="myErrorChannel"
              ref="myErrorLogger" />

              I put no existing tcp/ip address on the connection factory. I got spring exception in the console, but never go to the error channel. any one hnow how to propagat to the client. Any helping is appricated.

              Comment


              • #8
                Hi!

                How do you start the message flow? Now you show just a place where Exception appear.
                From other side: you are using
                HTML Code:
                <int:header-enricher>
                <int:error-channel ref="myErrorChannel" />
                </int:header-enricher>
                not correctly.
                Try to study samples, to understand how to handle errors:
                https://github.com/SpringSource/spri.../errorhandling

                Comment


                • #9
                  Thanks Cleric,

                  Here is starting the flow.

                  <int:gateway id="gw"
                  service-interface="org.springframework.integration.samples .tcpclientserver.SimpleGateway"
                  default-request-channel="tcpIn"
                  default-reply-channel="tcpOut"/>

                  <int-ip:tcp-connection-factory id="client"
                  type="client"
                  host="126.1.1.10"
                  port="1441"
                  single-use="false" using-nio="false" so-keep-alive="true"
                  so-timeout="10000"
                  />

                  <int:channel id="tcpIn" />

                  <int-ip:tcp-outbound-gateway id="myTCPOutGateway"
                  request-channel="tcpIn"
                  reply-channel="tcpOut"
                  connection-factory="client"
                  request-timeout="10000"
                  reply-timeout="10000"
                  />


                  <int:channel id="tcpOut" datatype="java.lang.String" />

                  Because the host="126.1.1.10" is no existing. It gets an exception when send TCP socket data on tcpIn channel.
                  Here is error log
                  11:59:39.652 DEBUG [main][org.springframework.integration.channel.DirectChan nel] preSend on channel 'input', message: [Payload=FAIL][Headers={timestamp=1371657579652, id=db94915e-1ad4-42ed-82f6-7facd4952f9d, errorChannel=org.springframework.integration.core. MessagingTemplate$TemporaryReplyChannel@665b6d00, replyChannel=org.springframework.integration.core. MessagingTemplate$TemporaryReplyChannel@665b6d00}]
                  11:59:39.652 DEBUG [main][org.springframework.integration.ip.tcp.TcpOutbound Gateway] org.springframework.integration.ip.tcp.TcpOutbound Gateway#0 received message: [Payload=FAIL][Headers={timestamp=1371657579652, id=db94915e-1ad4-42ed-82f6-7facd4952f9d, errorChannel=org.springframework.integration.core. MessagingTemplate$TemporaryReplyChannel@665b6d00, replyChannel=org.springframework.integration.core. MessagingTemplate$TemporaryReplyChannel@665b6d00}]
                  11:59:39.652 DEBUG [main][org.springframework.integration.ip.tcp.connection. TcpNetClientConnectionFactory] Opening new socket connection to 126.1.1.10:5678
                  12:00:00.658 ERROR [main][org.springframework.integration.ip.tcp.TcpOutbound Gateway] Tcp Gateway exception
                  java.net.ConnectException: Connection timed out: connect
                  at java.net.PlainSocketImpl.socketConnect(Native Method)
                  at java.net.PlainSocketImpl.doConnect(Unknown Source)
                  at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
                  at java.net.PlainSocketImpl.connect(Unknown Source)
                  at java.net.SocksSocketImpl.connect(Unknown Source)
                  at java.net.Socket.connect(Unknown Source)
                  at java.net.Socket.connect(Unknown Source)
                  at java.net.Socket.<init>(Unknown Source)
                  at java.net.Socket.<init>(Unknown Source)
                  at javax.net.DefaultSocketFactory.createSocket(Unknow n Source)
                  at org.springframework.integration.ip.tcp.connection. TcpNetClientConnectionFactory.createSocket(TcpNetC lientConnectionFactory.java:89)
                  at org.springframework.integration.ip.tcp.connection. TcpNetClientConnectionFactory.obtainConnection(Tcp NetClientConnectionFactory.java:63)
                  at org.springframework.integration.ip.tcp.connection. AbstractClientConnectionFactory.getConnection(Abst ractClientConnectionFactory.java:49)
                  at org.springframework.integration.ip.tcp.TcpOutbound Gateway.handleRequestMessage(TcpOutboundGateway.ja va:115)
                  at org.springframework.integration.handler.AbstractRe plyProducingMessageHandler.handleMessageInternal(A bstractReplyProducingMessageHandler.java:134)
                  at org.springframework.integration.handler.AbstractMe ssageHandler.handleMessage(AbstractMessageHandler. java:73)
                  at org.springframework.integration.dispatcher.Unicast ingDispatcher.doDispatch(UnicastingDispatcher.java :115)
                  at org.springframework.integration.dispatcher.Unicast ingDispatcher.dispatch(UnicastingDispatcher.java:1 02)
                  at org.springframework.integration.channel.AbstractSu bscribableChannel.doSend(AbstractSubscribableChann el.java:77)
                  at org.springframework.integration.channel.AbstractMe ssageChannel.send(AbstractMessageChannel.java:157)
                  at org.springframework.integration.channel.AbstractMe ssageChannel.send(AbstractMessageChannel.java:128)
                  at org.springframework.integration.core.MessagingTemp late.doSend(MessagingTemplate.java:288)
                  at org.springframework.integration.core.MessagingTemp late.doSendAndReceive(MessagingTemplate.java:318)
                  at org.springframework.integration.core.MessagingTemp late.sendAndReceive(MessagingTemplate.java:239)
                  at org.springframework.integration.core.MessagingTemp late.convertSendAndReceive(MessagingTemplate.java: 274)
                  at org.springframework.integration.gateway.MessagingG atewaySupport.doSendAndReceive(MessagingGatewaySup port.java:224)
                  at org.springframework.integration.gateway.MessagingG atewaySupport.sendAndReceive(MessagingGatewaySuppo rt.java:203)
                  at org.springframework.integration.gateway.GatewayPro xyFactoryBean.invokeGatewayMethod(GatewayProxyFact oryBean.java:306)
                  at org.springframework.integration.gateway.GatewayPro xyFactoryBean.doInvoke(GatewayProxyFactoryBean.jav a:269)
                  at org.springframework.integration.gateway.GatewayPro xyFactoryBean.invoke(GatewayProxyFactoryBean.java: 260)
                  at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :172)
                  at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:202)
                  at com.sun.proxy.$Proxy11.send(Unknown Source)
                  at org.springframework.integration.samples.tcpclients erver.TcpClientServerDemoTest.testFail(TcpClientSe rverDemoTest.java:79)
                  at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
                  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknow n Source)
                  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Un known Source)
                  at java.lang.reflect.Method.invoke(Unknown Source)
                  at org.junit.runners.model.FrameworkMethod$1.runRefle ctiveCall(FrameworkMethod.java:44)
                  at org.junit.internal.runners.model.ReflectiveCallabl e.run(ReflectiveCallable.java:15)
                  at org.junit.runners.model.FrameworkMethod.invokeExpl osively(FrameworkMethod.java:41)
                  at org.junit.internal.runners.statements.InvokeMethod .evaluate(InvokeMethod.java:20)
                  at org.junit.internal.runners.statements.RunBefores.e valuate(RunBefores.java:28)
                  at org.springframework.test.context.junit4.statements .RunBeforeTestMethodCallbacks.evaluate(RunBeforeTe stMethodCallbacks.java:74)
                  at org.springframework.test.context.junit4.statements .RunAfterTestMethodCallbacks.evaluate(RunAfterTest MethodCallbacks.java:83)
                  at org.springframework.test.context.junit4.statements .SpringRepeat.evaluate(SpringRepeat.java:72)
                  at org.springframework.test.context.junit4.SpringJUni t4ClassRunner.runChild(SpringJUnit4ClassRunner.jav a:231)
                  at org.junit.runners.BlockJUnit4ClassRunner.runChild( BlockJUnit4ClassRunner.java:49)
                  at org.junit.runners.ParentRunner$3.run(ParentRunner. java:193)
                  at org.junit.runners.ParentRunner$1.schedule(ParentRu nner.java:52)
                  at org.junit.runners.ParentRunner.runChildren(ParentR unner.java:191)
                  at org.junit.runners.ParentRunner.access$000(ParentRu nner.java:42)
                  at org.junit.runners.ParentRunner$2.evaluate(ParentRu nner.java:184)
                  at org.springframework.test.context.junit4.statements .RunBeforeTestClassCallbacks.evaluate(RunBeforeTes tClassCallbacks.java:61)
                  at org.springframework.test.context.junit4.statements .RunAfterTestClassCallbacks.evaluate(RunAfterTestC lassCallbacks.java:71)
                  at org.junit.runners.ParentRunner.run(ParentRunner.ja va:236)
                  at org.springframework.test.context.junit4.SpringJUni t4ClassRunner.run(SpringJUnit4ClassRunner.java:174 )
                  at org.eclipse.jdt.internal.junit4.runner.JUnit4TestR eference.run(JUnit4TestReference.java:50)
                  at org.eclipse.jdt.internal.junit.runner.TestExecutio n.run(TestExecution.java:38)
                  at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.runTests(RemoteTestRunner.java:467)
                  at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.runTests(RemoteTestRunner.java:683)
                  at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.run(RemoteTestRunner.java:390)
                  at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.main(RemoteTestRunner.java:197)
                  12:00:00.660 WARN [main][org.springframework.integration.gateway.GatewayPro xyFactoryBean$MethodInvocationGateway] failure occurred in gateway sendAndReceive
                  org.springframework.integration.MessagingException : Failed to send or receive
                  at org.springframework.integration.ip.tcp.TcpOutbound Gateway.handleRequestMessage(TcpOutboundGateway.ja va:136)
                  at org.springframework.integration.handler.AbstractRe plyProducingMessageHandler.handleMessageInternal(A bstractReplyProducingMessageHandler.java:134)
                  at org.springframework.integration.handler.AbstractMe ssageHandler.handleMessage(AbstractMessageHandler. java:73)
                  at org.springframework.integration.dispatcher.Unicast ingDispatcher.doDispatch(UnicastingDispatcher.java :115)
                  at org.springframework.integration.dispatcher.Unicast ingDispatcher.dispatch(UnicastingDispatcher.java:1 02)
                  at org.springframework.integration.channel.AbstractSu bscribableChannel.doSend(AbstractSubscribableChann el.java:77)
                  at org.springframework.integration.channel.AbstractMe ssageChannel.send(AbstractMessageChannel.java:157)
                  at org.springframework.integration.channel.AbstractMe ssageChannel.send(AbstractMessageChannel.java:128)
                  at org.springframework.integration.core.MessagingTemp late.doSend(MessagingTemplate.java:288)
                  at org.springframework.integration.core.MessagingTemp late.doSendAndReceive(MessagingTemplate.java:318)
                  at org.springframework.integration.core.MessagingTemp late.sendAndReceive(MessagingTemplate.java:239)
                  at org.springframework.integration.core.MessagingTemp late.convertSendAndReceive(MessagingTemplate.java: 274)
                  at org.springframework.integration.gateway.MessagingG atewaySupport.doSendAndReceive(MessagingGatewaySup port.java:224)
                  at or
                  ....
                  This outbound tcp don't allow to define the error channel, how do I get this messge to error channel. Thanks

                  Comment


                  • #10
                    When posting code/config please use [ code ] ... [ /code ] tags (no spaces in brackets).

                    The error-channel goes on the <int:gateway id="gw"...

                    Comment


                    • #11
                      Thanks. If the input data from message channel, what's the error channel goes to ?

                      Comment


                      • #12
                        No; an ErrorMessage with a payload of MessagingException is sent on the error channel; the payload has two properties - failedMessage - the message at the point of failure and cause - the exception.

                        If the flow on the error channel "consumes" the error message and sends a normal reply, the client will get that reply; if it throws another (or the original) exception, the client has to catch it.

                        Comment


                        • #13
                          Can you please send your code to me? I am working to propagate the java.net.socketException back to the client, but the message is being wrapped under MessagingException.

                          Comment


                          • #14
                            It's hard for us to provide an answer to question like this because it really depends on how your application is configured.

                            Please show your configuration and exactly what you are trying to achieve,

                            Comment


                            • #15
                              My situation is to emulate the socketnet exception which is thrown by our client in the production. We send a http request to the client via http-outbound gateway and the client returns an exception back and the root cause of the exception is socket net exception.

                              The goal here is to emulate the client error and sent back the socket next exception to our service. I hope you understood the entire scenario. Here is the code...
                              Code:
                              <int-http:inbound-gateway id="inboundDispositions"
                              		  path="/DISPOSITION_SERVICES/{leadProvider}"
                              		  request-channel="processInboundDisposition" error-channel="errorChannel">							 	
                              	<int-http:header name="leadProvider" expression="#pathVariables.leadProvider"/>
                              </int-http:inbound-gateway>
                              
                              <int:service-activator input-channel="processInboundDisposition" ref="urbanScienceMockResponseCodeGenerator" method="getExceptionMessage"/>
                              	   
                              <int:chain id="generateSocketNetException" input-channel="errorChannel" output-channel="exceptionConvertorChannel">
                              	<int:header-enricher>
                              	<int:header name="#{T(org.springframework.integration.http.HttpHeaders).STATUS_CODE}" expression="T(org.springframework.http.HttpStatus).INTERNAL_SERVER_ERROR"/>
                              	</int:header-enricher>	
                              	<int:transformer ref="urbanScienceMockResponseCodeGenerator" method="getSocketException"/>	
                              </int:chain>
                               
                              <int:object-to-string-transformer input-channel="exceptionConvertorChannel"/>
                              Java Code:
                              Code:
                              public void getExceptionMessage(@Payload String payload) throws SocketException
                              	{		 
                              		//return MessageBuilder.withPayload(HttpStatus.BAD_REQUEST).build();
                              		 getSocketNetException();	 
                              	}	
                              	
                              	private void getSocketNetException() throws SocketException{
                              		throw new SocketException("Connection reset-Mock");				
                              	}
                              	
                              	public Message<Throwable> getSocketException(Throwable throwable) {		 
                              		Throwable rootCause = org.apache.commons.lang.exception.ExceptionUtils.getRootCause(throwable);
                              
                              		if (rootCause == null) {
                              			rootCause = throwable.getClass().cast(throwable);
                              		}
                              		
                              		return MessageBuilder.withPayload(rootCause).build();	 //http_statusCode
                              	}
                              So when the socknet exception is being thrown back, it is being wrapped by the messaging exception by our actual service which is using outbound-gateway. Hope you understood my situation

                              Thanks
                              Mohammed Murtuza
                              Last edited by Gary Russell; Aug 18th, 2013, 08:55 PM.

                              Comment

                              Working...
                              X