При использовании Spring Boot Framework я столкнулся со странной проблемой с картографом модели Джексона.Кажется, что у Джексона иногда возникают проблемы с отображением данных 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, все работает нормально, независимо от того, когда я вызываю конечную точку.Очевидно, что это не идеальное решение, поскольку я теряю все преимущества аннотации RequestBody в Spring Framework.
/**
* 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;
}
}
Advisor 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.RELEASE
Spring Core: 4.3.8.RELEASE
Jackson Core: 2.8.8
Java: 8