0

I am facing a problem with Spring Integration. I am trying to execute a rest call via HttpRequestExecutingMessageHandler. My rest endpoint is accepting content-type 'application/json' only.

The problem is that the HttpRequestExecutingMessageHandler is posting with content-type 'text/plain;charset=UTF-8'.

@ServiceActivator(inputChannel = "transformRequestToJsonChannel", 
   outputChannel = "httpRequestOutChannel")
public Message<?> transformRequest(Message<DocumentConverterRequest> 
   message) 
{
  LOG.info("transforming document converter request to json: '{}'",         
  ObjectToJsonTransformer transformer = new ObjectToJsonTransformer();
  transformer.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
  Object payload = transformer.transform(message).getPayload();
  LOG.info("payload: '{}'", payload.toString());
  return MessageBuilder.withPayload(payload).build();
}

@Bean
@ServiceActivator(inputChannel = "httpRequestOutChannel")
public HttpRequestExecutingMessageHandler outbound() {
  HttpRequestExecutingMessageHandler handler = new 
  HttpRequestExecutingMessageHandler(documentConverterRestUrl);
  handler.setHttpMethod(HttpMethod.POST);
  handler.setErrorHandler(httpResponseErrorHandler);
  handler.setExpectedResponseType(String.class);
  handler.setCharset(Charset.defaultCharset().name());
  HeaderMapper<HttpHeaders> mapper = new DefaultHttpHeaderMapper();
  HttpHeaders httpHeaders = new HttpHeaders();
  httpHeaders.add(HttpHeaders.CONTENT_TYPE, 
    MediaType.APPLICATION_JSON_VALUE);
  mapper.toHeaders(httpHeaders);
  handler.setHeaderMapper(mapper);
  handler.setOutputChannel(httpResponseChannel());
  return handler;
}

How can i override the content-type?

Anton Styopin
  • 753
  • 4
  • 17
  • 35

2 Answers2

0

This piece of code does nothing:

  HeaderMapper<HttpHeaders> mapper = new DefaultHttpHeaderMapper();
  HttpHeaders httpHeaders = new HttpHeaders();
  httpHeaders.add(HttpHeaders.CONTENT_TYPE, 
    MediaType.APPLICATION_JSON_VALUE);
  mapper.toHeaders(httpHeaders);

That toHeaders() is called from the HttpRequestExecutingMessageHandler when we receive response. It really useless to use it explicitly in your code, especially in the bean definition phase and when you ignore a result.

You don't need to use an explicit HeaderMapper at all: a default one should be enough for you.

The ObjectToJsonTransformer really maps that setContentType() into a headers of the message it replies:

if (headers.containsKey(MessageHeaders.CONTENT_TYPE)) {
        // override, unless empty
        if (this.contentTypeExplicitlySet && StringUtils.hasLength(this.contentType)) {
            headers.put(MessageHeaders.CONTENT_TYPE, this.contentType);
        }
}
else if (StringUtils.hasLength(this.contentType)) {
        headers.put(MessageHeaders.CONTENT_TYPE, this.contentType);
}

So, there is a proper content type to map. By default HttpRequestExecutingMessageHandler uses:

/**
 * Factory method for creating a basic outbound mapper instance.
 * This will map all standard HTTP request headers when sending an HTTP request,
 * and it will map all standard HTTP response headers when receiving an HTTP response.
 * @return The default outbound mapper.
 */
public static DefaultHttpHeaderMapper outboundMapper() {

With an appropriate set of headers to map to HTTP request and from HTTP response.

The new DefaultHttpHeaderMapper() brings just an empty set of headers to map.

Please, raise an issue to improve JavaDocs and Reference Manual to note that default ctor of that class doesn't bring any headers to map.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • Thank you for your comment. I already made it work. Yes indeed the HeaderMapper was useless in my case. Also i did not need the ObjectToJsonTransformer, because the HttpRequestExecutingMessageHandler is doing it by himself, when giving a MappingJackson2HttpMessageConverter. The only thing i needed todo was to put the Content-Type into the message header before the message arrives the HttpRequestExecutingMessageHandler. I had to create a HttpMessageHandlerSpec which maps the message header Content-Type and voila. – Anton Styopin Sep 20 '19 at 09:08
0
@Bean
@ServiceActivator(inputChannel = "httpRequestOutChannel")
public HttpRequestExecutingMessageHandler outbound() {
  HttpRequestExecutingMessageHandler handler = Http.outboundGateway(documentConverterRestUrl)
        .httpMethod(HttpMethod.POST)
        .messageConverters(new MappingJackson2HttpMessageConverter())
        .mappedRequestHeaders("Content-Type")
        .get();

        handler.setOutputChannel(httpResponseChannel());
        return handler;
}

I removed my ObjectToJsonTransformer, because the messageConverters(new MappingJackson2HttpMessageConverter()) is doing the stuff.

Also i had to add the content-type to my message header: .setHeaderIfAbsent(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)

Anton Styopin
  • 753
  • 4
  • 17
  • 35