java ee - Correct way to do an EntityManager query during Hibernate Validation -


i'm bit of java ee/ejb noob, docs , other posts i've gathered cannot query database using same entitymanager/session during entity validation.

in general, lifecycle method of portable application should not invoke entitymanager or query operations, access other entity instances, or modify relationships within same persistence context.[43] lifecycle callback method may modify non-relationship state of entity on invoked.

translation please?

this pretty abstract...can explained in more concrete terms? leads more questions answers. example, if entity has lazy-loaded collection allowed access during validation? collection 'another entity' , require db query seems in violation of docs.

this 'lifecycle requirement' seems odd because it's fact of life validations indeed require querying database.

from other posts i've seen people around querying issue creating new entitymanager/session using entitymanagerfactory.

this leads me 2 questions using entitymanagers , hibernate validation:

  1. is possible have sort of design flaw or misusing hibernate validation because need query database during validation?
  2. given i'm using java ee jboss, how inject validator entitymanagerfactory?

i've tried this:

@stateless public class uservalidator implements constraintvalidator<validuser, user> {     @persistenceunit(unitname="blahblah")     entitymanagerfactory emf;      ... } 

but emf never gets injected. i'm guessing @stateless tag becomes irrelevant because i'm implementing constraintvalidator interface needed hibernate validator stuff work.

so what's general pattern getting @ entitymanagerfactory validator?

thanks!

through of comments , enough scrounging around, figured out 'canonical' way answer question.

but clear things up, question asking 2 things have 2 distinct answers:

  1. how inject things validators used in hibernate validation framework?
  2. assuming can inject things safe inject entitymanagerfactory or entitymanager , use them querying during jpa lifecycle event?

answering second question first i'll say, encouraged use second entitymanager queries during validation. means should injecting entitymanagerfactory , creating new entitymanager queries (rather injecting entitymanager same 1 created lifecycle event begin with).

generally speaking, validation purposes, you'll querying database anyway , not inserting/updating should safe do.

i asked related question here.

now answer question 1.

yes possible inject things validators used in hibernate validation framework. accomplish need 3 things:

  1. create custom constraintvalidatorfactory create validators used in framework (overriding hibernate's default factory). (my example uses java ee, not spring use beanmanager, in spring you'd use applicationcontext this).
  2. create validation.xml file tells hibernate validation framework class use constraintvalidatorfactory. make sure file ends on classpath.
  3. write validator injects something.

here example custom constraintvalidatorfactory uses 'managed' (injectable) validators:

package com.myvalidator;  public class constraintinjectablevalidatorfactory implements constraintvalidatorfactory {      private static beanmanager beanmanager;      @suppresswarnings(value="unchecked")     @override     public <t extends constraintvalidator<?, ?>> t getinstance(class<t> clazz) {         // lazily initialize beanmanager         if (beanmanager == null) {             try {                 beanmanager = (beanmanager) initialcontext.dolookup("java:comp/beanmanager");             } catch (namingexception e) {                 // todo what's best way handle this?                 throw new runtimeexception(e);             }         }          t result = null;          bean<t> bean = (bean<t>) beanmanager.resolve(beanmanager.getbeans(clazz));         // if bean/validator specified clazz not null means has         // injection points beanmanager , return it. validator         // comes beanmanager injected.         if (bean != null) {             creationalcontext<t> context = beanmanager.createcreationalcontext(bean);             if (context != null) {                 result = (t) beanmanager.getreference(bean, clazz, context);             }         // bean/validator not in beanmanager meaning has no injection         // points go ahead , instantiate new instance , return         } else {             try {                 result = clazz.newinstance();             } catch (throwable t) {                 throw new runtimeexception(t);             }         }          return result;     } } 

here example validation.xml file tells hibernate validator class use validatorfactory:

<?xml version="1.0" encoding="utf-8"?> <validation-config     xmlns="http://jboss.org/xml/ns/javax/validation/configuration"     xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"     xsi:schemalocation="http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.0.xsd">     <constraint-validator-factory>         com.myvalidator.constraintinjectablevalidatorfactory     </constraint-validator-factory> </validation-config> 

and validator class injection points:

public class uservalidator implements constraintvalidator<validuser, user> {      @persistenceunit(unitname="myvalidator")     private entitymanagerfactory entitymanagerfactory;      private entitymanager entitymanager;      @override     public void initialize(validuser annotation) {     }      @override     public boolean isvalid(user user, constraintvalidatorcontext context) {         // validation takes place during entitymanager.persist() lifecycle,         // here create new entitymanager separate original 1         // invoked validation         entitymanager = entitymanagerfactory.createentitymanager();          // use entitymanager query database needed validation          entitymanager.close();     } } 

Comments

Popular posts from this blog

assembly - 8086 TASM: Illegal Indexing Mode -

Java, LWJGL, OpenGL 1.1, decoding BufferedImage to Bytebuffer and binding to OpenGL across classes -

javascript - addthis share facebook and google+ url -