9

I'm new to Spring Boot and I might be doing some silly mistake so Appologies in advance for such question. I'm trying to write POST API which accept following JSON :

{
  "id" : null,
  "a": 1.3,
  "b": "somestring",
   "mapJson" : 
    { 
        "monday" : "10:00-12:00/n14:00-18:00", 
        "tuesday" : "10:00-12:00/n14:00-18:00",
        "wednesday" : "10:00-12:00/n14:00-18:00",
        "thursday" : "10:00-12:00/n14:00-18:00",
        "friday" : "10:00-12:00/n14:00-18:00",
        "saturday" : "10:00-12:00/n14:00-18:00",
        "sunday" : "10:00-12:00/n14:00-18:00"
    },
    "list" : ["cc","paytm","debit"]
}

Consider following DTO class , AbcDTO :

package com.abb.dto;
import java.util.List;
import com.abb.entities.OpeningHrs;
import lombok.Data;

@SuppressWarnings("unused")
@Data
public class AbcDTO {

    private Long id;
    private Double a;
    private String b;
    private MapJson mapJson;
    private List<String> list;

}

OpeningHrs is Class for mapping Json Map structure,

package com.abb.entities;
import lombok.Data;
@SuppressWarnings("unused")
@Data
public class MapJson {

    private String monday;
    private String tuesday;
    private String wednesday;
    private String thursday;
    private String friday;
    private String saturday;
    private String sunday;

}

AbcController which have Post API :

package com.abb.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.abb.dto.AbcDTO;

@RestController
@EnableAutoConfiguration
@RequestMapping("/abc")
@GetMapping(value="/{id}",produces={MediaType.APPLICATION_JSON_VALUE})
public class HotelController {

   @RequestMapping(value = "/xyz", method = RequestMethod.POST)
    public @ResponseBody AbcDTO registerHotel(@RequestBody AbcDTO aaa) {

       System.out.println(aaa.toString());
       return aaa; 
   // I'm not able to map JSON into this Object
    }

}

Please find following Responce I'm getting is :

{
    "timestamp": 1509193409948,
    "status": 406,
    "error": "Not Acceptable",
    "exception": "org.springframework.web.HttpMediaTypeNotAcceptableException",
    "message": "Could not find acceptable representation",
    "path": "/abc/xyz"
}
Mayur
  • 576
  • 2
  • 5
  • 26

4 Answers4

7

The POST request doesn't work because Spring doesn't know what kind of data it's expecting. So you will need to tell spring that you're expecting APPLICATION_JSON_VALUE so it knows how to process. consumes= will, as you probably guessed, tell Spring what the incoming POST body context type.

@RequestMapping(value = "xyz", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody AbcDTO registerHotel(@RequestBody AbcDTO aaa) {

    System.out.println(aaa.toString());
    return aaa; 
    // I'm not able to map JSON into this Object
}

With PostMapping

@PostMapping(value = "xyz", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody AbcDTO registerHotel(@RequestBody AbcDTO aaa) {

   System.out.println(aaa.toString());
   return aaa; 
   // I'm not able to map JSON into this Object
}

As you can see I have also added something else called, produces= this will instruct Spring how to format the response body of that request. So frontend receives JSON formatted body, not just random text.

Max
  • 915
  • 10
  • 28
Prav
  • 2,785
  • 1
  • 21
  • 30
  • 2
    Thanks , I missed that consumes parameter. but after adding it, it still **not working** – Mayur Oct 28 '17 at 21:39
  • I've added `PostMapping`, could you see if that works? Could toy also try removing the `GetMapping` of the `Class` as well, that might be blocking the entire `Class` as the request is `Post`. – Prav Oct 28 '17 at 21:46
  • Assuming you've also removed the `GetMapping` from the Class as well. Has the error changed at all? And what tool are you using to send request? – Prav Oct 28 '17 at 21:55
  • Yes, I have removed GetMapping from the Class and I'm using ARC and PostMan Both to send request, while Content-Type is set as Application/Json and request JSON is in Body. – Mayur Oct 28 '17 at 21:59
  • @Mayur Could you try removing the `/` of `/xyz`, that is the only thing I can think of now. Other than, the only thing I can think of is the use of `Get` method on PostMan` instead `Post`; but I highly doubt that's the case. – Prav Oct 29 '17 at 10:49
3

In my case helped this in pom

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>
Anna OOkey
  • 91
  • 1
  • 4
  • 1
    In your case I guess that your service produce XML? That was also the case for me but I also had to configure a message converter: `@Override public void configureMessageConverters(final List> converters) { converters.add(new MappingJackson2XmlHttpMessageConverter()); }` – Andreas Sandberg Sep 17 '21 at 16:38
2

In my case the problem was that I didn't specify public getters in response class (analog of your AbcDTO class). So there were nothing to get to serialize and return to client.

200OK
  • 701
  • 5
  • 14
2

I just spent half a day on this error, and finally discovered that Spring's ContentNegotiationConfigurer by default favours the path extension if it's present. I had this particular mapping:

@PostMapping(value="/convert/{fileName:.+}",produces=MediaType.APPLICATION_JSON_VALUE)
public Map<String, String> convert(@PathVariable String fileName, @RequestBody String data) {
   // Do conversion
}

Now when I posted to this controller with a filename "outputfile.pdf", Spring would simply assume the response had to be PDF, completely ignoring the "produces" parameter for the PostMapping.

The problem can be fixed fixed with ContentNegotiationConfigurer.favorPathExtension(false). As of Spring web 5.3 this should be the default, but still isn't.

Gert-Jan
  • 752
  • 1
  • 8
  • 21