Search code examples
javaspring-integrationspring-integration-dsl

Spring Integration error is attaching completed payload


I have a listener to the JMS. Once I read the message then I convert to my custom object

public IntegrationFlow queueProcessorFlow() {
        return IntegrationFlows.from(Jms.inboundAdapter(jmsTemplate)

                        .destination("test_queue"),
                c -> c.poller(Pollers.fixedDelay(5000L)
                        .maxMessagesPerPoll(1)))

                //convert json to our custom object
                .transform(new JsonToQueueEventConverterTransformer(springBeanFactory))

                .transform(new CustomTransformer(springBeanFactory))


                .handle(o -> {


                }).get();
    }

The transformer

public class CustomerTransformer implements GenericTransformer<CustomPojo, CustomPojo> {


    private final QueueDataProcessorSpringBeanFactory factory;


    @Override
    public CustomPojo transform(CustomPojo CustomPojo) {
        try {

           //do something e.g. service call
           throw new Exception("This failed mate !! SOS");
        } catch (Exception e) {            

        //ISSUE here 
        //e contains the original payload in the stack trace 
            throw new RuntimeException(e);
        }
        return CustomPojo;

    }

Now when I throw my custom exception the stack trace contains everything. It even contains the payload. I am not interested in the payload in case of exception.

How do I update not to include payload?

** Update **

After changing as per answer I still see the issue

org.springframework.integration.transformer.MessageTransformationException: Failed to transform Message; nested exception is org.springframework.messaging.MessageHandlingException: nested exception is org.springframework.integration.transformer.MessageTransformationException: Error initiliazing the :; nested exception is CustomException Error lab lab lab  , failedMessage=GenericMessage [payload=

my error handler

 @Bean
    public IntegrationFlow errorHandlingFlow() {
        return IntegrationFlows.from("errorChannel")
                .handle(message -> {
                    try {

                        ErrorMessage e = (ErrorMessage) message;
                        if (e.getPayload() instanceof MessageTransformationException) {
                            String stackTrace = ExceptionUtils.getStackTrace(e.getPayload());
                            LOG.info("Exception trace {} ", stackTrace);

Solution

  • Not sure what is the business purpose to lose a payload in the stack trace, but you can achieve that throwing a MessageTransformationException instead of that RuntimeException.

    To avoid a message in stack trace with the mentioned payload, you need to use one of these constructors:

    public MessageTransformationException(String description, Throwable cause) {
        super(description, cause);
    }
    
    public MessageTransformationException(String description) {
        super(description);
    }
    

    Instead of those based on the Message<?>.

    This way a wrapping MessageTransformingHandler will do an appropriate logic:

    protected Object handleRequestMessage(Message<?> message) {
        try {
            return this.transformer.transform(message);
        }
        catch (Exception e) {
            if (e instanceof MessageTransformationException) {
                throw (MessageTransformationException) e;
            }
            throw new MessageTransformationException(message, "Failed to transform Message", e);
        }
    }
    

    UPDATE

    It turned out that MessageTransformationException is not enough since the AbstractMessageHandler checks for the MessageHandlingException for wrapping in the IntegrationUtils.wrapInHandlingExceptionIfNecessary(). Therefore I suggest to throw a MessageHandlingException from your code instead. And use this constructor with the null for the message arg:

    MessageHandlingException(Message<?> failedMessage, Throwable cause)