geronimo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Jencks <david_jen...@yahoo.com>
Subject Re: GBeanInstance/GBeanInstanceState eating exceptions?
Date Tue, 27 Feb 2007 00:22:36 GMT

On Feb 26, 2007, at 3:33 PM, Jason Dillon wrote:

> I think David Jencks added something (or was going to add  
> something) which would provide more detail for these exceptions  
> when run from the car-m-p.
>
> David, did you ever get around to adding that?  If not, is it  
> something you can easily do?

I definitely added it to trunk (2.0).  I'm not sure if it made it  
into 1.2.

thanks
david jencks

>
> --jason
>
>
> On Jan 19, 2007, at 4:20 PM, Dain Sundstrom wrote:
>
>> I didn't know you wanted details :)   Honestly, I have no idea why  
>> the exception is being eaten, other than it may be expected.  The  
>> startup is asynchronous, so the start may wake up in a "not yet  
>> ready" state.  The reason it is in the current state is recorded  
>> in GBEanInstance.getStateReason().
>>
>> It is the configuration object that has decided, that it has  
>> waited long enough and if all beans are not started it is going to  
>> give up.  The feature was recently added, and is a big improvement  
>> over the previous behavior of waiting forever.  Basically, the  
>> configuration attempts to get all beans started, if they don't all  
>> start then it throws an exception stating why some of the beans  
>> didn't start.
>>
>> Anyway, if you see some more information that needs to be  
>> propagated, by all means add it, just be careful, that you aren't  
>> wiping out relevant information with irrelevant info.
>>
>> -dain
>>
>> On Jan 19, 2007, at 2:05 PM, Jason Dillon wrote:
>>
>>> Where are the methods to pass back failure information from  
>>> GBeanInstanceState to GBeanInstance (and so on) ?
>>>
>>> I don't see anything like getFailureReason() or anything similar.
>>>
>>> How is one supposed to expose the MissingDependencyException that  
>>> is thrown in GBeanInstanceState.attemptFullStart(), which occurs  
>>> when calling gbeanInstance.createInstance() and is then caught  
>>> and eaten?
>>>
>>> I need to propagate this exception detail back further to the  
>>> component that asked for the component to be loaded, and attach  
>>> the detail to the failure exception that is thrown when we ask a  
>>> configuration to load.
>>>
>>> What is the api to store and retrieve exceptions later that you  
>>> mention?
>>>
>>> --jason
>>>
>>>
>>> On Jan 17, 2007, at 10:40 PM, Dain Sundstrom wrote:
>>>
>>>> I'm not going to try to justify the design, but I'll explain it...
>>>>
>>>> The lifecycle method don't necessarily result in the bean fully  
>>>> completing a state change.  The bean may enter a transition  
>>>> state like starting or stopping and wait there for a resource to  
>>>> become available.  Really, they just initiate  a lifecycle  
>>>> change that will complete at a later time.  If the method were  
>>>> to throw an exception it would be completely random if it  
>>>> "worked" or not.  Therefore, the methods don't throw exceptions  
>>>> and then are supposed to store the exception so it can be  
>>>> retrieved later.
>>>>
>>>> The key is that most gbeans are started by the configuration and  
>>>> the configuration will gather any failures and throw a single  
>>>> exception containing all the problems.
>>>>
>>>> Now if there are places problems occurs and the exceptions  
>>>> aren't saved, it is a bug.
>>>>
>>>> -dain
>>>>
>>>> On Jan 17, 2007, at 2:06 PM, Jason Dillon wrote:
>>>>
>>>>> Why do GBeanInstance/GBeanInstanceState eat exceptions instead  
>>>>> of throwing them?
>>>>>
>>>>> This seems to be a common pattern with GBeans, where they don't  
>>>>> propagate the exception detail.  I was just looking at  
>>>>> GBeanInstance.start(), but looks like stop() and other methods  
>>>>> have the same basic issues.
>>>>>
>>>>> The lack of detail being propagated results in build failures  
>>>>> like:
>>>>>
>>>>> <snip>
>>>>> Configuration gbean failed to start org.apache.geronimo.configs/ 
>>>>> openejb/2.0-SNAPSHOT/car
>>>>> </snip>
>>>>>
>>>>> But they show no detail as to why they failed.  This one  
>>>>> happens to be caused by:
>>>>>
>>>>> <snip>
>>>>> org.apache.geronimo.kernel.repository.MissingDependencyException:  
>>>>> Unable to resolve dependency org.apache.openejb/openejb-loader// 
>>>>> jar
>>>>>         at  
>>>>> org.apache.geronimo.kernel.repository.DefaultArtifactResolver.reso 
>>>>> lveInClassLoader(DefaultArtifactResolver.java:123)
>>>>>         at  
>>>>> org.apache.geronimo.kernel.repository.DefaultArtifactResolver$ 
>>>>> $FastClassByCGLIB$$e847b746.invoke(<generated>)
>>>>>         at net.sf.cglib.reflect.FastMethod.invoke 
>>>>> (FastMethod.java:53)
>>>>> ...
>>>>> </snip>
>>>>>
>>>>> But you would never know that unless you hack up the  
>>>>> GBeanInstanceState with printlns or something.  There is some  
>>>>> logging which is done, but that is getting lost due to mismatch  
>>>>> in log4j and maven logging systems.  I thought I had a bridge  
>>>>> setup to handle this, but it appears to have been broken for  
>>>>> sometime.  But aside from the logging issue, I think its a  
>>>>> bigger problem that the GBean stuff is not throwing exceptions  
>>>>> with meaningful details.
>>>>>
>>>>> There are other bits which look rather wrong wrt showing  
>>>>> exception details, like:
>>>>>
>>>>> <snip>
>>>>> try {
>>>>>     kernel.startRecursiveGBean(dependent);
>>>>> } catch (GBeanNotFoundException e) {
>>>>>     // this is ok the gbean died before we could start it
>>>>> } catch (Exception e) {
>>>>>     // there is something wrong with this gbean... skip it
>>>>> }
>>>>> </snip>
>>>>>
>>>>> There is no log here at all... this exception just gets  
>>>>> swallowed up.
>>>>>
>>>>> This also looks fishy:
>>>>>
>>>>> <snip>
>>>>> try {
>>>>>     // try to create the instance
>>>>>     if (!gbeanInstance.createInstance()) {
>>>>>         // instance is not ready to start... this is normally  
>>>>> caused by references
>>>>>         // not being available, but could be because someone  
>>>>> already started the gbean.
>>>>>         // in another thread.  The reference will log a debug  
>>>>> message about why
>>>>>         // it could not start
>>>>>         return;
>>>>>     }
>>>>> } catch (Throwable t) {
>>>>>     // oops there was a problem and the gbean failed
>>>>>     log.error("Error while starting; GBean is now in the FAILED  
>>>>> state: abstractName=\"" + abstractName + "\"", t);
>>>>>     setStateInstance(State.FAILED);
>>>>>     lifecycleBroadcaster.fireFailedEvent();
>>>>>
>>>>>     if (t instanceof Exception) {
>>>>>         // ignore - we only rethrow errors
>>>>>         return;
>>>>>     } else if (t instanceof Error) {
>>>>>         throw (Error) t;
>>>>>     } else {
>>>>>         throw new Error(t);
>>>>>     }
>>>>> }
>>>>>
>>>>> // started successfully... notify everyone else
>>>>> setStateInstance(State.RUNNING);
>>>>> lifecycleBroadcaster.fireRunningEvent();
>>>>> </snip>
>>>>>
>>>>> The catch here is actually what was handling the above  
>>>>> MissingDependencyException, which sets the state to failed,  
>>>>> broadcasts the event, then eats the exception, and then  
>>>>> continues to set the state to running and broadcasts that  
>>>>> event, which should fail on the state transition of FAILED ->  
>>>>> RUNNING... but we should not even be attempting that transition  
>>>>> because of the caught exception.
>>>>>
>>>>> The nice comment about the createInstance() logging a DEBUG  
>>>>> message is also odd... this failure reason really should also  
>>>>> be propagated via an exception to allow higher-level systems to  
>>>>> handle it as needed.  All of this exception eating is really  
>>>>> making things much more difficult than they need to be when  
>>>>> using the car plugin to build the server.
>>>>>
>>>>>  * * *
>>>>>
>>>>> What is the reasoning behind this behavior?  I think that we  
>>>>> can simplify things a lot by simply throwing exceptions, as  
>>>>> well as propagating details to layers that really need it (like  
>>>>> the car:package goal really needs to know why the gbean failed  
>>>>> to start so that it can communicate that to the user).
>>>>>
>>>>> Can someone please explain to me why these exceptions are not  
>>>>> being thrown?
>>>>>
>>>>> Thanks,
>>>>>
>>>>> --jason
>>>>
>>>
>>
>


Mime
View raw message