Technologies: Spring, Hibernate, JSR-303, JQuery
Platform: Windows
I am trying to implement the @IdMustExist JSR-303 constraint. The purpose of the restriction is to check if the entered identifier value exists in the linked table. See Link for code snippets IdMustExist.java and IdMustExistValidator.java.
Scenario 1 - a valid identifier value is entered: in this case, when the hibernate EntityManager.merge operation is performed, I see that the @IdMustExist constraint is being met. It successfully confirms that the entered identifier value exists in another linked / linked table. Hibernate successfully completes the save operation. I noticed that hibernate fires selects SQL for the object before calling validator for @IdMustExist.
Scenario 2 - an invalid identifier value is entered: in this case, when the hibernate EntityManager.merge operation is performed, it throws an EntityNotFoundException (stack trace below), because it could not find the object for the entered invalid identifier. I was hoping that the @IdMustExist constraint would be triggered during the pre-upgrade phase and we could gracefully display the error message to the user. But something seems to fail until hibernation can enter the pre-update phase. I see that hibernation triggers SQL queries for an object and then throws an EntityNotFoundException. It has no way to call validate @IdMustExist.
Does this mean that I canβt check if the entered identifier exists in the linked / linked table via JSR-303? Any alternatives?
Thanks for your help in advance. In JP
javax.persistence.EntityNotFoundException: Unable to find com.mycompany.myapp.domain.package1.Class1 with id 100 at org.hibernate.ejb.Ejb3Configuration$Ejb3EntityNotFoundDelegate.handleEntityNotFound(Ejb3Configuration.java:133) at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:233) at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:285) at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152) at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1080) at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:1028) at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:623) at org.hibernate.type.EntityType.resolve(EntityType.java:431) at org.hibernate.type.EntityType.replace(EntityType.java:291) at org.hibernate.type.TypeFactory.replace(TypeFactory.java:532) at org.hibernate.event.def.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:495) at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:423) at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:234) at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:84) at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:859) at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:843) at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:847) at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:682) at com.mycompany.myapp.dao.hibernate.package2.HibernateClass2Dao.save(HibernateClass2Dao.java:101) at com.mycompany.myapp.service.package2.Class1ServiceImpl.update(Class1ServiceImpl.java:56) ... ... at java.lang.Thread.run(Thread.java:619)
HibernateClass2Dao.java
public void save(GenericRequest request, GenericResponse response){ Class2 class2Request = (Class2) request.getObject(Class2.class.getName()); EntityManager em = PersistenceUtil.getEntityManagerFactory().createEntityManager(); Class2 class2Persisted = em.find(Class2.class, class2Request.getId()); EntityTransaction tx = em.getTransaction(); try { tx.begin(); class2Persisted.setClass1(class2Request.getClass1()); em.merge(class2Request); tx.commit(); } catch (RollbackException rbe) { response.setSuccess(false); rbe.getCause().printStackTrace(); ConstraintViolationException cve = (ConstraintViolationException) rbe.getCause(); Set<ConstraintViolation<?>> constraintViolations = cve.getConstraintViolations(); if (constraintViolations.size() > 0){ for (ConstraintViolation<?> violation : constraintViolations){ Iterator<Node> itr = violation.getPropertyPath().iterator(); String propertyPath = itr.next().getName(); Class<? extends Payload> payload = violation.getConstraintDescriptor().getPayload().iterator().next(); String payloadName = payload.getCanonicalName(); response.addMessage(violation.getMessage(), violation.getLeafBean().getClass().getName(), propertyPath , payloadName); } } } finally { em.close(); } }
Class2ServiceImpl.java
public void update(GenericRequest request, GenericResponse response){ class2Dao.save(request, response); }
Class2Controller.java
@RequestMapping(value="/update") public @ResponseBody GenericResponse update(String jqGridId, String oper , Class2 class2 , BindingResult bindingResult) throws Exception { GenericResponse response = new GenericResponse(true); response.setMessageSource(messageSource); Locale locale = new Locale(CommonConstants.DEFAULT_LOCALE); if (bindingResult.hasErrors()){ response.setSuccess(false); addBindingMessages(response, bindingResult, locale); return response; } class2.setId(Long.parseLong(jqGridId)); class2.setCode(jqGridId); GenericRequest request = new GenericRequest(UserUtil.getUser(), class2); this.class2Service.update(request, response); return response; }