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