How to return plain text in spring controller?
Asked Answered
P

4

9

I want to return a simple plain text string as follows:

@RestController 
@RequestMapping("/test")
public class TestController {
    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/my", method = RequestMethod.GET, produces="text/plain")
    public String test() {
        return "OK";
    }

Problem: I also have a global ContentNegotiation filter as follows:

@Configuration
public class ContentNegotiationAdapter extends WebMvcConfigurerAdapter {
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(false)
                .favorParameter(true)
                .ignoreAcceptHeader(true)
                .useJaf(false)
                .defaultContentType(MediaType.APPLICATION_XML);
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.configureMessageConverters(converters);
    }
}

Result: whenever I access the spring controller, I'm getting the error:

Could not find acceptable representation

Question: how can I force the controller to return plain text, even though only XML was configured within content negotation (which I have to keep)?

Psychosexual answered 29/10, 2015 at 13:2 Comment(0)
P
4

First Way

@GetMapping(value = "/", produces = MediaType.TEXT_PLAIN_VALUE)
public @ResponseBody
String getResponseAsText() {

    return "Text Message Here";
}

Second Way

@GetMapping(value = "/")
public ResponseEntity<String> getResponseAsText() {

    var httpHeaders = new HttpHeaders();
    httpHeaders.setContentType(new MediaType("text", "plain", StandardCharsets.UTF_8));

    return new ResponseEntity<>("Text Message here", httpHeaders, HttpStatus.OK);
}
Protoactinium answered 29/9, 2022 at 13:8 Comment(4)
Those two methods aren't doing the same... Anything in @GetMapping (or @RequestMapping) is used, as the name implies, for mapping a request to a controller method. It does nothing to enforcing the content type being returned (produces actually accepts an array of values so you can have different methods for the same URL producing different content, but it isn't enforcing anything).Pastoralist
httpHeaders.setContentType(new MediaType("text", "plain", StandardCharsets.UTF_8)) is used when you want to manually set the content type for a specific HTTP response. @Produces(MediaType.TEXT_PLAIN) is an annotation that is used in the context of frameworks like JAX-RS or Spring Web's MVC to declare the media type that a resource method (e.g., a controller method) produces. Both approaches achieve the same result of setting the HTTP response content type to plain text. The choice between them depends on the specific requirements and the framework being used.Protoactinium
@Produces won't work with Spring MVC, so suggesting to do that won't work.Pastoralist
Indeed, you are correct. I elaborated on an alternative approach(Second Way) to accomplish content negotiation in Spring MVC. thanks ...Protoactinium
C
3

If you remove produces="text/plain" from the mapping, it returns plain text but the header is set to "application/xml". This is probably not desirable. I tested with the latest version of Spring Boot.

If you are using the version of Spring >= 4.1.2, you can try to use defaultContentTypeStrategy instead of defaultContentType, to set the correct content type in the header:

   configurer.favorPathExtension(false)
            .favorParameter(true)
            .ignoreAcceptHeader(true)
            .useJaf(false)
            .defaultContentTypeStrategy(new ContentNegotiationStrategy() {
                @Override
                public List<MediaType> resolveMediaTypes(NativeWebRequest nativeWebRequest) throws
                        HttpMediaTypeNotAcceptableException {
                    System.out.println("Description:"+nativeWebRequest.getDescription(false));
                    if (nativeWebRequest.getDescription(false).endsWith("/test/my")) {
                        return Collections.singletonList(MediaType.TEXT_PLAIN);
                    }
                    else {
                        return Collections.singletonList(MediaType.APPLICATION_XML);
                    }
                }
            })
            //.defaultContentType(MediaType.APPLICATION_XML)
;
Carrol answered 29/10, 2015 at 15:2 Comment(0)
A
-1

If I recall well, you can annotate the method with @ResponseBody and it will return plain text.

Check this

Annoying answered 29/10, 2015 at 13:6 Comment(0)
O
-2

You need to specify @ResponseBody annotation for your test method like:

public @ResponseBody String test(){}
Outspeak answered 29/10, 2015 at 13:36 Comment(2)
No, @RestController implies @ResponseBody.Psychosexual
Like @Psychosexual mentioned, using @RestController is the equivalent to writing @ResponseBody on all of the request mapping methods in your controller.Jamey

© 2022 - 2025 — McMap. All rights reserved.