TL;DR: This is a new feature (thanks to OP) available in Spring Integration >=5.5.0. You need to:
- Get the appropriate Spring Integration version
- Change your
MessagingGateway
so it returns a ResponseEntity
- Configure your integration flow to not extract the body and to expect a
ResponseEntity
- Create a new
HttpMessageConverter
that supports ResponseEntity
The GitHub issue/feature request that OP created, resulted in an actual feature being implemented in Spring Integration. It is now possible to receive ResponseEntity
objects. What Artem Bilan explained was correct prior to the implementation of the feature and still is correct if the flag extractResponseBody
is set to true
(default). If it is set to false
, then it is pretty easy to get a ResponseEntity
(now).
What You Need To Do
First get a new version (>=5.5.0) of Spring Integration in your POM.xml
or build.gradle
dependencies {
...
implementation "org.springframework.integration:spring-integration-http:5.5.2"
...
}
Now in my case I previously had a REST call that resulted in a String
. Now I want a ResponseEntity<String>
. So the MessagingGateway
I previously defined...
old
@MessagingGateway
public interface Client {
/**
* Makes call to (another) Server
*/
@Gateway(requestChannel = "requestChannel", replyChannel = "replyChannel")
String makeSomeCall(@Header("url") String url, @Payload SomePayload sp);
}
... becomes (only return value changed):
new
@MessagingGateway
public interface Client {
/**
* Makes call to (another) server
*/
@Gateway(requestChannel = "requestChannel", replyChannel = "replyChannel")
ResponseEntity<String> makeSomeCall(@Header("url") String url, @Payload SomePayload sp);
}
Now if we leave it this way, then it still won't work. We need to tell Spring, that the ResponseBody should not be extracted. We do this in the integration flow:
@Bean
MessageChannel replyChannel() {
return MessageChannels.direct("replyChannel").get();
}
@Bean
MessageChannel clientChannel() {
return MessageChannels.direct().get();
}
IntegrationFlow clientFlow() {
final SpelExpressionParser parser = new SpelExpressionParser();
return IntegrationFlows.from(clientChannel())
.handle(Http.outboundGateway(parser.parseExpression("headers.url"), restTemplate)
.charset("UTF-8")
.extractResponseBody(false) // <-- this is new w/ default being true!
.expectedResponseType(ResponseEntity.class)) // <-- this was String.class
.channel(clientReplyChannel())
.get();
}
If we leave it here, it will still not work. The program will not be able to find an appropriate HttpMessageConverter
. You need to write one on your own. It all depends on what the content of your ResponseEntity
is. Thankfully, you most likely don't need to write a whole HttpMessageConverter
on your own. You can simply extend the "approriate" one and tell it to accept ResponseEntity
. My new MessageConverter looks like this.
@Component
public class ResponseEntityHttpMessageConverter extends StringHttpMessageConverter {
public ResponseEntityHttpMessageConverter() {
}
@Override
public boolean supports(final Class<?> clazz) {
return ResponseEntity.class == clazz;
}
}
Spring Boot should be able to pick it up on its own. I believe there is plenty of material about this online in case you get stuck.
Hint: Just don't make the mistake to implement HttpMessageConverter<ResponseEntity>
. Spring will unwrap the ResponseEntity for the MessageConverter
itself. So the converter should only be for the content.