Quiero consumir un servicio RESTful que devuelva el tipo de contenido de text/javascript .
Dado que no hay OOTB HttpMessageConverter que pueda hacer esto en Spring Boot, quiero registrar un convertidor personalizado.
Una forma que encontré para hacer esto es personalizar el RestTemplate modificando MappingJackson2HttpMessageConverter :
@Component public class CustomRestTemplateProvider { public RestTemplate getCustomRestTemplate(MediaType mediaType) { MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(); jacksonConverter.setSupportedMediaTypes(Collections.singletonList(mediaType)); List<HttpMessageConverter<?>> converters = new ArrayList<>(); converters.add(jacksonConverter); return new RestTemplate(converters); } } Luego, en mi servicio, simplemente llame a getCustomRestTemplate(new MediaType("text", "javascript")
La solución anterior funciona bien, pero también traté de crear un nuevo convertidor que maneje este tipo de medio, de acuerdo con la documentación de Spring Boot (27.1.2) :
Así que creé un nuevo convertidor:
@Component public class TextJavascriptMessageConverter extends AbstractJackson2HttpMessageConverter { public TextJavascriptMessageConverter(ObjectMapper objectMapper) { super(objectMapper); setTextJavascriptAsSupportedMediaType(); } private void setTextJavascriptAsSupportedMediaType() { List<MediaType> supportedMediaTypes = new ArrayList<>(); supportedMediaTypes.add(new MediaType("text", "javascript")); setSupportedMediaTypes(supportedMediaTypes); } }Luego traté de registrarlo como en la documentación:
@Configuration public class ApplicationConfiguration { @Bean public HttpMessageConverters customConverters() { HttpMessageConverter<Object> converter = new TextJavascriptMessageConverter(new ObjectMapper()); return new HttpMessageConverters(Collections.singletonList(converter)); } } Aún así, recibo un mensaje que dice Could not extract response: no suitable HttpMessageConverter found for response type [class example.MyResponsee] and content type [text/javascript]
Incluso traté de extender MappingJackson2HttpMessageConverter , pero tampoco funcionó. ¿Qué me estoy perdiendo? Además, ¿es una buena práctica crear un nuevo convertidor para esto, o es aceptable modificar uno existente (como se muestra en el primer ejemplo)?
La documentación es un poco confusa, pero debería poder registrar su bean HttpMessageConverter y se agregará de manera adecuada.
Cualquier bean HttpMessageConverter que esté presente en el contexto se agregará a la lista de convertidores
Dado que ya ha registrado TextJavascriptMessageConverter como un bean (a través de @Component), debería poder autoconectar HttpMessageConverters para acceder a todos los convertidores.
Aunque preferiblemente podría autoconectar un RestTemplateBuilder que maneja la configuración de restTemplate para usted (incluidos los convertidores).
Ejemplo:
@SpringBootApplication public class DemoApplication { @Component public static class TextJavascriptConverter extends AbstractJackson2HttpMessageConverter { public TextJavascriptConverter() { //can use overloaded constructor to set supported MediaType super(new ObjectMapper(), new MediaType("text", "javascript")); } } @Bean public ApplicationRunner demoRunner(RestTemplateBuilder builder, TextJavascriptConverter javascriptConverter) { return args -> { //can autowire RestTemplateBuilder for sensible defaults (including converters) RestTemplate restTemplate = builder.build(); //confirm your converter is there if (restTemplate.getMessageConverters().contains(javascriptConverter)) { System.out.println("My custom HttpMessageConverter was registered!"); } }; } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }Además, ¿es una buena práctica crear un nuevo convertidor para esto, o es aceptable modificar uno existente (como se muestra en el primer ejemplo)?
Probablemente sea mejor que cree su propio convertidor; de lo contrario, corre el riesgo de dejar de admitir los tipos de medios originales.
Creo que debería usar otro constructor para designar explícitamente el tipo de medio.
protected AbstractJackson2HttpMessageConverter(ObjectMapper objectMapper) { init(objectMapper); } protected AbstractJackson2HttpMessageConverter(ObjectMapper objectMapper, MediaType supportedMediaType) { super(supportedMediaType); init(objectMapper); } protected AbstractJackson2HttpMessageConverter(ObjectMapper objectMapper, MediaType... supportedMediaTypes) { super(supportedMediaTypes); init(objectMapper); }Debería poder definir un nuevo bean MappingJackson2HttpMessageConverter , que Boot seleccionará y cargará de forma predeterminada.
@Bean public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){ MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(); jacksonConverter.setSupportedMediaTypes (Collections.singletonList(mediaType)); return jacksonConverter; }