Java 8 Необязательный <?> Модуль проверки подлинности в Spring

В моем проекте Spring Boot при использовании следующих правил проверки в моем DTO

@Length(max = 70)
@UnwrapValidatedValue
private Optional<String> vendorName;

Я получаю следующее исключение

javax.validation.ValidationException: HV000182: No validation value unwrapper is registered for type java.util.Optional<java.lang.String>

Я не могу найти нигде, как зарегистрировать пользовательский флажок проверки достоверности в Spring

Ответ 1

Вы должны зарегистрировать ValidatedValueUnwrapper в валидаторе.

Валидатор можно настроить с помощью LocalValidatorFactoryBean:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:util="http://www.springframework.org/schema/util"
  xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">

  <bean name="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="validationPropertyMap">
      <util:map>
        <entry key="hibernate.validator.validated_value_handlers" 
               value="com.mycompany.validator.OptionalValidatedValueUnwrapper"/>
      </util:map>
    </property>
  </bean>
</beans>

или в java:

@Bean
public LocalValidatorFactoryBean validator() {
    LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
    validator.getValidationPropertyMap().put("hibernate.validator.validated_value_handlers",
            "com.mycompany.validator.OptionalValidatedValueUnwrapper");
    return validator;
}

Вы можете найти правильную ValidatedValueUnwrapper реализацию в структуре dropwizard (на основе Optional от guava).

public class OptionalValidatedValueUnwrapper extends ValidatedValueUnwrapper<Optional<?>> {

    private final TypeResolver resolver = new TypeResolver();

    @Override
    public Object handleValidatedValue(final Optional<?> optional) {
        return optional.orNull();
    }

    @Override
    public Type getValidatedValueType(final Type type) {
        ResolvedType resolvedType = resolver.resolve(type);
        return resolvedType.typeParametersFor(Optional.class).get(0).getErasedType();
    }
}