yikes... I didn't study this in detail recently but I wonder if we should add an xbean RuntimeNamingException that wraps the NamingException and have ContextFederation.getFederatedBindings() unwrap only this runtime exception?
david jencks On Oct 21, 2010, at 11:10 AM, Rick McGuire wrote: > On 10/21/2010 12:58 PM, David Jencks wrote: >> umm... >> >> doing a naming lookup should only throw NamingExceptions.... so I think what >> should happen is that the reference should wrap the ValidationException in a >> NamingException. Will this mess up the tck? > This seems like the correct thing to do, but unfortunately, it didn't work. > The problem is in the xbean ContextUtil$ReadOnlyBinding.getObject() method: > > public Object getObject() { > try { > return resolve(value,getName(),null,context); > }catch (NamingException e) { > throw new RuntimeException(e); > } > } > > This is catching the NamingException and turning it into a RuntimeException. > This doesn't seem correct to me, but the Binding interface it implements does > not throw any checked exceptions, so this is the only way this error can get > reflected back. > > Looking at the call chain, I'm thinking that > ContextFederation.getFederatedBindings() should catch RuntimeExceptions and > and either turn them into NamingExceptions or just ignore the exception like > it does with the NotContextExceptions. > > Rick > >> thanks >> david jencks >> >> On Oct 21, 2010, at 9:34 AM, David Jencks wrote: >> >>> Hi Rick, >>> >>> The code that does the lookup is here in the jetty integration code: >>> (GeronimoWebAppContext near line 104) >>> >>> try { >>> javax.naming.Context ctx = >>> integrationContext.getComponentContext(); >>> Object validatorFactory = ctx.lookup("comp/ValidatorFactory"); >>> >>> setAttribute("javax.faces.validator.beanValidator.ValidatorFactory", >>> validatorFactory); >>> } catch (NamingException e) { >>> // ignore. We just don't set the property if it's not available. >>> } >>> >>> >>> I suspect it used to pass because we were only using default validatory >>> factories so we could always create one. Either that, or we used to throw >>> a NamingException when we failed (the code you quote catches a naming >>> exception....). >>> >>> I wonder if a better solution would be to also catch and ignore a >>> ValidationException here? >>> >>> thanks >>> david jencks >>> >>> On Oct 21, 2010, at 7:55 AM, Rick McGuire wrote: >>> >>>> I played around with different solutions and finally came up with >>>> something that fixes the problem. Unfortunately, I'm not sure what I did >>>> is legitimate or not. The root problem here is the naming reference >>>> implementations were throwing ValidationExceptions for any failures with >>>> creating a ValidatorFactory. This probably was the behavior that should >>>> be implemented, but unfortunately, the getFederatedBindings() processing >>>> was triggering the resolution of these objects and the resulting >>>> exceptions were causing deploy failures. The test cases in question were >>>> testing the very conditions that triggered the exceptions. The exception >>>> was raised, but at deploy time, resulting in a test case failure. >>>> >>>> I managed to fix this by having the reference objects we bind into jndi >>>> catch the exceptions and just return null. Everything is passing in the >>>> TCK now, but I'm not sure returning null is the correct thing to do here. >>>> >>>> I'm not really sure how we every were passing 100% in the container with >>>> the original code. I would have thought that if the same sequence of >>>> calls were getting made to resolve the provider, then some of the same >>>> failures would have been seen. I'm going to hold off on committing my >>>> changes until I get some feedback on this. >>>> >>>> Rick >>>> >>>> On 10/21/2010 7:48 AM, Rick McGuire wrote: >>>>> We're down to 13 bean validation failures in the tck now, but these >>>>> failures are a little puzzling. The tests in error are all giving >>>>> deploy failures, with the root cause being an exception triggered by >>>>> getFederatedBindings(): >>>>> >>>>> java.lang.RuntimeException: javax.naming.NamingException: Validator [Root >>>>> exception is javax.validation.ValidationException: Unable to find >>>>> suitable provider: class >>>>> org.hibernate.jsr303.tck.common.TCKValidationProvider] >>>>> at >>>>> org.apache.xbean.naming.context.ContextUtil$ReadOnlyBinding.getObject(ContextUtil.java:201) >>>>> at >>>>> org.apache.xbean.naming.context.ContextFederation.getFederatedBindings(ContextFederation.java:118) >>>>> at >>>>> org.apache.xbean.naming.context.AbstractFederatedContext.getBindings(AbstractFederatedContext.java:99) >>>>> at >>>>> org.apache.xbean.naming.context.AbstractFederatedContext.getBinding(AbstractFederatedContext.java:86) >>>>> at >>>>> org.apache.xbean.naming.context.AbstractContext.lookup(AbstractContext.java:133) >>>>> at >>>>> org.apache.xbean.naming.context.AbstractContext.lookup(AbstractContext.java:605) >>>>> at >>>>> org.apache.geronimo.jetty8.handler.GeronimoWebAppContext.<init>(GeronimoWebAppContext.java:104) >>>>> at >>>>> org.apache.geronimo.jetty8.WebAppContextWrapper.<init>(WebAppContextWrapper.java:211) >>>>> at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native >>>>> Method) >>>>> at >>>>> sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) >>>>> at >>>>> sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) >>>>> at java.lang.reflect.Constructor.newInstance(Constructor.java:513) >>>>> at >>>>> org.apache.xbean.recipe.ReflectionUtil$ConstructorFactory.create(ReflectionUtil.java:952) >>>>> at >>>>> org.apache.xbean.recipe.ObjectRecipe.internalCreate(ObjectRecipe.java:276) >>>>> at >>>>> org.apache.xbean.recipe.AbstractRecipe.create(AbstractRecipe.java:96) >>>>> at >>>>> org.apache.xbean.recipe.AbstractRecipe.create(AbstractRecipe.java:61) >>>>> at >>>>> org.apache.geronimo.gbean.runtime.GBeanInstance.createInstance(GBeanInstance.java:933) >>>>> at >>>>> org.apache.geronimo.gbean.runtime.GBeanInstanceState.attemptFullStart(GBeanInstanceState.java:271) >>>>> at >>>>> org.apache.geronimo.gbean.runtime.GBeanInstanceState.start(GBeanInstanceState.java:105) >>>>> >>>>> >>>>> The root cause of this failure is an exception in >>>>> DefaultValidatorReference.getContent(): >>>>> >>>>> @Override >>>>> public Object getContent()throws NamingException { >>>>> ValidatorFactory factory =null; >>>>> try { >>>>> factory = (ValidatorFactory)new >>>>> InitialContext().lookup("java:comp/ValidatorFactory"); >>>>> }catch(NamingException e) { >>>>> factory =Validation.buildDefaultValidatorFactory(); >>>>> } >>>>> return factory.getValidator(); >>>>> } >>>>> >>>>> The root cause of this failure is the NamingException on the .lookup() >>>>> call. Since this occurs during the building of the federated context, I >>>>> suspect the initial context is not initialized correctly at this phase. >>>>> There's a bit of a chicken-and-egg problem here. The >>>>> buildDefaultValidatorFactory() call is failing because the incorrect >>>>> thread context classloader is getting used to resolve the provider. >>>>> >>>>> The puzzling piece to me is why this process is making the getContent() >>>>> calls in the first place. Since this binding will create a new instance >>>>> each time it is requested, either A) an instance is getting created >>>>> needlessly and thrown away or B) this instance is ending up bound to the >>>>> JNDI context as a one-off, which would be an incorrect result. >>>>> >>>>> I think I can fix this by making the DefaultValidatorReference look up >>>>> the ValidatorFactoryGBean to obtain the factory used to create the >>>>> ValidatorInstance rather than doing a jndi lookup, but I want to verify >>>>> that the lookup occurring at this point is the correct behavior and >>>>> there's not a better solution available. >>>>> >>>>> Rick >> >