Announcement Announcement Module
Collapse
No announcement yet.
Synchronous Error Handling Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Synchronous Error Handling

    I hava a doubt about synchronous - asynchronous messaging and error handling.

    I have a service that send a message to a channel that is connected to an SFTP Outbound Adapter. I have a try-catch around send call. In asynchronous mode the service always returns true after sending the message. In synchronous mode it waits until SFTP is ok or an exception is thrown and returns false in that case.

    I'd like to have the possibility to switch fast between synchronous messaging to asynchronous messaging so I have two channels and a bridge, a queue channel 1, a pub-sub channel 2 and a bridge between them. If I want synchronous messaging I send to the channel 2 directly. If I want asyncronous messaging I send to the channel 1.

    In the errorChannel I receive all errors and perform some logging and process. The problem is that in asynchronous mode, the exception in the SFTP call is sent to the errorChannel, but in synchronous mode, the exception flows directly to the caller and I need to repeat the logging an process logic in the catch block. If I remove the try-catch arount the send call, in synchronous mode the exception is then sent to the errorChannel but the caller never returns and I can't return a false in the service.

    I'd like to pass all errors to the error channel but also return to the caller after, in case of synchronous call to return a false in my service. żIs it possible to do this? I'd like my service to be transparent regarding sync or async, only configuration changes.

    Thank you for your help in advance.

  • #2
    Any chance you could put up the config and the code for the service activator to give us a head start in recreating?
    Thanks

    Comment


    • #3
      Thats a summarize of the code

      The spring integration config regarding this case

      Code:
      [...]
      <channel id="channel1">
      	<queue capacity="1000"/>
      </channel>
      <publish-subscribe-channel id="channel2" />
      						   
      <bridge input-channel="channel1"
        	   output-channel="channel2">	
      	<poller max-messages-per-poll="16" fixed-rate="10000"/>		
      </bridge>	
      
      <sftp:outbound-channel-adapter channel="channel2" 
      	session-factory="sftpSessionFactory" 
      	remote-directory="${sftp.dir}"
      	temporary-file-suffix="uploading"/>
      
      <service-activator input-channel="errorChannel"
      		          output-channel="nullChannel" 
      			   ref="myServiceActivator" 
      		           method="handleError"/>
      [...]
      MyService

      Code:
      public class MyServiceImpl {
      
         @Autowired
         @Qualifier("channel1") // or "channel2"
          private MessageChannel sftpChannel;
      
          public boolean uploadFile(String filename) {
      		try {
      			sftpChannel.send(MessageBuilder.withPayload(filename)).build());	
      			return true;
      		} catch (Exception e) {
      			return false;
      		}
          }
      }
      MyServiceActivator

      Code:
      public class MyServiceActivator {
      
          public void handleError(MessagingException e) {
                  // Logging and process
      
          }
      }
      Thanks

      Comment


      • #4
        In all cases the exception always goes back to the caller. The real question is who is the caller? When a user invokes synchronous operation he/she is the caller, but in the async case the newly allocated thread is the caller. The initial call from the user was returned right away after it was delegated to this new thread (new caller). So in other words in the sync case you have complete control of the invocation and as you pointed out you can surround it with a try/catch block. However in the async case the try/catch block is meaningless (as you said), so the errorChannel is just a way to plug your catch block if you need too.
        That said, you can easily accomplish all you want by fronting your flow with MessagingGateway which has an error-channel attribute.
        Code:
        <int:gateway . . . error-channel="myErrorChannel"/>
        For more on gateways please read this http://static.springsource.org/sprin...ingle/#gateway

        Comment


        • #5
          The xsd specifies that the session-factory should be of type org.springframework.integration.sftp.session.SftpS essionFactory.
          I can only see an implementation called org.springframework.integration.sftp.session.Defau ltSftpSessionFactory
          Looking in the history it was interfaced and renamed as such.

          Comment


          • #6
            @dnlegge the XSD should specify this interface: org.springframework.integration.file.remote.sessio n.SessionFactory
            That is what DefaultSftpSessionFactory implements (after some refactoring). Could you please open a JIRA issue for that change?

            Thanks,
            Mark

            Comment


            • #7
              @occus3 out of interest, what version of SI are you using? I have had a couple of problems with your config snippet in the latest (2.0.5)

              Comment


              • #8
                Hi,

                I'm using 2.0.4, I really didn't know there was a new release.

                Thank you all for your help. I think the gateway will be the best solution. As oleg said, in synchronous mode the exception always flow to the caller. I didn't realize that my service (uploadFile) is called from a service activator that is called from a pollable channel, so if I remove the try/catch, the exception will go to the errorChannel because nobody handle this exception until it reaches the "asynchronous" flow with the pollable channel.

                Thanks.

                Comment

                Working...
                X