0

We are really confused with error handling in Spring Integration. We are using Boot 2.0.2 and Kotlin.

Within a @Transformer we throw an Exception X.

Also, within a Java DSL flow definition, we throw the same exception X

Channels

@Bean(TO_BE_PROCESSED_CHANNEL)
fun toBeProcessed() = PublishSubscribeChannel(defaultExecutor())

Flow

@Configuration
class VideoDescriptorPersistSubflow(
    val videoRepository: JdbcVideoRepository,
    val ingestRecordRepository: CustomIngestRecordRepository
) {

@Bean
fun videoDescriptorPersistFlow(
        toBeProcessed: MessageChannel,
        processedVideos: MessageChannel
) =
        IntegrationFlows.from(toBeProcessed)
                .filter { message: Message<*> -> message.ingestRecordId() != null }
                .handle { videoDescriptor: VideoDescriptor, _ -> validateVideoDescriptor(videoDescriptor) }
                .handle { videoDescriptor: VideoDescriptor, _ -> videoRepository.persist(videoDescriptor) }
                .channel(processedVideos)
                .get()

fun validateVideoDescriptor(videoDescriptor: VideoDescriptor): VideoDescriptor {
    val errors = VideoDescriptorValidator().validate(videoDescriptor)
    if (errors.isNotEmpty()) {
        throw VideoMetadataValidationException(errors)
    }

    return videoDescriptor
}

Later in the errorChannel we filter out X and do some stuff. At that point we need the failed message.

For the exception thrown by the @Transformer the originalMessage is there.

For the one thrown from the java DSL subflow, the originalMessage is null.

We did some digging and realised, the former is wrapped in MessagingExceptionWrapper whereas the later is wrapped in a MessageHandlingException which does not contain a reference to the original message.

Could someone please help us understand under what circumstances Spring Integration wraps using what exceptions? Docs do not say much here, or we couldn't find anything relevant.

UPDATE: CHANGING FROM PUBSUB TO QUEUE CHANNEL MAKES IT WORK...

UPDATE 2: Following Gary's advide we are now using payload.failed message, which works just fine. There is something dodgy though with originalMessage in ErrorMessage.

José Carlos
  • 414
  • 2
  • 8
  • You need to show the configuration in both cases and what precedes the integration flow DSL. – Gary Russell May 17 '18 at 17:57
  • Thanks @GaryRussell I was really hoping you were around. Changing from aChannel from a PubSub with an executor to a Queue makes it work... Let me add more config here (although, that's pretty much it). – José Carlos May 17 '18 at 17:58

1 Answers1

1

payload.failedMessage is the message at the time of failure. ErrorMessage.originalMessage is the message at the start of the flow. It is not populated in all cases.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • But org.springframework.messaging.support.ErrorMessage only contains originalMessage. We cast to that after picking up the message from the errorQueue... – José Carlos May 17 '18 at 18:01
  • Generally the `ErrorMessage.payload.failedMessage` is most relevant. `ErrorMessage.originalMessage` (the message where the exception is caught) is added in many cases, when it is available. If you show your configuration, we can determine if it's a bug or not. – Gary Russell May 17 '18 at 18:04