Я борюсь с проектом Spring Boot 2.1.4, использующим Hibernate / Validator, Spring Data REST, Spring HATEOAS.
Я переопределяю LocalValidatorFactoryBean для поиска сообщений в определенной папке:
@Configuration
@EnableRetry
@EnableTransactionManagement
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
public class CustomConfiguration {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:/i18n/messages");
// messageSource.setDefaultEncoding("UTF-8");
// set to true only for debugging
messageSource.setUseCodeAsDefaultMessage(false);
messageSource.setCacheSeconds((int) TimeUnit.HOURS.toSeconds(1));
messageSource.setFallbackToSystemLocale(false);
return messageSource;
}
@Bean
public MessageSourceAccessor messageSourceAccessor() {
return new MessageSourceAccessor(messageSource());
}
/**
* Enable Spring bean validation https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation
*
* @return
*/
@Bean
public LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
factoryBean.setValidationMessageSource(messageSource());
return factoryBean;
}
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
methodValidationPostProcessor.setValidator(validator());
return methodValidationPostProcessor;
}
Я также позаботился о том, чтобы переопределить getValidator ():
@Configuration
@EnableHypermediaSupport(type = {HypermediaType.HAL})
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private LocalValidatorFactoryBean validator;
@Override
public Validator getValidator() {
return validator;
}
Я прочитал много обсуждений по этой проблеме, например, https://github.com/spring-projects/spring-boot/issues/3071 и связанных тем.
Iдобавлен этот пользовательский Совет:
/**
* Workaround class for making JSR-303 annotation validation work for controller method parameters. Check the issue
* <a href="https://jira.spring.io/browse/DATAREST-593">DATAREST-593</a>
*/
@ControllerAdvice
public class RequestBodyValidationProcessor extends RequestBodyAdviceAdapter {
@Autowired
private LocalValidatorFactoryBean validator;
@Override
public boolean supports(final MethodParameter methodParameter, final Type targetType,
final Class<? extends HttpMessageConverter<?>> converterType) {
final Annotation[] parameterAnnotations = methodParameter.getParameterAnnotations();
for (final Annotation annotation : parameterAnnotations) {
if (annotation.annotationType().equals(Valid.class)) {
return true;
}
}
return false;
}
@Override
public Object afterBodyRead(final Object body, final HttpInputMessage inputMessage, final MethodParameter parameter,
final Type targetType, final Class<? extends HttpMessageConverter<?>> converterType) {
final Object obj = super.afterBodyRead(body, inputMessage, parameter, targetType, converterType);
//TODO Il messaggio come ad esempio {eyeexam.pupillarydistance.missing} non viene interpolato tramite il file di properties
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(obj);
if (!constraintViolations.isEmpty()) {
throw new ConstraintViolationException(constraintViolations);
}
return obj;
}
}
Я испытываю пропущенное разрешение сообщения при вызове конечной точки контроллера покоя:
@RepositoryRestController
@PreAuthorize("isAuthenticated()")
public class EyeExamController {
@PostMapping(path = "/eyeExams/saveWithNote")
public ResponseEntity<?> save(@Valid @RequestBody EyeExamNote eyeExamNote, Locale locale,
PersistentEntityResourceAssembler resourceAssembler) {
return new ResponseEntity<Resource<?>>(resourceAssembler.toResource(eyeExamService.save(eyeExamNote)), HttpStatus.OK);
}
Я ожидаю, что результат проверки ScriptAsserts моего компонентаразрешено правильно:
@ScriptAssert(lang = "javascript", script = "(_.pupillaryDistanceIntermediate2Tot != null && _.pupillaryDistanceFarTot != null) ? (_.pupillaryDistanceIntermediate2Tot < _.pupillaryDistanceFarTot) :true", alias = "_", reportOn = "pupillaryDistanceIntermediate2Tot", message = "{eyeexam.pupillarydistance.intermediate.lower}"),
Вместо этого, когда я вызываю конечную точку, я получаю строку {eyeexam.pupillarydistance.intermediate.lower}
как интерполированное сообщение вместо моего текста (он находится в файле messages.properties в папке i18n согласно моему определению).
Кто-то предложил переместить ключи проверки в ValidationMessages.properties
, но это не работает для меня.Я делаю что-то неправильно?Любая подсказка приветствуется.