Rengas
Rengas

Reputation: 733

How to use RestTemplate with application/octet-stream response type

I am using a ISBNdB to get info about the books.The reponse type is application/octet-stream. A sample json response I get looks as follows

{
"index_searched" : "isbn",
"data" : [
  {
     "publisher_id" : "john_wiley_sons_inc",
     "publisher_name" : "John Wiley & Sons, Inc",
     "title_latin" : "Java programming interviews exposed",
     "language" : "eng",
     "summary" : "",
     "physical_description_text" : "1 online resource (xvi, 368 pages) :",
     "author_data" : [
        {
           "name" : "Markham, Noel",
           "id" : "markham_noel"
        },
        {
           "id" : "greg_milette",
           "name" : "Greg Milette"
        }
     ],
     "title_long" : "Java programming interviews exposed",
     "urls_text" : "",
     "publisher_text" : "New York; John Wiley & Sons, Inc",
     "book_id" : "java_programming_interviews_exposed",
     "awards_text" : "; ",
     "subject_ids" : [],
     "isbn13" : "9781118722862",
     "lcc_number" : "",
     "title" : "Java programming interviews exposed",
     "isbn10" : "1118722868",
     "dewey_decimal" : "005.13/3",
     "edition_info" : "; ",
     "notes" : "\"Wrox programmer to programmer\"--Cover.; Acceso restringido a usuarios UCM = For UCM patrons only.",
     "marc_enc_level" : "",
     "dewey_normal" : "5.133"
  }
  ]
  }

I am using Jackson to convert this reponse. My Pojo looks as follows

@JsonIgnoreProperties(ignoreUnknown = true)

public class value {
    private  String index_searched;
    // Another pojo in different file with ignore properties
    private data[] dat;

    public value(){

    }
    public data[] getDat() {
        return dat;
    }

    public void setDat(data[] dat) {
        this.dat = dat;
    }
    public String getIndex_searched() {
        return index_searched;
    }
    public void setIndex_searched(String index_searched) {
        this.index_searched = index_searched;
    } 
   }

When I tried following

  value book = restTemplate.getForObject(FINAL_URL, value.class);

I get this exception

org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.rocketrenga.mylibrary.domain.value] and content type [application/octet-stream]

But I am able to map the response to String

String book = restTemplate.getForObject(FINAL_URL, String.class);
ObjectMapper mapper = new ObjectMapper();
value val = mapper.readValue(book, value.class);
System.out.println(val.getIndex_searched());

How to go about mapping the response directly POJO instead of String and converting back to POJO

Upvotes: 11

Views: 29569

Answers (3)

John Williams
John Williams

Reputation: 5430

Neither of these answers worked for me, albeit I did not try very long. This solution does not map to POJO directly but resolves the issue with a single additional line of code.

I got it working by changing

    ResponseEntity<AbInitioResponse> responseEntity = restTemplate.exchange(urlTemplate, HttpMethod.GET, requestEntity, AbInitioResponse.class, params);
    AbInitioResponse abInitioResponse = responseEntity.getBody();

into the following, ie getting the response as a byte[] and then explicitly serialising it to the desired class

    ResponseEntity<byte[]> responseEntity = restTemplate.exchange(urlTemplate, HttpMethod.GET, requestEntity, byte[].class, params);
    byte[] abInitioOctetResponse = responseEntity.getBody();
    AbInitioResponse abInitioResponse = objectMapper.readValue(abInitioOctetResponse, AbInitioResponse.class);

where objectMapper is an @Autowired com.fasterxml.jackson.databind.ObjectMapper

This answer was was helped by download-file-of-content-type-octet-stream-using-resttemplate.

Upvotes: 0

jny
jny

Reputation: 8067

You need to conifigure restTemplate with message converters. In your configuration do the following:

   @Bean
    public RestOperations restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();

        
        converter.setSupportedMediaTypes(
                Arrays.asList(new MediaType[]{MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM}));

        restTemplate.setMessageConverters(Arrays.asList(converter, new FormHttpMessageConverter()));
        return restTemplate;
    }

Upvotes: 19

Vity
Vity

Reputation: 362

I guess the better solution is to just add another converter, not to modify current ones:

@Bean
public RestTemplate restTemplate() {
    final RestTemplate restTemplate = new RestTemplate();
    restTemplate.getMessageConverters().add(jacksonSupportsMoreTypes());
    return restTemplate;
}


private HttpMessageConverter jacksonSupportsMoreTypes() {//eg. Gitlab returns JSON as plain text 
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setSupportedMediaTypes(Arrays.asList(MediaType.parseMediaType("text/plain;charset=utf-8"), MediaType.APPLICATION_OCTET_STREAM));
    return converter;
}

Upvotes: 8

Related Questions