On Apr 3, 2011, at 12:24 PM, Romain Manni-Bucau wrote: > oh sorry, here is the temp file (waiting to have something working at least > a bit ;)):
:) > http://www.2shared.com/file/-BN3pMRJ/bean-validation-to-complete.html Note that those proxies are not really necessary. The JNDI context of an ejb or webapp is already attached to thread state. Basically here's how a JNDI lookup works: 1. A user does "java:comp/env/mything"; 2. It hits code that routes the call like so: Context ctx = ThreadContext.getThreadContext().getDeploymentInfo().getJndiEnc() return ctx.lookup(name); Then with the proxy approach any invocation on the proxy would loop back around and redo that whole process with a: String moduleId = ThreadContext.getThreadContext().getDeploymentInfo().getModuleID(); ValidatorFactory vf = system.getJNDIContext().lookup(Assembler.VALIDATOR_FACTORY_NAMING_CONTEXT + moduleId); vf.doTheCall(); Instead of binding that proxy into JNDI you can bind a link to the global name, like so: jndiEnc.bind("java:comp/env/mything", new IntraVmJndiReference(Assembler.VALIDATOR_FACTORY_NAMING_CONTEXT + moduleId)); Best place to do that would be JndiEncBuilder in the ResourceReferenceInfo loop of the buildMap() method. The JndiEncBuilder already has the moduleId as a field, so it should work out. And strictly speaking for the first iteration we don't have to wire it up to the EntityManagerFactory yet. We could just get the ValidatorFactory/Validator part going then fire up the Bean Validation TCK and see how close we are. When we have some confidence that we're on the right track, we could take on the EntityManagerFactory part as a separate phase. Side note that there isn't always thread state. Unit tests for example run without a ThreadContext until they invoke an EJB and then it only lasts for the call of the EJB. Nothing we can do about that as we aren't the ones executing the test method. That's the part that makes supporting "java:comp/env" lookups in test cases very hard. We do the test case injection support by more or less deploying the testcase as a bean and then when the user calls "bind(inject, testCase)" we use the class name of the test case as the deploymentId and can locate the right BeanContext that way. We then just call beanContext.getJndiEnc() to get the context. And because the context itself works fine without thread state everything from there works fine -- i.e. everything we pull out of the context and inject into the test case will continue working after the "bind(inject, testCase)" process completes. -David > 2011/4/3 David Blevins <[email protected]> > >> Might have to attach the patch to a JIRA. Don't think the list supports >> attachments. >> >> -David >> >> On Apr 3, 2011, at 8:42 AM, Romain Manni-Bucau wrote: >> >>> i attached a patch "to complete", i don't know how to do the TODO part >> (to get module id from a unknow call). >>> >>> i take all comments about this start... >>> >>> Romain >>> >>> 2011/4/3 Romain Manni-Bucau <[email protected]> >>> Is there a solution to get informations about current context (module id >> for example) at runtime (on a lookup)? >>> >>> Romain >>> >>> Le 3 avr. 2011 10:59, "Romain Manni-Bucau" <[email protected]> a >> écrit : >>> >>> >>>> can creating as many emf as persistence-unit * validation-factory >> number be >>>> a solution? >>>> >>>> for m in modules // has exactly one validation factory >>>> for p in pu >>>> emfs.put(p.id + " " + m.moduleId, createEm(p, m)) >>>> >>>> i could bind it in the jndi tree too. IMHO it is a bit like what is >> done >>>> today but it starts to be a bit heavy, no? >>>> >>>> Romain >>>> >>>> 2011/4/3 Romain Manni-Bucau <[email protected]> >>>> >>>>> In fact we have to create one emf by module (we could add some >> optimization >>>>> later) so the binding will change IMHO. In a try i set persistence and >>>>> validation in modules, it can work but it will change persistence >> management >>>>> so i think i have to wait thiago work to do it on 3.2.x too. What's >> your >>>>> opinion about this change? >>>>> >>>>> Romain >>>>> >>>>> Le 3 avr. 2011 01:42, "David Blevins" <[email protected]> a >> écrit : >>>>> >>>>>> Seems like we might have to find a way to track which module a >>>>> PersistenceUnitInfo comes from so we can give it the right >> ValidatorFactory. >>>>>> >>>>>> -David >>>>>> >>>>>> On Apr 2, 2011, at 12:29 PM, Romain Manni-Bucau wrote: >>>>>> >>>>>>> Probably a stupid question: validation dd can be defined by module >> but a >>>>>>> persistence module is shared between modules so how can i link a >>>>> validation >>>>>>> factory to a module in the entitymanager creation? Did i >> misunderstood >>>>> the >>>>>>> spec? >>>>>>> >>>>>>> - Romain >>>>>>> >>>>>>> Le 2 avr. 2011 01:25, "David Blevins" <[email protected]> a >> écrit >>>>> : >>>>>>>> >>>>>>>> On Apr 1, 2011, at 1:53 PM, Romain Manni-Bucau wrote: >>>>>>>> >>>>>>>>> it was my first question about the openejb jndi tree, i don't >> know >>>>> where >>>>>>>>> this context is accessible. >>>>>>>> >>>>>>>> The tree ends up looking like this >>>>> BeanContext->ModuleContext->AppContext. >>>>>>> The Assembler builds them all so any code part of the assembler can >> do >>>>>>> whatever they want with them during building and we can pass them >> around >>>>> as >>>>>>> needed in that code. Doesn't have to be on that object, but is an >> option >>>>> if >>>>>>> it makes things easier. >>>>>>>> >>>>>>>> I see we don't build the individual ModuleContext objects till >> later. >>>>> So >>>>>>> maybe there's some clever way to attach the ValidatorFactory >> instances >>>>> to >>>>>>> AppContext. Or a clever way to build the ModuleContext objects >> earlier. >>>>> Not >>>>>>> sure. >>>>>>>> >>>>>>>> In terms of the actual JNDI binding, what we did for EJB, >>>>> EntityManager, >>>>>>> and DataSource references is when we build the actual object we >> bind it >>>>> with >>>>>>> a global name. Then all references in the individual smaller JNDI >> trees >>>>> we >>>>>>> build are just pointers to the global name. So building the JNDI >> tree of >>>>> the >>>>>>> module or an ejb doesn't involve much and is really just a lot of >>>>>>> "symlinks." >>>>>>>> >>>>>>>> We may or may not be able to do that here. If we did the end >> result >>>>> would >>>>>>> be that each ValidatorFactory is bound exactly twice, once as >> itself (a >>>>>>> plain Factory) and again wrapped with some sort of wrapper like >>>>>>> BusinessLocalReference for the "get me a new Validator instance" >>>>> reference. >>>>>>>> >>>>>>>>> >>>>>>>>> ill verify but i think we doesn't need the mapping file but it >> will be >>>>>>>>> loaded before the entitymanager factory (of course ;)) >>>>>>>>> >>>>>>>>> so in your opinion i should load in the configurationfactory the >>>>>>>>> validation.xml, put it in Info objects then copy it in modules to >>>>> finally >>>>>>>>> bind validatorfactory/validator in module contexts? i find it a >> bit >>>>>>>>> complicated for a simple need, no? >>>>>>>> >>>>>>>> Passing a URI or String are our only other two options. Any "live" >>>>> objects >>>>>>> like URL is not allowed in the Info tree. We can always expand the >>>>>>> functionality later, so starting simple is fine. >>>>>>>> >>>>>>>> Here would be some side-effects of doing it in the Assembler and >>>>> creating >>>>>>> an JAXB and Info tree: >>>>>>>> >>>>>>>> 1 validation.xml file would gain altdd support (i.e. >>>>>>> META-INF/test.validation.xml) >>>>>>>> 2 could potentially do property overriding of validation.xml like >> we do >>>>>>> for persistence.xml properties >>>>>>>> 3 could construct a validation.xml in code -- we do this in >> various >>>>> tests >>>>>>> with ejb-jar.xml, beans.xml, and persistence.xml >>>>>>>> 4 xml parsing issues would be caught in the "configure" phase and >> not >>>>> in >>>>>>> the "assemble" phase >>>>>>>> >>>>>>>> It may or may not be worth it to do any of those things. Pragmatic >>>>> choices >>>>>>> are always fine :) It's usually easy to start simple and make it >> more >>>>>>> involved later, whereas the reverse is seldom true. So whatever >> gets the >>>>> job >>>>>>> done is fine. :) >>>>>>>> >>>>>>>> We could probably find a way to work in #1 regardless -- we'd just >> need >>>>> to >>>>>>> use the URL we get from module.getAltDDs(). Then either turn that >> URL >>>>> into a >>>>>>> URI and use that in the Info tree or perhaps somewhat lame, but >>>>> effective, >>>>>>> parse the xml and pass the contents as a String (would get us #4 at >>>>> least). >>>>>>>> >>>>>>>> #3 and #4 probably would require going "all the way" like we do >> for >>>>>>> persistence.xmls. Again, not sure if it is worth it and doesn't >> really >>>>> need >>>>>>> to be done now. >>>>>>>> >>>>>>>> The harder part is what to do in the Assembler anyway. >>>>>>>> >>>>>>>> >>>>>>>> -David >>>>>>>> >>>>>>>>> >>>>>>>>> 2011/4/1 David Blevins <[email protected]> >>>>>>>>> >>>>>>>>>> >>>>>>>>>> On Apr 1, 2011, at 1:13 PM, Romain Manni-Bucau wrote: >>>>>>>>>> >>>>>>>>>>> Hi all, >>>>>>>>>>> >>>>>>>>>>> to implement bean validation, is it a good idea to do like it >> (i >>>>> tried >>>>>>> to >>>>>>>>>>> write something simple but understandable, say me if i failed >> ;)): >>>>>>>>>>> >>>>>>>>>>> <[email protected]>1) create a builder ValidatorBuilder >> class >>>>>>>>>>> i) method createValidatorFactory(ModuleType type {WEBAPP, >> OTHER}, >>>>> URL >>>>>>>>>>> validationUrl {null or not}) returning a ValidatorFactory >>>>>>>>>>> 2) in Assembler::createApplication() >>>>>>>>>>> i) bind a dynamic proxy in "VALIDATOR_FACTORY_NAMING_CONTEXT + >>>>>>>>>>> ValidatorFactory" (same idea for Validator) - >>>>>>>>>>> containerSystem.getJNDIContext().bind("...", vfProxy) >>>>>>>>>>> ii) IMHO it should be done before the persistence building (to >> put >>>>> it >>>>>>>>>> as >>>>>>>>>>> parameter in the entity manager factory creation) but will it >> not >>>>> break >>>>>>>>>>> something about the weaving (i saw some comments about it)? >>>>>>>>>>> 3) the proxy/proxies >>>>>>>>>>> i) manage a map/cache of ValidatorFactory and Validator (is it >>>>>>>>>> necessary >>>>>>>>>>> for validator?). The key will be the module (maybe the path? it >>>>> should >>>>>>>>>> only >>>>>>>>>>> be unique) >>>>>>>>>>> ii) invoke(...) { >>>>>>>>>>> type = getModuleTypeFromClassLoader(); >>>>>>>>>>> if (!validatorFactoryExistsForModule(currentModule())) { >>>>>>>>>>> vf = ValidatorBuilder::createValidatorFactory(type); >>>>>>>>>>> } >>>>>>>>>>> return whatWeWantByReflection(); >>>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> One quick thought would be to maybe put the ValidatorFactory >> instance >>>>> in >>>>>>>>>> the ModuleContext object. Should eliminate the need for any >>>>>>> mapping/caching >>>>>>>>>> which often ends up leaky. We might even (someday) want to redo >> some >>>>> of >>>>>>> the >>>>>>>>>> EntityManagerFactory stuff that way -- we didn't have an >> AppContext >>>>> or >>>>>>>>>> ModuleContext when that code was written. >>>>>>>>>> >>>>>>>>>> On the URL note. The Info object tree passed from the >>>>>>> ConfigurationFactory >>>>>>>>>> to the Assembler doesn't allow URL or Class or any other thing >> tied >>>>> to a >>>>>>>>>> classloader. If we were to create a set of Info objects to >> represent >>>>> the >>>>>>>>>> validation.xml, how complex would that tree be? For the >> beans.xml and >>>>>>>>>> persistence.xml it was pretty simple. >>>>>>>>>> >>>>>>>>>> The validation configuration file looks really simple. The >> mapping >>>>> file >>>>>>> is >>>>>>>>>> complex. I'm not sure if we need both or just one of them like >> in JPA >>>>>>> (we >>>>>>>>>> handle persistence.xml and the provider handles the mapping >> files) >>>>>>>>>> >>>>>>>>>> -David >>>>>>>>>> >>>>>>>>>> >>>>>>>> >>>>>> >>>>> >>> >> >>
