mixiul__
mixiul__

Reputation: 395

Spring Boot - HttpMessageConverter JSONP (application/javascript)

I am calling a REST endpoint that returns basic JSON in the response body but the Content-Type response header is set to application/javascript.

Here is my standard RestTemplate bean:

 RestTemplateBuilder restBuilder = new RestTemplateBuilder();
    return restBuilder.setConnectTimeout(connectTimeout)
            .setReadTimeout(readTimeout)
            .build();

When I make getForObject requests with this template the default converters are unable to handle the response, I get the exception:

org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class MyResponseObj] and content type [application/javascript]

Is there some quick configuration I can add to my RestTemplate to handle this response and before the usual conversion?

My work around for this at the moment is just to convert the response to a String instead of my domain object and then manually create my object with an ObjectMapper but that feels a bit dirty.

Upvotes: 1

Views: 1742

Answers (2)

Andrea Zanotti
Andrea Zanotti

Reputation: 51

The best option I found is the following:

//Create a new converter class, that it's basically the same jackson, but it works with when header is javascript
public class JavaScriptMessageConverter extends AbstractJackson2HttpMessageConverter {

    //Add a new mediatype converter
    private JavaScriptMessageConverter() {
        super(Jackson2ObjectMapperBuilder.json().build(),new MediaType("application","javascript"));
    }
}

//Other class...

//Then add the converter to your rest template
restTemplate.getMessageConverters().add(new JavaScriptMessageConverter());
//Of course you can define the class also a bean and have it as singleton

I checked it against this free API that has exactly your problem: http://api.coindesk.com/v1/bpi/currentprice.json

16-11-2018 12:02:06.885 [http-nio-12000-exec-1] [process,,,] [] INFO  i.z.m.w.r.ArchRestLoggingInterceptor.logResponse - BitcoinService, Response with status code: 200, headers: {Content-Type=[application/javascript], Content-Length=[672], Access-Control-Allow-Origin=[*], Cache-Control=[max-age=15], Date=[Fri, 16 Nov 2018 11:02:06 GMT], Expires=[Fri, 16 Nov 2018 11:03:07 UTC], Server=[nginx/1.12.1], X-Powered-By=[Fat-Free Framework], X-Cache=[Miss from cloudfront, MISS from ced01squidp02.replynet.prv], X-Amz-Cf-Id=[v3NAF9Z0C5SiQrgLuAsxDgUQBP1-oLWUviHvS_9mOaFk7XrSAu7ZMQ==], X-Cache-Lookup=[MISS from ced01squidp02.replynet.prv:8080], Via=[1.1 1b96443527f684c809162d975cdd968f.cloudfront.net (CloudFront), 1.1 ced01squidp02.replynet.prv (squid/3.5.21)], Connection=[keep-alive]}, raw response: {"time":{"updated":"Nov 16, 2018 11:02:00 UTC","updatedISO":"2018-11-16T11:02:00+00:00","updateduk":"Nov 16, 2018 at 11:02 GMT"},"disclaimer":"This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchan...org","chartName":"Bitcoin","bpi":{"USD":{"code":"USD","symbol":"$","rate":"5,583.3925","description":"United States Dollar","rate_float":5583.3925},"GBP":{"code":"GBP","symbol":"£","rate":"4,363.6892","description":"British Pound Sterling","rate_float":4363.6892},"EUR":{"code":"EUR","symbol":"€","rate":"4,923.4020","description":"Euro","rate_float":4923.402}}}

Upvotes: 3

Erik Pearson
Erik Pearson

Reputation: 1383

What you should be able to do is customize the HttpMessageConverter to work with the application/javascript media type: https://dzone.com/articles/customizing

Something like this might work, but I did not test this:

    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
        jsonConverter.getSupportedMediaTypes().add(new MediaType("application/javascript"));

        return jsonConverter;
    }

Now the tutorial I adapted this from focuses on the RestController and not the RestTemplate. If it doesn't work, instead of using a bean, you can manually create the converter object and set the HttpMessageConverters on the RestTemplate object:

restTemplate.getMessageConverters().add(jsonConverter);

The key is to have the proper converter map to the right media type, in your case application/javascript.

Upvotes: 0

Related Questions