Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot - RestController Deserializing YAML Uploads?

How can I configure a Spring Boot RestController to accept YAML uploads?

The following results in a 415. I can see from debugging that the MappingJackson2HttpMessageConverter instances in my Spring context only support [application/json;charset=UTF-8, application/*+json;charset=UTF-8]. I can't be the only Spring Boot user trying to do this, and I'm surprised it doesn't just work - most things do in Spring Boot!

I've got the YAML dataformat in my POM:

    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-yaml</artifactId>
    </dependency>

My RestController has a method thus:

@RequestMapping(method=RequestMethod.POST, value="/", consumes="application/yaml")
public String upload(@RequestBody Declaration declaration) {
    //Do stuff
}

And my test:

@Test
public void triggersConvergence() throws Exception {
    ClassPathResource fixture = new ClassPathResource("declaration.yml");
    HttpHeaders requestHeaders = new HttpHeaders();
    requestHeaders.add("Content-Type", "application/yaml");
    requestHeaders.add("Accept", "application/json");

    URI uri = new URI("http://127.0.0.1:"+port);
    byte[] bytes = new byte[(int)fixture.contentLength()];
    fixture.getInputStream().read(bytes);
    RequestEntity<byte[]> postRequest = new RequestEntity<byte[]>(bytes, requestHeaders, HttpMethod.POST, uri);

    ResponseEntity<String> response = rest.exchange(postRequest, String.class);
    assertThat(response.getStatusCode(), is(HttpStatus.OK));
    assertThat(response.getBody(), is("Converged org my-lovely-org"));
}
like image 397
EngineerBetter_DJ Avatar asked May 19 '16 15:05

EngineerBetter_DJ


People also ask

What does @RestController do in Spring Boot?

Spring RestController annotation is used to create RESTful web services using Spring MVC. Spring RestController takes care of mapping request data to the defined request handler method. Once response body is generated from the handler method, it converts it to JSON or XML response.

Can we return view from RestController?

In @RestController, we can not return a view. @Controller annotation indicates that the class is a “controller” like a web controller.

Does Spring Boot prevent XML configuration?

Advantages of Spring Boot:It avoids writing lots of boilerplate Code, Annotations and XML Configuration. It is very easy to integrate Spring Boot Application with its Spring Ecosystem like Spring JDBC, Spring ORM, Spring Data, Spring Security etc.


2 Answers

While this functionality is not available in Spring it's easy to add using YAMLMapper it in 2 simple steps:

  1. Define your own HttpMessageConverter that supports Content-Type: application/x-yaml:

    final class YamlJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {
        YamlJackson2HttpMessageConverter() {
            super(new YAMLMapper(), MediaType.parseMediaType("application/x-yaml"));
        }
    }
    
  2. Register your converter:

    @Configuration
    public class YamlConfiguration extends WebMvcConfigurerAdapter {
        @Override
        public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
            converters.add(new YamlJackson2HttpMessageConverter());
        }
    }
    

Enjoy controller methods consuming and producing application/x-yaml from POJOs.

like image 72
miensol Avatar answered Oct 26 '22 23:10

miensol


Yes, you can do that.

Maven dependencies:

<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-yaml</artifactId>
  <version>2.5.4</version>
</dependency>

Controller method:

@RequestMapping(value = "/my/endpoint", method = RequestMethod.POST, consumes = "application/x-yaml")
@ResponseBody
public ResponseEntity<MyResponse> receiveYaml(@RequestBody final String yaml) {
    //unserialize yaml
}

Request example using curl:

curl -X POST --header "Content-Type: application/x-yaml" --header "Accept: */*" -d "invoice: 34843
date   : 2001-01-23
bill-to: &id001
    given  : Chris
    family : Dumars
    address:
        lines: |
            458 Walkman Dr.
            Suite #292
        city    : Royal Oak
        state   : MI
        postal  : 48046
ship-to: *id001
product:
    - sku         : BL394D
      quantity    : 4
      description : Basketball
      price       : 450.00
    - sku         : BL4438H
      quantity    : 1
      description : Super Hoop
      price       : 2392.00
tax  : 251.42
total: 4443.52
comments: >
    Late afternoon is best.
    Backup contact is Nancy
    Billsmer @ 338-4338."
like image 40
humungs Avatar answered Oct 26 '22 22:10

humungs