0

I have written spring cloud stream application listening to Kinesis streams

Message Flow across channel

Kinesis Input --> Transformer --> Router (route to error or actaul processor)

I am planning to write error handling across these channels. Currently I am explicitly catching the error and sending to different channels. Instead of catching and modifying the payload, I would like to implement generi exception handler

Binder

    public interface Binder {

      @Input(ITEM_KINESIS_INPUT)
      SubscribableChannel itemMessage();

    }

Configuration

    @Configuration
    @EnableIntegration
    public class IntegrationConfiguration {

      @Bean(name = DEFAULT_ITEM_LISTENER)
      public MessageChannel defaultItemChannel() {
        return new DirectChannel();
      }

      @Bean(name = DEFAULT_ERROR)
      public MessageChannel DEFAULT_ERROR() {
        return new DirectChannel();
      }

      @Bean
      @Transformer(inputChannel = ITEM_KINESIS_INPUT, outputChannel = ITEM_TRANSFORMER)
      public ItemTransformer itemTransformer() {
        return new ItemTransformer();
      }


      @ServiceActivator(inputChannel = ITEM_TRANSFORMER)
      @Bean
      public ItemMessageTypeRouter router() {
        return new ItemMessageTypeRouter();
      }

    // I tried this as well Not working
      @ServiceActivator(inputChannel = "errorChannel")
      @Bean
      public AbstractMessageHandler process() {
        return new AbstractMessageHandler() {
          @Override
          protected void handleMessageInternal(Message<?> message1) throws Exception {
            System.out.println("MessageHandler SA");
          }
        };

      }

    }

Transformer

    public class ItemTransformer extends AbstractTransformer {


      @Override
      public String getComponentType() {
        return "transformer";
      }



      @Override
      protected Object doTransform(Message<?> message) throws Exception {
        Object transformedPayload = null;
        try {
          //transform
        } catch (Exception e) {
          transformedPayload =
              new MessageTransformationException(message, "failed to transform message", e);
        }
        return MessageBuilder.withPayload(transformedPayload).copyHeaders(message.getHeaders()).build();
      }
    }

And in Router routing to different channel for error

public class ItemMessageTypeRouter extends AbstractMappingMessageRouter {


  @Override
  protected List<Object> getChannelKeys(Message<?> message) {
    return (message.getPayload() instanceof Throwable) ? Arrays.asList(DEFAULT_ERROR)
        : Arrays.asList(DEFAULT_ITEM_LISTENER)
  } 
}

Error Handling

@EnableBinding(Binder.class)
public class ErrorListener implements MessageListener<Message> {

  @Autowired
  private MessagesBackupRepository backupRepository;

  @Override
  @StreamListener(DEFAULT_ERROR)
  public void receiveMessage(Message message) {
    log.error("Error has been reported " + message);
  }

}

Can we implement generic exception handler all these channels.

Currently I only handle error in Transformer, but if there is any exception occurs in Router or later channels, then this also needs to handled manually

Any insight for better error handling

Patan
  • 17,073
  • 36
  • 124
  • 198
  • 1
    Why doesn’t this model work for you: https://docs.spring.io/spring-cloud-stream/docs/Elmhurst.M4/reference/htmlsingle/#binder-error-channels ? – Artem Bilan Feb 18 '18 at 13:34
  • @Artem Bilan. I did not understand exactly how to implement discrete error handling for each channel. In my question I have also stated that I tried with global error channel. It would be great if you can help on some example – Patan Feb 18 '18 at 23:45

0 Answers0