ejb@glassfish.java.net

Re: Application Exception being wrapped into EJBException

From: Antonio Goncalves <antonio.mailing_at_gmail.com>
Date: Mon, 2 Oct 2006 17:28:03 +0200

> Also note that even if the ValidationException were to be propagated as
> is, the persistence manager still would not know it is an EJB "Application
Exception"
> so any required behavior such as marking the transaction for rollback
would still be
> performed by the persistence manager regardless of the attributes of the
> @ApplicationException definition.

That makes sense. I going to try a similar use case outside the container to
see what king of exception is thrown. I've changed my ValidationException to
extend Exception instead of RuntimeException, but it doesn't work either.
The exception is still wrapped into an EJBException and the root cause is
event worse *Caused by: java.lang.ClassCastException:
com.yaps.petstore.exception.ValidationException*.

javax.ejb.EJBException
 at com.sun.ejb.containers.BaseContainer.processSystemException(
BaseContainer.java:3753)
 at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java
:3653)
 at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java
:3455)
 at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1257)
 at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(
EJBLocalObjectInvocationHandler.java:192)
 at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(
EJBLocalObjectInvocationHandlerDelegate.java:118)
 at $Proxy69.createCustomer(Unknown Source)
 at com.yaps.petstore.web.jsf.AccountController.doCreateCustomer(Unknown
Source)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(
NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(
DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:585)
 at com.sun.el.parser.AstValue.invoke(AstValue.java:157)
 at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:283)
 at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(
MethodBindingMethodExpressionAdapter.java:71)
 at com.sun.faces.application.ActionListenerImpl.processAction(
ActionListenerImpl.java:96)
 at javax.faces.component.UICommand.broadcast(UICommand.java:383)
 at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:471)
 at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:783)
 at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(
InvokeApplicationPhase.java:97)
 at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:244)
 at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:113)
 at javax.faces.webapp.FacesServlet.service(FacesServlet.java:244)
 at org.apache.catalina.core.ApplicationFilterChain.servletService(
ApplicationFilterChain.java:397)
 at org.apache.catalina.core.StandardWrapperValve.invoke(
StandardWrapperValve.java:278)
 at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java
:586)
 at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java
:556)
 at org.apache.catalina.core.StandardContextValve.invokeInternal(
StandardContextValve.java:246)
 at org.apache.catalina.core.StandardContextValve.invoke(
StandardContextValve.java:185)
 at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java
:586)
 at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:73)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java
:182)
 at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java
:586)
 at com.sun.enterprise.web.VirtualServerPipeline.invoke(
VirtualServerPipeline.java:120)
 at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:939)
 at org.apache.catalina.core.StandardEngineValve.invoke(
StandardEngineValve.java:137)
 at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java
:586)
 at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java
:556)
 at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:939)
 at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:231)
 at
com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(
DefaultProcessorTask.java:619)
 at
com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.processNonBlocked
(DefaultProcessorTask.java:550)
 at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(
DefaultProcessorTask.java:780)
 at
com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask
(DefaultReadTask.java:326)
 at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(
DefaultReadTask.java:251)
 at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(
DefaultReadTask.java:205)
 at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:252)
 at com.sun.enterprise.web.connector.grizzly.WorkerThreadImpl.run(
WorkerThreadImpl.java:103)
*Caused by: java.lang.ClassCastException:
com.yaps.petstore.exception.ValidationException*
 at
oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener.invokeMethod
(MetadataEntityListener.java:313)
 at
oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityClassListener.invokeMethod
(MetadataEntityClassListener.java:69)
 at
oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener.prePersist
(MetadataEntityListener.java:439)
 at
oracle.toplink.essentials.descriptors.DescriptorEventManager.notifyListener(
DescriptorEventManager.java:658)
 at
oracle.toplink.essentials.descriptors.DescriptorEventManager.notifyEJB30Listeners
(DescriptorEventManager.java:601)
 at
oracle.toplink.essentials.descriptors.DescriptorEventManager.executeEvent(
DescriptorEventManager.java:199)
 at
oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.registerNotRegisteredNewObjectForPersist
(UnitOfWorkImpl.java:3226)
 at
oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.registerNotRegisteredNewObjectForPersist
(RepeatableWriteUnitOfWork.java:298)
 at
oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist
(UnitOfWorkImpl.java:3186)
 at
oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerImpl.persist(
EntityManagerImpl.java:170)
 at com.sun.enterprise.util.EntityManagerWrapper.persist(
EntityManagerWrapper.java:433)
 at com.yaps.petstore.service.customer.CustomerBean.createCustomer(Unknown
Source)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(
NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(
DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:585)
 at com.sun.enterprise.security.application.EJBSecurityManager.runMethod(
EJBSecurityManager.java:1050)
 at com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:165)
 at com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod(
BaseContainer.java:2788)
 at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:3870)
 at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(
EJBLocalObjectInvocationHandler.java:184)
 ... 43 more



2006/10/2, Kenneth Saks <Kenneth.Saks_at_sun.com>:
>
> Cheng Fang wrote:
>
> > Our tests for the similar scenario passed. The only difference
> > between our tests and your is, your ValidationException is from Entity
> > lifecycle callback methods, and our unchecked ApplicationException is
> > from a regular slsb business methods.
> > JPA spec says entity lifecycle callback methods may throw
> > runtime/uncheckec exception, which causes the current transaction to
> > be rolled back. So your unchecked ApplicationException behaves more
> > like a system exception. EJB interceptor methods are more restrictive
> > in that it does not allow any application exception.
>
> That's true of callbacks defined in an interceptor class, but not true
> of AroundInvoke methods.
> The signature of an AroundInvoke method is defined to throw
> java.lang.Exception so that it may
> propagate any application-defined exceptions that appear in the
> corresponding business
> method's signature.
>
> >
> >
> > Throwing such runtime exception from @PrePersist seems a pretty common
> > use case. The JPA spec has such an example. Can someone clarify?
>
> I'm not aware of any requirements in the persistence spec that guarantee
> that an exception thrown
> by the entity code will propagate *as is* back to the caller of an
> EntityManager API. The EntityManager
> API is typed to throw certain specific runtime exceptions. The
> @ApplicationException behavior
> is EJB-container specific, so the persistence manager doesn't know
> anything about it. The persistence
> manager is probably just wrapping the ValidationException into one of
> the exceptions defined in
> the persist() API method signature. The ejb container then sees a
> runtime exception, not an
> Application Exception.
>
> Also note that even if the ValidationException were to be propagated as
> is, the persistence
> manager still would not know it is an EJB "Application Exception" so any
> required behavior
> such as marking the transaction for rollback would still be performed by
> the persistence
> manager regardless of the attributes of the @ApplicationException
> definition.
>
> --ken
>
> >
> >
> > Cheng
> >
> >
> >
> >
> > Antonio Goncalves wrote:
> >
> >> Hi,
> >>
> >> I've got a JSF back bean trying to catch my application exception but
> >> ends up with an EJBException. Here is my model :
> >>
> >> * A Customer entity bean throws an Application Exception in a call
> >> back method to validate its data
> >>
> >> @Entity
> >> public class Customer implements Serializable {
> >>
> >> @PrePersist
> >> @PreUpdate
> >> private void validateData() {
> >> if (firstname == null || "".equals(firstname))
> >> throw new *ValidationException*("Invalid first name");
> >> if (lastname == null || "".equals(lastname))
> >> throw new ValidationException("Invalid last name");
> >> }
> >> }
> >>
> >> * The Validation Exception is a RuntimeException but uses the
> >> ApplicationException annotation
> >>
> >> @*ApplicationException*(rollback = true)
> >> public class *ValidationException* extends *RuntimeException* {
> >>
> >> }
> >>
> >> * Between the Entity and JSF there is a Stateless bean that
> >> manipulates this entity but doesn't wrap or throw an exception
> >>
> >> @Stateless
> >> public class CustomerBean implements CustomerRemote, CustomerLocal {
> >>
> >> @PersistenceContext(name = "petstorePU")
> >> private EntityManager em;
> >>
> >> public Customer createCustomer(final Customer customer) {
> >> em.persist(*customer*);
> >> }
> >>
> >> }
> >>
> >> * My JSF Back Bean calls the Stateless to create a customer. He tries
> >> to catch the ValidationException and display the error message on my
> >> page
> >>
> >> public String doCreateCustomer() {
> >>
> >> FacesContext context = FacesContext.getCurrentInstance();
> >> String navigateTo = null;
> >>
> >> try {
> >> customer = customerBean.createCustomer(customer, address);
> >> } *catch (ValidationException e)* {
> >> context.addMessage(null, new
> >> FacesMessage(FacesMessage.SEVERITY_WARN , e.getMessage(), null));
> >> }
> >>
> >> If I change the catch (ValidationException e) into catch
> >> (EJBException e) it woks because here is my stack trace on the server
> >>
> >> *javax.ejb.EJBException*
> >> at
> >> com.sun.ejb.containers.BaseContainer.processSystemException(
> BaseContainer.java:3753)
> >>
> >> at
> >> com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java
> :3653)
> >>
> >> at
> >> com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java
> :3455)
> >>
> >> at
> >> com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java
> :1257)
> >> at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke
> >> (EJBLocalObjectInvocationHandler.java:192)
> >> at
> >> com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(
> EJBLocalObjectInvocationHandlerDelegate.java:118)
> >>
> >> at $Proxy163.createCustomer(Unknown Source)
> >> at
> >> com.yaps.petstore.web.jsf.AccountController.doCreateCustomer(Unknown
> >> Source)
> >> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> >> at
> >> sun.reflect.NativeMethodAccessorImpl.invoke(
> NativeMethodAccessorImpl.java
> >> :39)
> >> at
> >> sun.reflect.DelegatingMethodAccessorImpl.invoke(
> DelegatingMethodAccessorImpl.java:25)
> >>
> >> at java.lang.reflect.Method.invoke(Method.java:585)
> >> at com.sun.el.parser.AstValue.invoke(AstValue.java:157)
> >> at
> >> com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:283)
> >> at
> >> javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(
> MethodBindingMethodExpressionAdapter.java:71)
> >>
> >> at com.sun.faces.application.ActionListenerImpl.processAction
> >> (ActionListenerImpl.java:96)
> >> at javax.faces.component.UICommand.broadcast(UICommand.java:383)
> >> at
> >> javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:471)
> >> at javax.faces.component.UIViewRoot.processApplication
> >> (UIViewRoot.java:783)
> >> at
> >> com.sun.faces.lifecycle.InvokeApplicationPhase.execute(
> InvokeApplicationPhase.java:97)
> >>
> >> at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:244)
> >> at com.sun.faces.lifecycle.LifecycleImpl.execute
> >> (LifecycleImpl.java:113)
> >> at javax.faces.webapp.FacesServlet.service(FacesServlet.java:244)
> >> at
> >> org.apache.catalina.core.ApplicationFilterChain.servletService(
> ApplicationFilterChain.java:397)
> >>
> >> at org.apache.catalina.core.StandardWrapperValve.invoke
> >> (StandardWrapperValve.java:278)
> >> at
> >> org.apache.catalina.core.StandardPipeline.doInvoke(
> StandardPipeline.java:586)
> >>
> >> at
> >> org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java
> :556)
> >>
> >> at org.apache.catalina.core.StandardContextValve.invokeInternal
> >> (StandardContextValve.java:246)
> >> at
> >> org.apache.catalina.core.StandardContextValve.invoke(
> StandardContextValve.java:185)
> >>
> >> at
> >> org.apache.catalina.core.StandardPipeline.doInvoke(
> StandardPipeline.java:586)
> >>
> >> at com.sun.enterprise.web.WebPipeline.invoke (WebPipeline.java:73)
> >> at
> >> org.apache.catalina.core.StandardHostValve.invoke(
> StandardHostValve.java:182)
> >>
> >> at
> >> org.apache.catalina.core.StandardPipeline.doInvoke(
> StandardPipeline.java:586)
> >>
> >> at com.sun.enterprise.web.VirtualServerPipeline.invoke
> >> (VirtualServerPipeline.java:120)
> >> at
> >> org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:939)
> >> at
> >> org.apache.catalina.core.StandardEngineValve.invoke(
> StandardEngineValve.java:137)
> >>
> >> at org.apache.catalina.core.StandardPipeline.doInvoke
> >> (StandardPipeline.java:586)
> >> at
> >> org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java
> :556)
> >>
> >> at
> >> org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:939)
> >> at org.apache.coyote.tomcat5.CoyoteAdapter.service
> >> (CoyoteAdapter.java:231)
> >> at
> >>
> com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter
> (DefaultProcessorTask.java:619)
> >>
> >> at
> >>
> com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.processNonBlocked
> >> (DefaultProcessorTask.java:550)
> >> at
> >> com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(
> DefaultProcessorTask.java:780)
> >>
> >> at
> >>
> com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask
> >> (DefaultReadTask.java:326)
> >> at
> >> com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(
> DefaultReadTask.java:251)
> >>
> >> at
> >> com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(
> DefaultReadTask.java:205)
> >>
> >> at
> >> com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java
> :252)
> >> at
> >> com.sun.enterprise.web.connector.grizzly.WorkerThreadImpl.run(
> WorkerThreadImpl.java:103)
> >>
> >> Caused by: com.yaps.petstore.exception.* ValidationException*:
> >> Invalid first name
> >> at com.yaps.petstore.domain.customer.Customer.validateData(Unknown
> >> Source)
> >> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> >> at sun.reflect.NativeMethodAccessorImpl.invoke
> >> (NativeMethodAccessorImpl.java:39)
> >> at
> >> sun.reflect.DelegatingMethodAccessorImpl.invoke(
> DelegatingMethodAccessorImpl.java:25)
> >>
> >> at java.lang.reflect.Method.invoke(Method.java:585)
> >> at
> >>
> oracle.toplink.essentials.internal.security.PrivilegedAccessHelper.invokeMethod
> >> (PrivilegedAccessHelper.java:307)
> >> at
> >>
> oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener.invokeMethod
> (MetadataEntityListener.java:302)
> >>
> >> at
> >>
> oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityClassListener.invokeMethod
> >> (MetadataEntityClassListener.java:69)
> >> at
> >>
> oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener.prePersist
> (MetadataEntityListener.java:439)
> >>
> >> at
> >>
> oracle.toplink.essentials.descriptors.DescriptorEventManager.notifyListener
> >> (DescriptorEventManager.java:658)
> >> at
> >>
> oracle.toplink.essentials.descriptors.DescriptorEventManager.notifyEJB30Listeners
> (DescriptorEventManager.java:601)
> >>
> >> at
> >>
> oracle.toplink.essentials.descriptors.DescriptorEventManager.executeEvent
> >> (DescriptorEventManager.java:199)
> >> at
> >>
> oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.registerNotRegisteredNewObjectForPersist
> (UnitOfWorkImpl.java:3226)
> >>
> >> at
> >>
> oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.registerNotRegisteredNewObjectForPersist
> >> (RepeatableWriteUnitOfWork.java:298)
> >> at
> >>
> oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist
> (UnitOfWorkImpl.java:3186)
> >>
> >> at
> >>
> oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerImpl.persist
> >> (EntityManagerImpl.java:170)
> >> at
> >> com.sun.enterprise.util.EntityManagerWrapper.persist(
> EntityManagerWrapper.java:433)
> >>
> >> at
> >> com.yaps.petstore.service.customer.CustomerBean.createCustomer(Unknown
> >> Source)
> >> at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
> >> at
> >> sun.reflect.NativeMethodAccessorImpl.invoke(
> NativeMethodAccessorImpl.java:39)
> >>
> >> at
> >> sun.reflect.DelegatingMethodAccessorImpl.invoke(
> DelegatingMethodAccessorImpl.java:25)
> >>
> >> at java.lang.reflect.Method.invoke (Method.java:585)
> >> at
> >> com.sun.enterprise.security.application.EJBSecurityManager.runMethod(
> EJBSecurityManager.java:1050)
> >>
> >> at
> >> com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:165)
> >> at com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod
> >> (BaseContainer.java:2788)
> >> at
> >> com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:3870)
> >> at
> >> com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(
> EJBLocalObjectInvocationHandler.java:184)
> >>
> >> ... 43 more
> >>
> >> I am confused because on the EJB specification this is what's written :
> >>
> >> 14.1.1 Application Exceptions
> >>
> >> An application exception may be a subclass (direct or indirect) of
> >> java.lang.Exception (i.e., a "checked exception"), or an application
> >> exception class may be defined as a subclass of the
> >> java.lang.RuntimeException (an "unchecked exception")
> >>
> >> 14.1.2 Goals for Exception Hand
> >>
> >> An application exception thrown by an enterprise bean instance should
> >> be reported to the client precisely (i.e., the client gets the same
> >> exception)
> >>
> >> 14.2.1 Application Exceptions
> >>
> >> An application exception that is an unchecked exception is defined as
> >> an application exception by annotating it with the
> >> applicationException metadata annotation.
> >>
> >> Thanks for your help,
> >>
> >>
> >>
> >> Antonio
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: ejb-unsubscribe_at_glassfish.dev.java.net
> > For additional commands, e-mail: ejb-help_at_glassfish.dev.java.net
> >
>
>
>
>