spring-amqp icon indicating copy to clipboard operation
spring-amqp copied to clipboard

Set replyPostProcessor default value from the message container factory

Open anassder opened this issue 3 years ago • 4 comments

Expected Behavior Use default value (bean name or class) for @RabbitListener annotation's attribute replyPostProcessor using message container factory like we do for AfterReceivePostProcessors and BeforeSendReplyPostProcessors.

Current Behavior We can set replyPostProcessor value only from @RabbitListener annotation. Example :

@RabbitListener(queues = "test.header", group = "testGroup", replyPostProcessor = "echoCustomHeader")
public String capitalizeWithHeader(String in) {
    return in.toUpperCase();
}

@Bean
public ReplyPostProcessor echoCustomHeader() {
    return (req, resp) -> {
        resp.getMessageProperties().setHeader("myHeader", req.getMessageProperties().getHeader("myHeader"));
        return resp;
    };
}

Context Currently we need to add a custom header (that we get from inbound request) to our responses, and we can't do that using AfterReceivePostProcessors or BeforeSendReplyPostProcessors because MessagePostProcessor.postProcessMessage give only the current message as parameter. The best solution for this probleme is to use replyPostProcessor, but we can't change all @RabbitListener annotations to add this attribute. That's why I suggest to add new method to the container factory to make changing default replyPostProcessor value possible. (like for setAfterReceivePostProcessors and setBeforeSendReplyPostProcessors)

anassder avatar Feb 25 '22 14:02 anassder

Agreed. This is really a valid requirement. We have a logic like this already:

JavaUtils.INSTANCE // NOSONAR
					.acceptIfNotNull(this.beforeSendReplyPostProcessors,
							messageListener::setBeforeSendReplyPostProcessors)

where the mentioned replyPostProcessor is really a property of the same messageListener. So, that BaseRabbitListenerContainerFactory can really have such a new replyPostProcessor option exposed.

Feel free to come back to us with a contribution: https://github.com/spring-projects/spring-amqp/blob/main/CONTRIBUTING.adoc

Thank you!

artembilan avatar Mar 01 '22 17:03 artembilan

It's actually this code that sets the RPP...

https://github.com/spring-projects/spring-amqp/blob/a3aedc67072bdfc01850dec7f87195cd8bf86381/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/BaseRabbitListenerContainerFactory.java#L124-L125

Not the setBeforeSendReplyPostProcessors.

In the meantime, you can use this...

@Bean
public ReplyPostProcessor echoCustomHeader(AbstractRabbitListenerContainerFactory<?> factory) {
	ReplyPostProcessor rpp = (req, resp) -> {
		resp.getMessageProperties().setHeader("myHeader", req.getMessageProperties().getHeader("myHeader"));
		return resp;
	};
	factory.setContainerCustomizer(container -> {
		MessagingMessageListenerAdapter listener = ((MessagingMessageListenerAdapter) container
				.getMessageListener());
		listener.setReplyPostProcessor(rpp);
	});
	return rpp;
}

garyrussell avatar Mar 01 '22 17:03 garyrussell

Yes, but it also could be done by the BaseRabbitListenerContainerFactory as a common place for such a property. The @RabbitListener one can override, of course.

artembilan avatar Mar 01 '22 17:03 artembilan

Original SO question: https://stackoverflow.com/questions/71149751/configure-spring-amqp-to-use-default-bean-for-rabblitlisteners-replypostproces/71159878#71159878

garyrussell avatar Mar 01 '22 17:03 garyrussell