Search code examples
javakotlinspring-integrationspring-integration-dsl

Spring Integration null originalMessage in ErrorMessage


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.


Solution

  • 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.