ejb@glassfish.java.net

Re: Application Exception being wrapped into EJBException

From: Cheng Fang <Cheng.Fang_at_Sun.COM>
Date: Mon, 02 Oct 2006 09:36:52 -0400

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.

Throwing such runtime exception from @PrePersist seems a pretty common
use case. The JPA spec has such an example. Can someone clarify?

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