spring4.2.3 및 hibernate5.1.0 기반 프로젝트에서 폼 유효성 검사를 위해 커스텀 애노테이션을 사용하고 있습니다.커스텀 애노테이션을 사용한 스프링 폼 유효성 확인
1) 내 주석 인터페이스 내 논리 클래스 UnitConstraintValidator 나는 사용자 정의 주석을 사용하고있는 곳
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import com.rapidtech.rapidtechorganic.custom.annotation.IsUnit;
public class UnitConstraintValidator implements ConstraintValidator<IsUnit, String> {
@Override
public void initialize(IsUnit unit) {
// TODO Auto-generated method stub
}
@Override
public boolean isValid(String unit, ConstraintValidatorContext cxt) {
if(unit.equals(null) || unit == null){
return false;
}
if(unit.matches("kg|KG|Kg|Litre|litre|lt|ton|Ton")){
return true;
}
return false;
}
}
3) 내 모델 클래스처럼 보이는)이
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import com.rapidtech.rapidtechorganic.custom.logic.UnitConstraintValidator;
@Documented
@Constraint(validatedBy = UnitConstraintValidator.class)
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IsUnit {
String message() default "Please Enter a valid UNIT e.g. kg,litre,ton";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
이 보이는
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.rapidtech.rapidtechorganic.custom.annotation.IsUnit;
@JsonIgnoreProperties(ignoreUnknown = true)
@Entity
public class Lot implements java.io.Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long lotId;
@Size(min=5,max=30)
private String lotNumber;
@IsUnit
private String lotName;
@OneToOne(cascade = {CascadeType.ALL})
private ProductAvailable productAvailable;
public long getLotId() {
return lotId;
}
public void setLotId(long lotId) {
this.lotId = lotId;
}
public String getLotNumber() {
return lotNumber;
}
public void setLotNumber(String lotNumber) {
this.lotNumber = lotNumber;
}
public String getLotName() {
return lotName;
}
public void setLotName(String lotName) {
this.lotName = lotName;
}
public ProductAvailable getProductAvailable() {
return productAvailable;
}
public void setProductAvailable(ProductAvailable productAvailable) {
this.productAvailable = productAvailable;
}
}
4) 사용자 지정 주석을 사용하는 My ProductAvailable 모델 클래스
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.validation.constraints.Size;
import com.rapidtech.rapidtechorganic.custom.annotation.IsUnit;
@Entity
public class ProductAvailable implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long productAvailableId;
@Size(min=2,max=30,message="ahha ahha ahha")
private String productAvailableName;
@IsUnit
private String productAvailableUnit;
private double productAvailableUnitTransportationCharge;
private double productAvailableUnitLabourCharge;
private double productAvailableUnitOtherCharge;
private long productAvailableQuantity;
private double productAvailableUnitPrice;
@OneToOne
private Lot lot;
public long getProductAvailableId() {
return productAvailableId;
}
public void setProductAvailableId(long productAvailableId) {
this.productAvailableId = productAvailableId;
}
public String getProductAvailableName() {
return productAvailableName;
}
public void setProductAvailableName(String productAvailableName) {
this.productAvailableName = productAvailableName;
}
public long getProductAvailableQuantity() {
return productAvailableQuantity;
}
public void setProductAvailableQuantity(long productAvailableQuantity) {
this.productAvailableQuantity = productAvailableQuantity;
}
public double getProductAvailableUnitPrice() {
return productAvailableUnitPrice;
}
public void setProductAvailableUnitPrice(double productAvailableUnitPrice) {
this.productAvailableUnitPrice = productAvailableUnitPrice;
}
public String getProductAvailableUnit() {
return productAvailableUnit;
}
public void setProductAvailableUnit(String productAvailableUnit) {
this.productAvailableUnit = productAvailableUnit;
}
public double getProductAvailableUnitTransportationCharge() {
return productAvailableUnitTransportationCharge;
}
public void setProductAvailableUnitTransportationCharge(double productAvailableUnitTransportationCharge) {
this.productAvailableUnitTransportationCharge = productAvailableUnitTransportationCharge;
}
public double getProductAvailableUnitLabourCharge() {
return productAvailableUnitLabourCharge;
}
public void setProductAvailableUnitLabourCharge(double productAvailableUnitLabourCharge) {
this.productAvailableUnitLabourCharge = productAvailableUnitLabourCharge;
}
public double getProductAvailableUnitOtherCharge() {
return productAvailableUnitOtherCharge;
}
public void setProductAvailableUnitOtherCharge(double productAvailableUnitOtherCharge) {
this.productAvailableUnitOtherCharge = productAvailableUnitOtherCharge;
}
public Lot getLot() {
return lot;
}
public void setLot(Lot lot) {
this.lot = lot;
}
}
유효성 검사를 위해 hibernate-validator4.1.0.Final 및 JSR 303을 사용하고 있습니다.
내가 알 수 있듯이 하나의 Lot이 많은 ProductAvailable을 가질 수 있다는 것을 의미하는 OneToMany 매핑과 함께 두 개의 모델 클래스 Lot 및 ProductAvailable이 있습니다.
내 문제는 다음과 같습니다 내 사용자 정의 annotaion 클래스 부지와 잘 작동하지만, 클래스 ProductAvailable의 경우에는 예외를 던지는 IsUnit.
예외는 다음과 같습니다
javax.validation.ConstraintViolationException: Validation failed for classes [com.rapidtech.rapidtechorganic.model.ProductAvailable] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='Please Enter a valid UNIT e.g. kg,litre,ton', propertyPath=productAvailableUnit, rootBeanClass=class com.rapidtech.rapidtechorganic.model.ProductAvailable, messageTemplate='Please Enter a valid UNIT e.g. kg,litre,ton'}
]
org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:138)
org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:78)
org.hibernate.action.internal.EntityInsertAction.preInsert(EntityInsertAction.java:205)
org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:82)
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:560)
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:434)
org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1295)
org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:468)
org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3135)
org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2352)
org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
com.rapidtech.rapidtechorganic.dao.AbstractDao.save(AbstractDao.java:30)
com.rapidtech.rapidtechorganic.dao.lot.LotDaoImpl.save(LotDaoImpl.java:22)
com.rapidtech.rapidtechorganic.service.LotServiceImpl.save(LotServiceImpl.java:25)
com.rapidtech.rapidtechorganic.controller.LotController.saveLotController(LotController.java:59)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
내 컨트롤러 클래스는 다음과 같습니다
@RequestMapping(value = "/saveLot", method = RequestMethod.POST)
public ModelAndView saveLotController(@Valid @ModelAttribute(value="lot") Lot lot, BindingResult result) {
ModelAndView model;
if(result.hasErrors()){
model = new ModelAndView("saveLotForm");
}
else {
Services lotService = (LotServiceImpl) appContext.getBean("lotServiceImpl");
lot.getProductAvailable().setLot(lot);
lotService.save(lot);
model = new ModelAndView("Success");
model.addObject("successMessage","Lot "+lot.getLotName()+" Saved Successfully!");
}
return model;
}
어떤 도움 appreaciated 사전에 감사 할 것입니다.
그리고 그 문제는 무엇입니까?! 유효성 검사를 수행하고 유효성 검사 규칙을 준수하지 않습니다. 그래서 그렇습니다. 실패 할 것입니다. –
정확하게 알려주세요. – tinku