3

Here is my controller class:

@Controller
@RequestMapping("/actuator")
public class HealthController {

    @RequestMapping(value = "/metrics", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON)
    @ResponseBody
    public HealthModel getDump() throws JsonProcessingException {
        return new HealthModel();
        //return mapper.writeValueAsString(metrics.invoke());
    }

    @RequestMapping(value = "/metrics", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN)
    @ResponseBody
    public String getHealth() {
        return "HEALTHY";
    }
}

Model:

public class HealthModel {

    @JsonProperty
    private String status;
    @JsonProperty
    private int id;

    public HealthModel(){
        this.status="WARN";
        this.id=2;
    }

}

Note I have mapped /metrics to return json or plain-text depending on the Accept Header in the request

When I make request at

curl -v -H "Accept: application/json" http://localhost:8080/myapp/actuator/metrics

I get expected response in json {"status":"WARN","id":2}.

However, when I try

curl -v -H "Accept: text/plain" http://localhost:8080/myapp/actuator/metrics

I get HTTP/1.1 406 Not Acceptable.


EDIT

@EnableWebMvc
@Configuration
public class AppMvcConfig extends WebMvcConfigurerAdapter {

   @Resource(name = "appObjectMapper")
    private ObjectMapper appObjectMapper;

    @Resource(name = "modelObjectMapper")
    private ObjectMapper modelObjectMapper;

 @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
       
        final MappingJackson2HttpMessageConverter inputConverter = new MappingJackson2HttpMessageConverter();
        inputConverter.setObjectMapper(appObjectMapper);

        final MappingJackson2HttpMessageConverter outputConverter = new MappingJackson2HttpMessageConverter();
        outputConverter.setObjectMapper(modelObjectMapper);

        converters.add(new JacksonDualMapperConverter(appObjectMapper, modelObjectMapper));

        super.configureMessageConverters(converters);
    }

}
informatik01
  • 16,038
  • 10
  • 74
  • 104
brain storm
  • 30,124
  • 69
  • 225
  • 393
  • can you show your web configuration (EnableWebMvc configuration class, etc)? Did you configure specific messageconverters or content negotiation manager? – Brian Clozel Sep 04 '15 at 17:36
  • @BrianClozel: I do have EnableWebMVc class where I configured message converters. I have it above, but It is supposed to convert only Json I suppose.please let me know – brain storm Sep 04 '15 at 17:44

3 Answers3

8

Just in case anyone still gets the Type mismatch: cannot convert from MediaType to String[] error:

The solution is to use MediaType.APPLICATION_JSON_VALUE

instead of MediaType.APPLICATION_JSON

Regards

Camilo
  • 83
  • 1
  • 2
3

According to the documentation, @ResponseBody indicates that indicates that the return type should be written straight to the HTTP response body (and not placed in a Model, or interpreted as a view name). So annotation should be there. On the second look, your produces annotation does not seem to be correct. It should be produces = MediaType.TEXT_PLAIN_VALUE and not produces = MediaType.TEXT_PLAIN. I tried the following and it worked for me:

    @RequestMapping(value = "/metrics", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE)
    @ResponseBody
    public String getHealth() {
        return "HEALTHY";
    }

You also might have to add StringHttpMessageConverter.

jny
  • 8,007
  • 3
  • 37
  • 56
  • 2
    what is the MediaType are you using? is it `org.springframework.http.MediaType`; or `javax.ws.rs.core.MediaType;`. I am using the second one. when I try to use the first one, I get compile error `cannot convert from MediaType to String[]` – brain storm Sep 04 '15 at 18:08
  • I am using org.springframework.http.MediaType. As I mentioned, I am using MediaType.TEXT_PLAIN_VALUE which is a string – jny Sep 04 '15 at 18:10
  • I tried to use same as yours. I get compile error `Type mismatch: cannot convert from MediaType to String[]` – brain storm Sep 04 '15 at 18:13
  • @brainstorm, I got the "type mismatch" error too, when trying to use consumes = MediaType.TEXT_PLAIN. Switched to consumes = "text/plain" and it compiles ok. Don't know if that helps your situation, but thought it worth mentioning.... – Joshua Richardson Jan 04 '17 at 23:29
3

Since you're adding a custom MessageConverter configureMessageConverters, this turns off default converter registration (see JavaDoc).

So when content negotiation kicks in, you only have one message converter (the Jackson one) that only supports JSON media types and does not know how to handle text/plain.

You should add a StringHttpMessageConverter to the list in order to support text/plain.

converters.add(new StringHttpMessageConverter());
Brian Clozel
  • 56,583
  • 15
  • 167
  • 176
  • looks like I need to add dependency in pom for spring-messaging. After adding it in pom, I still do not see import option for StringMessageConverter. http://mvnrepository.com/artifact/org.springframework/spring-messaging/4.0.0.RELEASE – brain storm Sep 04 '15 at 18:31
  • pilot error! You need the HTTP variant of this StringHttpMessageConverter, included in spring-webmvc. No need to add spring-messaging unless you're using spring-websocket or messaging oriented features. Sorry about that! I just edited my answer to reflect this. – Brian Clozel Sep 04 '15 at 18:33
  • worked nicely. Thank you. if you worked with spring-boot-actuator, I have few questions posted here and you are now 10K congrats! – brain storm Sep 04 '15 at 18:41
  • Indeed 10K, thanks! I'll look at those questions, maybe I can help. – Brian Clozel Sep 04 '15 at 18:51