【发布时间】:2018-12-02 06:56:04
【问题描述】:
我有一个标准的 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.
我们的依赖树
我已阅读以下内容
Custom Message Key in Hibernate validator not working with message.property
Does Spring Boot automatically resolve message keys in javax and hibernate validation annotations
但我仍然无法弄清楚我做错了什么。
更新
根据@Jonathan Johx 的建议,我将 ResourceBundleMessage 的基本名称更改为messages(也更新了代码 sn-p),但仍然出现错误。
【问题讨论】:
-
我猜在您的测试类中
Station对象成员为空。 (因为它是使用this.station = new Station()创建的)。而且您已经在验证器规则中说明了不能为空的规则。例如:stationId、stationName。如果我错了,请纠正我。 -
它应该为空。这就是验证失败的原因。但是由于某种原因没有查找消息键。
-
你能试试
messageSource.setBasename("classpath:messages");吗?
标签: spring hibernate spring-boot hibernate-validator