Spring Data Rest: ошибка 500 при ожидании 4xx - PullRequest
0 голосов
/ 16 июня 2020

Учитывая следующие сущности, когда я «публикую» новую сущность «TrainerProfile» и пропускаю некоторые из параметров @NotNull в «Location», я получаю 500 вместе с трассировкой стека, упакованной в JSON вместо 400 и полезная информация о том, что пошло не так.

@Entity
public class TrainerProfile {
    ...

    @NotNull
    @OneToOne(cascade = CascadeType.ALL)
    private Location location;

}

@Entity
public class Location {

    @Id @GeneratedValue
    private Long id;

    @NotNull
    private String zipcode;

    @NotNull
    private String city;

    @NotNull
    private String country;

}

Когда я отправляю эти данные в API

{
  ...
  "location": {
    "zipcode": "10000"
  }
}

, я вижу следующие журналы:

javax.validation.ConstraintViolationException: Validation failed for classes [training.edit.provider.model.Location] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
    ConstraintViolationImpl{interpolatedMessage='must not be null', propertyPath=city, rootBeanClass=class training.edit.provider.model.Location, messageTemplate='{javax.validation.constraints.NotNull.message}'}
    ConstraintViolationImpl{interpolatedMessage='must not be null', propertyPath=country, rootBeanClass=class training.edit.provider.model.Location, messageTemplate='{javax.validation.constraints.NotNull.message}'}
]

Но клиент REST видит это:

< HTTP/1.1 500
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Access-Control-Allow-Origin: http://localhost:4200
< Access-Control-Allow-Credentials: true
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Tue, 16 Jun 2020 09:33:16 GMT
< Connection: close
<
{"timestamp":"2020-06-16T09:33:16.605+0000","status":500,"error":"Internal Server Error","message":"Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction","trace":"org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction\n\tat org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:543)\n...

Текст намного длиннее, но я избавляю вас от всего остального.

Я настроил проверку следующим образом:

@Configuration
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class RestConfiguration implements RepositoryRestConfigurer {

    private final @NonNull Validator validator;

    private final @NonNull UriToIdConverter converter;

    @Override
    public void configureConversionService(ConfigurableConversionService conversionService) {
        RepositoryRestConfigurer.super.configureConversionService(conversionService);
        conversionService.addConverter(converter);
    }

    @Override
    public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
       validatingListener.addValidator("afterCreate", validator);
       validatingListener.addValidator("beforeCreate", validator);
       validatingListener.addValidator("afterSave", validator);
       validatingListener.addValidator("beforeSave", validator);
    }

}

Как я могу получить правильное сообщение об ошибке в этом случае? Когда я публикую что-то, что не работает для «TrainerProfile», я получаю правильное сообщение и код ошибки, но не для вложенного объекта.

1 Ответ

1 голос
/ 02 июля 2020

Промежуточное решение

Каждый запрос Spring Data REST вызывает транзакцию. Внешнее исключение RollbackException дает вам ответ 500, даже если это исключение на самом деле происходит из-за ошибки вложенной проверки ConstraintViolationException. Рабочее, но не очень хорошее решение должно иметь ResponseEntityExceptionHandler для извлечения вложенного исключения, как в примере auth0 . Код здесь .

Предложение

Просто не используйте Spring Data REST там, где он не соответствует вашим требованиям.

, как сказал лидер Spring Data REST Оливер Дротбом в этом ответе .

RESTful API должен работать для агрегата . Агрегат - это концепция DDD. Агрегат не работает с реляционной базой данных. Попробуйте базу данных No- SQL, например Mon go DB. Отправной точкой для изучения DDD является выступление Оливера .

...