On Sat, Aug 23, 2003 at 11:01:21PM -0700, Jeremy Boynes wrote:
> > From: Dain Sundstrom [mailto:[EMAIL PROTECTED]
> > I think you missed the best point in this email
> Maybe, but I don't follow your example...
>
> >
> > On Saturday, August 23, 2003, at 02:31 PM, David Blevins wrote:
> >
> > > We actually do wrap exceptions though.
> > > - If the bean throws a checked exception, we wrap it with
> > a special
> > > exception type. When the client side get the exception, it
> > pulls out
> > > the nested exception and throws it.
> > > - If the bean throws an unchecked exception, we wrap it in a
> > > different exception (InvalidateReferenceException). When
> > the client
> > > get's one of those, the proxy is invalidated as the bean
> > was garbage
> > > collected, the nested exception is then thrown which will be a
> > > RemoteException/EJBException/TransactionRolledbackException/etc.
> >
> > So in the CallBackInterceptor you do something like this:
> >
> > try {
> > return new
> > SimpleInvocationResult(callbackMethod.invoke(instance, callbackArgs));
> > } catch (IllegalAccessException e) {
> > // This method is using the Java language access
> > control and the
> > // underlying method is inaccessible.
> > throw new EJBException(e);
> > } catch (InvocationTargetException e) {
> > // unwrap the exception
> > throw new ApplicationException(e.getTargetException();
> > }
> >
> >
> > Then later in the chain, if you want to distinguish the
> > ApplicationException from the container exception just catch
> > ApplicationException specifically, so for your example you would have
> > this:
> >
> > boolean threwApplicationException = false;
> > try {
> > return getNext().invoke(invocation);
> > } catch (ApplicationException e) {
> > threwSystemException = true;
> > throw e;
> > } finally {
> > // this invocation is done so remove the reference to the
> > context
> > EJBInvocationUtil.putEnterpriseContext(invocation, null);
> > if (threwApplicationException) {
> > // invocation threw an application exception so the pool
> > // needs to dispose of the context
> > pool.remove(ctx);
> > } else {
> > // return the context to the pool
> > pool.release(ctx);
> > }
> > }
> >
> >
> > I think this is much cleaner and we don't have to inspect the result
> > for the exceptional cases. In the client container you catch the
> > ApplicationException and throw the root cause.
> >
>
> Doesn't this need to be:
>
> boolean threwSystemException = false;
> try {
> return getNext().invoke(invocation);
> } catch (InvalidateReferenceException e) {
> threwSystemException = true;
> throw e;
> } catch (Exception e) {
> threwSystemException = true;
> throw e;
> } catch (Error e) {
> threwSystemException = true;
> throw e;
> } finally {
> EJBInvocationUtil.putEnterpriseContext(invocation, null);
> if (threwSystemException) {
> // invocation threw a system exception so the pool
> // needs to dispose of the context
> pool.remove(ctx);
> } else {
> // return the context to the pool
> pool.release(ctx);
> }
> }
>
> You still need to ensure that the context gets disposed of if there was
> a Exception thrown by an interceptor, leaving you with the catch blocks.
> So you still have multiple return paths:
> * normal result
> * ApplicationException being thrown
> * InvalidateReferenceException being thrown
> * Exception from an Interceptor
> * Error from an Interceptor
>
You only need to catch a specific exception type when you need to do something
unique. The above block could be written as:
try {
InvocationResult r = getNext().invoke(invocation);
pool.release(ctx);
return r;
} catch (Throwable t) {
pool.remove(ctx);
throw t;
} finally {
EJBInvocationUtil.putEnterpriseContext(invocation, null);
}
-David