简体   繁体   中英

Content type 'application/json;charset=UTF-8' not supported with Spring boot controller call

I have a problem with sending my data from my angular form to my Spring boot controller: I'm getting this error: ** WARN 15020 --- [nio-8181-exec-2].c.j.MappingJackson2HttpMessageConverter: Failed to evaluate Jackson deserialization for type [[simple type, class com.biblio.fr.biblio.entite.BookDTO]]: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.biblio.fr.biblio.entite.BookDTODeserializer': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.biblio.fr.biblio.entite.BookDTODeserializer]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.biblio.fr.biblio.entite.BookDTODeserializer.()

WARN 15020 --- [nio-8181-exec-2].c.j.MappingJackson2HttpMessageConverter: Failed to evaluate Jackson deserialization for type [[simple type, class com.biblio.fr.biblio.entite.BookDTO]]: com.fasterxml.jackson.databind.JsonMappingException: Class com.biblio.fr.biblio.entite.BookDTODeserializer has no default (no arg) constructor

WARN 15020 --- [nio-8181-exec-2].wsmsDefaultHandlerExceptionResolver: Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported] **

This is my java code:

@RequestMapping(value = "/addBook", method = RequestMethod.POST, produces = "application/json")
    @ApiOperation(value = "Add a new Book in the Library", response = BookDTO.class)
    @ApiResponses(value = { @ApiResponse(code = 409, message = "Conflict: the book already exist"),
            @ApiResponse(code = 201, message = "Created: the book is successfully inserted"),
            @ApiResponse(code = 304, message = "Not Modified: the book is unsuccessfully inserted") })
    public ResponseEntity<BookDTO> createNewBook(@RequestBody BookDTO bookDTORequest) {
        // , UriComponentsBuilder uriComponentBuilder
        Book existingBook = bookService.findBookByIsbn(bookDTORequest.getIsbn());
        if (existingBook != null) {
            return new ResponseEntity<BookDTO>(HttpStatus.CONFLICT);
        }
        Book bookRequest = mapBookDTOToBook(bookDTORequest);
        Book book = bookService.saveBook(bookRequest);
        if (book != null && book.getId() != null) {
            BookDTO bookDTO = mapBookToBookDTO(book);
            return new ResponseEntity<BookDTO>(bookDTO, HttpStatus.CREATED);
        }
        return new ResponseEntity<BookDTO>(HttpStatus.NOT_MODIFIED);
 
    }
 
    private BookDTO mapBookToBookDTO(Book book) {
        ModelMapper mapper = new ModelMapper();
        BookDTO bookDTO = mapper.map(book, BookDTO.class);
        if (book.getCategory() != null) {
            bookDTO.setCategory(new CategoryDTO(book.getCategory().getCode(), book.getCategory().getLabel()));
        }
        return bookDTO;
    }
 
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonDeserialize(using = BookDTODeserializer.class)
@Data
@AllArgsConstructors
public class BookDTO implements Comparable<BookDTO> {
    @ApiModelProperty(value = "Book id")
    private Integer id;
 
    @ApiModelProperty(value = "Book title")
    private String title;
 
    @ApiModelProperty(value = "Book isbn")
    private String isbn;
 
    @ApiModelProperty(value = "Book release date by the editor")
    private LocalDate releaseDate;
 
    @ApiModelProperty(value = "Book register date in the library")
    private LocalDate registerDate;
 
    @ApiModelProperty(value = "Book total examplaries")
    private Integer totalExamplaries;
 
    @ApiModelProperty(value = "Book author")
    private String author;
 
    @ApiModelProperty(value = "Book category")
    private CategoryDTO category;
 
 
    @Override
    public int compareTo(BookDTO o) {
        return title.compareToIgnoreCase(o.getTitle());
    }
 
    public BookDTO() {
        super();
    }
 
}
 
@Entity
@Data
@AllArgsConstructors
public class Book {
    private static final long serialVersionUID = 425345L;
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
 
    private String title;
    private String author;
    private String publisher;
    private String publicationDate;
    private String language;
    private String category;
    private int numberOfPages;
    private String format;
    private String isbn;
    private double shippingWeight;
    private double listPrice;
    private double ourPrice;
    private boolean active = true;
 
    @Column(columnDefinition = "text")
    private String description;
    private int inStockNumber;
 
    @Transient
    private MultipartFile bookImage;
}
 
@Data
@AllArgsConstructors
@JsonDeserialize(using = CategoryDTODeserializer.class)
public class CategoryDTO implements Comparable<CategoryDTO> {
    public CategoryDTO() {
    }
 
    public CategoryDTO(String code, String label) {
        super();
        this.code = code;
        this.label = label;
    }
 
    @ApiModelProperty(value = "Category code")
    private String code;
 
    @ApiModelProperty(value = "Category label")
    private String label;
 
}
 
@Entity
@Table(name = "CATEGORY")
public class Category {
    public Category() {
    }
 
    public Category(String code, String label) {
        super();
        this.code = code;
        this.label = label;
    }
 
    private String code;
 
    private String label;
 
    @Id
    @Column(name = "CODE")
    public String getCode() {
        return code;
    }
 
    public void setCode(String code) {
        this.code = code;
    }
 
    @Column(name = "LABEL", nullable = false)
    public String getLabel() {
        return label;
    }
 
    public void setLabel(String label) {
        this.label = label;
    }
}
 
public class BookDTODeserializer extends StdDeserializer<BookDTO> {
 
    @Override
    public BookDTO deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        // TODO Auto-generated method stub
        JsonNode node = p.getCodec().readTree(p);
        Integer id = (Integer) ((IntNode) node.get("id")).numberValue();
        String title = node.get("title").asText();
        String isbn = node.get("isbn").asText();
        LocalDate releaseDate = LocalDate.parse(node.get("releaseDate").asText());
        LocalDate registerDate = LocalDate.parse(node.get("registerDate").asText());
        Integer totalExamplaries = (Integer) ((IntNode) node.get("totalExamplaries")).numberValue();
        String author = node.get("author").asText();
        String codeCategory = node.get("code").asText();
        String labelCategory = node.get("label").asText();
 
        return new BookDTO(id, title, isbn, releaseDate, registerDate, totalExamplaries, author,
                new CategoryDTO(codeCategory, labelCategory));
        // return null;
    }
 
    public BookDTODeserializer(Class<?> vc) {
        super(vc);
        // TODO Auto-generated constructor stub
    }
 
    public BookDTODeserializer(JavaType valueType) {
        super(valueType);
        // TODO Auto-generated constructor stub
    }
 
    public BookDTODeserializer(StdDeserializer<?> src) {
        super(src);
        // TODO Auto-generated constructor stub
    }
 
}
 
public class CategoryDTODeserializer extends StdDeserializer<CategoryDTO> {
 
    @Override
    public CategoryDTO deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        JsonNode node = p.getCodec().readTree(p);
        String codeCategory = node.get("code").asText();
        String labelCategory = node.get("label").asText();
        return new CategoryDTO(codeCategory, labelCategory);
    }
 
    public CategoryDTODeserializer(Class<?> vc) {
        super(vc);
        // TODO Auto-generated constructor stub
    }
 
    public CategoryDTODeserializer(JavaType valueType) {
        super(valueType);
        // TODO Auto-generated constructor stub
    }
 
    public CategoryDTODeserializer(StdDeserializer<?> src) {
        super(src);
        // TODO Auto-generated constructor stub
    }
 
}

and my angular code

saveBook(book: Book): Observable<Book>{
      let headers = new HttpHeaders();
      headers.append('content-type', 'application/json');
      headers.append('accept', 'application/json');
      return this.http.post<Book>(environment.apiUrl+'/rest/book/api/addBook', book, {headers: headers});
     }

Any idea please?

According to the WARN/Error message you are missing the following:

  1. No default constructor found; nested exception is java.lang.NoSuchMethodException: com.biblio.fr.biblio.entite.BookDTODeserializer

Declare BookDTODeserializer with @NoArgsConstructor

  1. Add consumes as JSON as well. @RequestMapping(value = "/addBook", method = RequestMethod.POST, produces = "application/json", consumes = "application/json")

I'm not getting the point why you need this "manual" deserializer considering you are already receiving the DTO in your request body as a JSON.

Content type 'application/json;charset=UTF-8' not supported with Spring boot controller call

is not the problem here

The problem is:

com.biblio.fr.biblio.entite.BookDTODeserializer has no default (no arg) constructor

public class BookDTODeserializer extends StdDeserializer<BookDTO> {
    public BookDTODeserializer() {
        super(BookDTO.class);
    }
    ...
}

Simply add @NoArgsConstructor does not help you, an error will show:

There is no default constructor available in 'com.fasterxml.jackson.databind.deser.std.StdDeserializer'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM