Hibernate Validation不会在Spring Boot应用程序中查找错误消息

时间:2018-12-02 06:56:04

标签: spring hibernate spring-boot hibernate-validator

这是我的Spring启动项目。Project Set up

我有一个标准的Spring Boot JPA堆栈,我在其中尝试验证实例变量的状态。我的豆子如下:

配置

@Component
public class ConfigurationHelper {

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasenames("messages");
        messageSource.setUseCodeAsDefaultMessage(true);
        messageSource.setCacheSeconds(5);
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }

    @Bean
    public Validator validator() {
        LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
        factoryBean.setValidationMessageSource(this.messageSource());
        return factoryBean;
    }
}

模型类

@Table(name = "user_station", indexes = {
    @Index(columnList = "station_id", name = "station_index_station_id"),
    @Index(columnList = "station_name", name="station_index_name"),
    @Index(columnList = "hd_enabled", name = "station_index_hd_enabled")
})
@Entity
@EqualsAndHashCode(exclude = {"createdTimeStamp", "updatedTimestamp"}, callSuper = true)
@ToString(exclude = {"createdTimeStamp", "updatedTimestamp"}, callSuper = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Station extends IError {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    @JsonIgnore
    private Long id;

    // Represents a station id for the user.
    @Column(name="station_id", nullable = false, unique = true)
    @NotEmpty(message = "{station.id.empty}")
    @Pattern(regexp = "^K|W[A-Za-z0-9\\-].*$", message = "{station.id.name.not.valid}")
    private String stationId;

    @Column(name="station_name", nullable = false)
    @JsonProperty("name")
    @NotEmpty(message = "{station.name.empty}")
    private String stationName;

    @Column(name = "hd_enabled")
    private Boolean hdEnabled;

    @Column(name="call_sign", nullable = false)
    @NotEmpty(message = "{station.call.sign.empty}")
    private String callSign;

    @Column(name="user_created_timestamp")
    @JsonIgnore
    private LocalDateTime createdTimeStamp;

    @Column(name="user_modified_timestamp")
    @JsonIgnore
    private LocalDateTime updatedTimestamp;

    /**
     * Initialises the timestamps prior to update or insertions.
     *
     * <p>The implementation ensures that time stamps would always reflect the time when entities
     * were persisted or updated.
     */
    @PrePersist
    @PreUpdate
    public void setTimestamps() {
        LocalDateTime utcNow = LocalDateTime.now(ZoneOffset.UTC);
        if (this.createdTimeStamp == null) {
            this.createdTimeStamp = utcNow;
        }
        this.updatedTimestamp = utcNow;
        if (this.hdEnabled == null) {
            this.hdEnabled = Boolean.FALSE;
        }
    }

    // Getters, Setters, Equals and HashCode functions.
}

单元测试

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes= {App.class})
public class StationTest {

    @Autowired
    private Validator validator;

    private Station station;

    @Before
    public void setUp() throws Exception {
        this.station = new Station();
    }


    @Test
    public void testValidator_allNulls() {
        Set<ConstraintViolation<Station>> constraintViolations =
            this.validator.validate(this.station);
        MatcherAssert.assertThat(constraintViolations.isEmpty(), Is.is(false));
        for (ConstraintViolation<Station> constraintViolation : constraintViolations) {
            System.out.println(constraintViolation.getMessage());
        }
    }
}

这是我的输出

. . . . Rest of the stack trace omitted . . . .

     2018-12-01 23:30:38.532  INFO 21297 --- [           main] com.iheartmedia.model.StationTest        : Starting StationTest on Kartiks-MacBook-Pro-2.local with PID 21297 (started by krishnanand in /Users/krishnanand/projects/iheartmedia)
2018-12-01 23:30:38.533 DEBUG 21297 --- [           main] com.iheartmedia.model.StationTest        : Running with Spring Boot v2.0.5.RELEASE, Spring v5.0.9.RELEASE
2018-12-01 23:30:38.539  INFO 21297 --- [           main] com.iheartmedia.model.StationTest        : No active profile set, falling back to default profiles: default
2018-12-01 23:30:38.596  INFO 21297 --- [           main] o.s.w.c.s.GenericWebApplicationContext   : Refreshing org.springframework.web.context.support.GenericWebApplicationContext@6892b3b6: startup date [Sat Dec 01 23:30:38 PST 2018]; root of context hierarchy
2018-12-01 23:30:39.565  INFO 21297 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$b7d31eab] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-12-01 23:30:39.730  INFO 21297 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2018-12-01 23:30:39.871  INFO 21297 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2018-12-01 23:30:39.903  INFO 21297 --- [           main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
2018-12-01 23:30:39.917  INFO 21297 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [
    name: default
    ...]
2018-12-01 23:30:40.030  INFO 21297 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate Core {5.2.17.Final}
2018-12-01 23:30:40.031  INFO 21297 --- [           main] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found
2018-12-01 23:30:40.066  INFO 21297 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
2018-12-01 23:30:40.196  INFO 21297 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2018-12-01 23:30:40.652  INFO 21297 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2018-12-01 23:30:40.985  INFO 21297 --- [           main] o.h.h.i.QueryTranslatorFactoryInitiator  : HHH000397: Using ASTQueryTranslatorFactory
2018-12-01 23:30:41.351  INFO 21297 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-12-01 23:30:41.586  INFO 21297 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.web.context.support.GenericWebApplicationContext@6892b3b6: startup date [Sat Dec 01 23:30:38 PST 2018]; root of context hierarchy
2018-12-01 23:30:41.624  WARN 21297 --- [           main] aWebConfiguration$JpaWebMvcConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2018-12-01 23:30:41.658  INFO 21297 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/iheartmedia/stations],methods=[GET]}" onto public java.util.List<com.iheartmedia.model.Station> com.iheartmedia.controller.StationController.retrieveAllStations()
2018-12-01 23:30:41.660  INFO 21297 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/iheartmedia/station],methods=[POST]}" onto public org.springframework.http.ResponseEntity<com.iheartmedia.dto.StationMixin> com.iheartmedia.controller.StationController.createStation(com.iheartmedia.model.Station,org.springframework.validation.Errors)
2018-12-01 23:30:41.660  INFO 21297 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/iheartmedia/station],methods=[DELETE]}" onto public org.springframework.http.ResponseEntity<com.iheartmedia.dto.StationMixin> com.iheartmedia.controller.StationController.deleteStation(com.iheartmedia.model.Station)
2018-12-01 23:30:41.663  INFO 21297 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2018-12-01 23:30:41.664  INFO 21297 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2018-12-01 23:30:41.687  INFO 21297 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-12-01 23:30:41.687  INFO 21297 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-12-01 23:30:41.979  INFO 21297 --- [           main] com.iheartmedia.model.StationTest        : Started StationTest in 3.704 seconds (JVM running for 4.431)
{station.call.sign.empty}
{station.name.empty}
{station.id.empty}
2018-12-01 22:11:10.360  INFO 18663 --- [       Thread-2] o.s.w.c.s.GenericWebApplicationContext   : Closing org.springframework.web.context.support.GenericWebApplicationContext@6892b3b6: startup date [Sat Dec 01 22:11:06 PST 2018]; root of context hierarchy
2018-12-01 22:11:10.363  INFO 18663 --- [       Thread-2] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2018-12-01 22:11:10.364  INFO 18663 --- [       Thread-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2018-12-01 22:11:10.367  INFO 18663 --- [       Thread-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

Process finished with exit code 0

messages.properties资源包

station.not.found=Station {0} was not found
station.id.empty=Station ID can not be empty.
station.id.format.not.valid=Station ID ${validatedValue} is not valid. Station ID should start with either W or K.
station.name.empty=Station name can not be empty.
station.call.sign.empty=Station call sign can not be empty.

我们的依赖树

Project Dependency Tree

我已阅读以下内容

  1. Custom error messaging on Hibernate Validation

  2. Custom Message Key in Hibernate validator not working with message.property

  3. Does Spring Boot automatically resolve message keys in javax and hibernate validation annotations

但是我仍然无法弄清楚我在做什么错。

更新

根据@Jonathan Johx的建议,我将ResourceBundleMessage的基本名称更改为messages(也更新了代码段),但是仍然出现错误。

1 个答案:

答案 0 :(得分:0)

问题是因为classpath:确实引用了ConfigurationHelper类的文件夹的根目录,但未找到。尝试将文件名重命名为Validator使用的 ValidationMessages .properties ,并更新以下行:

messageSource.setBasenames("ValidationMessages"); 

已更新

如果您要默认使用验证消息,则必须创建一个文件:

  

ValidationMessages.properties

并添加您认为必要的属性。