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 01:52:33 GMT
The stuff I added was mostly changing interfaces so the client could  
access the reason, and having the client do so: I also changed a  
bunch of places to record more info in the reason.

thanks
david jencks

On Feb 26, 2007, at 5:43 PM, Dain Sundstrom wrote:

> I fixed a bug in 1.2, where the exception was being rethrown before  
> it was recorded as the root cause.
>
> -dain
>
> On Feb 26, 2007, at 4:22 PM, David Jencks wrote:
>
>>
>> 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.re

>>>>>>> solveInClassLoader(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