2

I use Spring-boot 2.0.1 with WebFlux as Rest server.

In me RestController I would like to automatically deserialize an object (Product). But I get a Jackson error as if ParameterNamesModule was not registered.

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of com.truc.Product (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator) at [Source: UNKNOWN; line: -1, column: -1] at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1451) at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1027) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1290) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1574) at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:965) at org.springframework.http.codec.json.AbstractJackson2Decoder.lambda$decodeInternal$0(AbstractJackson2Decoder.java:113) ... 287 common frames omitted

I have jackson-module-parameter-names in my pom

 <dependency>
     <groupId>com.fasterxml.jackson.module</groupId>
     <artifactId>jackson-module-parameter-names</artifactId>
 </dependency>

And this the route in RestController

@ResponseStatus(HttpStatus.CREATED)
@RequestMapping(method = RequestMethod.POST)
public Mono<Entity<Product>> postProduct(@RequestBody Product product) {
    return productService.insert(product);
}

If I try to deserialize manually it works :

@Autowired
private ObjectMapper objectMapper;
...
@ResponseStatus(HttpStatus.CREATED)
@RequestMapping(method = RequestMethod.POST)
public Mono<Entity<Product>> postProduct(ServerWebExchange exchange) {
    return exchange.getRequest().getBody()
            .last().flatMap(buffer -> {
        try {
            Product product = objectMapper.readValue(buffer.asInputStream(), Product.class);
            return productService.insert(product);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    });
}

This is my Product.class

package com.truc;

import java.time.LocalDate; import java.util.Optional;

public final class Product {
    public static final String PREFIX = "PT";

    public final String description;
    public final String shortDescription;
    public final String sku;
    public final float weight;
    public final LocalDate newSince;
    public final LocalDate newUntil;
    public final Status status;
    public final Visibility visibility;
    public final String metaKeywords;

    public Product(String description, String shortDescription, String sku, Float weight,
                   LocalDate newSince, LocalDate newUntil, Status status, Visibility visibility, String metaKeywords) {
        this.description = description;
        this.shortDescription = shortDescription;
        this.sku = sku;
        this.weight = Optional.ofNullable(weight).orElse(0f);
        this.newSince = newSince;
        this.newUntil = newUntil;
        this.status = status;
        this.visibility = visibility;
        this.metaKeywords = metaKeywords;
    }

    public enum Status {
        ACTIVE, INACTIVE
    }

    public enum Visibility {
        FULL, CATALOG, SEARCH, NONE
    } 
}

If I understand @JsonCreator is not required after jackson-databind 2.9, I use jackson 2.9.5

If I add @JsonCreator I get a new error 415 Unsupported Content-Type 'application/json' ...

I don't understand where I'm wrong ?

Thanks

Alan Hay
  • 22,665
  • 4
  • 56
  • 110
Marthym
  • 3,119
  • 2
  • 14
  • 22
  • looks like a no default constructor error. can you also share the product class? Basically you should either have a default constructor or a constructor with no input or tell the jackson how to construct the entity with @JsonCreator entity – cool Apr 14 '18 at 13:24
  • Sure, I complete the question with Product code. For `@JsonCreator` If I add it I get a new error 415 Unsupported Content-Type 'application/json' thanks for your response – Marthym Apr 14 '18 at 13:38

2 Answers2

2

You have to add default constructor in your RequestBody class which is ProductClass then it will work

T.Thakkar
  • 203
  • 2
  • 9
0

As explain here @EnableWebFlux deactivate all the webflux auto-configuration. And I use it in Configuration class without extend the class with WebFluxConfigurer.

When I remove @EnableWebFlux it work again, the ObjectMapper is configured as expected.

So it's ok Thanks

Marthym
  • 3,119
  • 2
  • 14
  • 22