间歇性Jackson模型映射器参考链错误

时间:2018-12-21 16:31:58

标签: java spring spring-boot jackson

在使用Spring Boot Framework时,我遇到了Jackson的模型映射器的怪异问题。杰克逊有时似乎在从JSON有效负载映射到我的一个DTO时遇到问题。奇怪的是,只有当有问题的端点不是服务器启动时调用的第一个端点之一时,这种情况才会发生。这是错误:

2018-12-21 11:10:05.012 [http-nio-8080-exec-7] WARN  o.s.w.s.m.s.DefaultHandlerExceptionResolver.handleHttpMessageNotReadable(384) - Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON document: No _valueDeserializer assigned
 at [Source: java.io.PushbackInputStream@22361a02; line: 1, column: 208] (through reference chain: c.r.p.a.d.s.ServiceProviderSubscriptionDTO["advisor"]->c.r.p.a.d.AdvisorDTO["lastModifiedBy"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No _valueDeserializer assigned
 at [Source: java.io.PushbackInputStream@22361a02; line: 1, column: 208] (through reference chain: c.r.p.a.d.s.ServiceProviderSubscriptionDTO["advisor"]->c.r.p.a.d.AdvisorDTO["lastModifiedBy"])

以下是发生此错误时调用的端点。仅当我在以下端点之前调用几个端点时,才会发生此错误。如果在服务器启动后我首先调用此端点,则它将正确成功。

/**
 * POST /subscriptions/subscribe -> Create account subscription.
 *
 * @param serviceProviderSubscriptionDTO the subscription information
 * @return the created subscription object
 */
@RequestMapping(value = "/subscriptions/subscribe", method = RequestMethod.POST)
@Timed
public ResponseEntity<?> subscribe(@RequestBody ServiceProviderSubscriptionDTO serviceProviderSubscriptionDTO) {
    this.logger.error("Service Provider Subscription DTO:      " + ReflectionToStringBuilder.toString(serviceProviderSubscriptionDTO));
    try {
        SubscriptionDTO result = this.service.create(serviceProviderSubscriptionDTO);
        return ResponseEntity.ok().body(result);
    } catch (Exception ex) {
        ex.printStackTrace();
        this.logger.error(ex.getMessage());
    }
    return ResponseEntity.badRequest().body(new ErrorDTO("SUBSCRIPTION_CREATE_FAILED"));
} 

如果将控制器更改为仅接受通用映射,然后使用org.modelmapper.ModelMapper将其映射到ServiceProviderSubscriptionDTO,则无论何时调用端点,一切都可以正常工作。显然,这不是理想的解决方案,因为我失去了Spring Framework的RequestBody注释的所有好处。

/**
 * POST /subscriptions/subscribe -> Create account subscription.
 *
 * @param serviceProviderSubscriptionDTO the subscription information
 * @return the created subscription object
 */
@RequestMapping(value = "/subscriptions/subscribe", method = RequestMethod.POST)
@Timed
public ResponseEntity<?> subscribe(@RequestBody Map<String, Object> serviceProviderSubscriptionDTO) {
    this.logger.error("Service Provider Subscription DTO:      " + ReflectionToStringBuilder.toString(serviceProviderSubscriptionDTO));
    try {
        ServiceProviderSubscriptionDTO converted = this.modelMapper.map(serviceProviderSubscriptionDTO, ServiceProviderSubscriptionDTO.class);
        SubscriptionDTO result = this.service.create(converted);
        return ResponseEntity.ok().body(result);
    } catch (Exception ex) {
        ex.printStackTrace();
        this.logger.error(ex.getMessage());
    }
    return ResponseEntity.badRequest().body(new ErrorDTO("SUBSCRIPTION_CREATE_FAILED"));
} 

下面是DTO供参考。

服务提供商订阅DTO

@JsonIgnoreProperties(ignoreUnknown = true)
public class ServiceProviderSubscriptionDTO {
    /**
     * The payment source token.
     */
    protected String paymentSourceToken;
    /**
     * The Advisor reference.
     */
    @JsonIgnoreProperties("subscription")
    private AdvisorDTO advisor;

    public String getPaymentSourceToken() {
        return this.paymentSourceToken;
    }

    public void setPaymentSourceToken(String paymentSourceToken) {
        this.paymentSourceToken = paymentSourceToken;
    }

    public AdvisorDTO getAdvisor() {
        return this.advisor;
    }

    public void setAdvisor(AdvisorDTO advisor) {
        this.advisor = advisor;
    }
}

订阅DTO

@JsonIgnoreProperties(ignoreUnknown = true)
public class SubscriptionDTO {
    /**
     * Database identification number.
     */
    @Id
    protected Long id;
    /**
     * First and last name of the user who created the record in database.
     */
    protected String lastModifiedBy;
    /**
     * The Advisor reference.
     */
    @JsonIgnoreProperties({ "subscription", "lastModifiedBy" })
    private AdvisorDTO advisor;
    /**
     * The Service Provider Subscription.
     */
    private ServiceProviderSubscriptionDTO serviceProviderSubscription;

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getLastModifiedBy() {
        return this.lastModifiedBy;
    }

    public void setLastModifiedBy(String lastModifiedBy) {
        this.lastModifiedBy = lastModifiedBy;
    }

    public AdvisorDTO getAdvisor() {
        return this.advisor;
    }

    public void setAdvisor(AdvisorDTO advisor) {
        this.advisor = advisor;
    }

    public ServiceProviderSubscriptionDTO getServiceProviderSubscription() {
        return this.serviceProviderSubscription;
    }

    public void setServiceProviderSubscription(ServiceProviderSubscriptionDTO serviceProviderSubscription) {
        this.serviceProviderSubscription = serviceProviderSubscription;
    }
}

DTO顾问

@JsonIgnoreProperties(ignoreUnknown = true)
public class AdvisorDTO {
    /**
     * Database identification number.
     */
    @Id
    protected Long id;
    /**
     * First and last name of the user who created the record in database.
     */
    protected String lastModifiedBy;
    /**
     * The subscription.
     */
    private SubscriptionDTO subscription;

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getLastModifiedBy() {
        return this.lastModifiedBy;
    }

    public void setLastModifiedBy(String lastModifiedBy) {
        this.lastModifiedBy = lastModifiedBy;
    }

    public SubscriptionDTO getSubscription() {
        return this.subscription;
    }

    public void setSubscription(SubscriptionDTO subscription) {
        this.subscription = subscription;
    }
}

在我看来,这似乎是某种模型映射缓存问题,其中其他端点正在为模型映射器缓存某种与此对象不兼容的指令。当将这些有效载荷读入控制器时,我不知道杰克逊如何处理这些有效载荷,因此我只能推测。这些错误是在我的任何控制器代码运行之前引发的。

有人对我有任何见解,可能是什么原因引起的以及如何解决?

Spring Boot:1.5.3。发布

Spring Core:4.3.8。发布

Jackson Core:2.8.8

Java:8

0 个答案:

没有答案