0

We are using Spring-Integration in our project. I am experiencing a weird problem with http:outbound-gateway. We need to pass the following headers for executing a rest service. 1)Accept=application/vnd.dsths.services-v1+xml

2)Content-Type=application/xml

The weird part is that the response returned is not always unique, In dev environment, xml response(Content-Type=application/vnd.dsths.services-v1+xml) is returned while in client environment, json response(Content-Type=application/vnd.dsths.services-v1+json) is returned. I have verified the log files by turning on DEBUG and found that the org.springframework.web.client.RestTemplate is Setting request Accept header to [text/plain, application/json, application/*+json, */` * ].

2017-07-10 16:17:11,563 DEBUG [org.springframework.web.client.RestTemplate] (ajp-/10.226.55.163:8009-1) Setting request Accept header to [text/plain, application/json, application/*+json, */*]

I could able to overcome this problem by overriding the value of accept=*/* to accept=application/vnd.dsths.services-v1+xml in the client environment(Please note that this header is not the actual "Accept" header).

The question here is why http:outbound-gateway is behaving oddly and manipulating the header value? Why the Spring Integration is not able to identify the difference between the headers and "accept" and "Accept"? Is my fix correct one?

Ashok.N
  • 1,327
  • 9
  • 29
  • 64

1 Answers1

0

Not sure what is the question about difference, but according RFC-2616 HTTP headers are case-insensitive: Are HTTP headers case-sensitive?.

And DefaultHttpHeaderMapper follow that recommendations:

private void setHttpHeader(HttpHeaders target, String name, Object value) {
    if (ACCEPT.equalsIgnoreCase(name)) {
        if (value instanceof Collection<?>) {

What you show is the part of Spring MVC already, far away from Spring Integration. See RestTemplate code:

public void doWithRequest(ClientHttpRequest request) throws IOException {
        if (this.responseType != null) {
            Class<?> responseClass = null;
            if (this.responseType instanceof Class) {
                responseClass = (Class<?>) this.responseType;
            }
            List<MediaType> allSupportedMediaTypes = new ArrayList<>();
            for (HttpMessageConverter<?> converter : getMessageConverters()) {
                if (responseClass != null) {
                    if (converter.canRead(responseClass, null)) {
                        allSupportedMediaTypes.addAll(getSupportedMediaTypes(converter));
                    }
                }
                else if (converter instanceof GenericHttpMessageConverter) {
                    GenericHttpMessageConverter<?> genericConverter = (GenericHttpMessageConverter<?>) converter;
                    if (genericConverter.canRead(this.responseType, null, null)) {
                        allSupportedMediaTypes.addAll(getSupportedMediaTypes(converter));
                    }
                }
            }
            if (!allSupportedMediaTypes.isEmpty()) {
                MediaType.sortBySpecificity(allSupportedMediaTypes);
                if (logger.isDebugEnabled()) {
                    logger.debug("Setting request Accept header to " + allSupportedMediaTypes);
                }
                request.getHeaders().setAccept(allSupportedMediaTypes);
            }
        }
    }

As you see the logic is based on the provided HttpMessageConverter and it is, honestly, is correct. The Accept header is exactly what the client can handle from the server.

If you don't like such a behavior and you are sure in your client, you can inject RestTemplate to the http:outbound-gateway but already with only desired HttpMessageConverter.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • Okay. Thanks for the explanation. I am thinking that MessageBuilder.removeHeader("accept") should work so that the correct header `Accept` can be recognized by Spring framework. Does that make sense or do you foresee any other problems? – Ashok.N Jul 12 '17 at 10:20
  • ??? You fully don't understand me. Do I talk about removing some header? I explain you how there are those values for the `Accept` and how to overcome that. Your `Accept` header from the Spring Integration does not have any effect and it is overridden in the `RestTemplate` anyway. – Artem Bilan Jul 12 '17 at 14:19