persistence@glassfish.java.net

Re: EJB 3 and JPA Exception Handling

From: Mitesh Meswani <Mitesh.Meswani_at_Sun.COM>
Date: Mon, 02 Oct 2006 12:03:27 -0700

Mahesh.Kannan wrote:
> CCing persistnce team.
>
> Butash, Bob wrote:
>
>> All,
>>
>> I have a question regarding Exception Handling regarding JPA code.
>> Here is my Scenario:
>>
>> I have a JSF backing bean that is invoking a business service via a
>> JNDI lookup through the service locator pattern.
>>
>> public String registerNewUser() throws SystemUserException,
>> Exception
>> {
>> SystemUser user = (SystemUser)getManagedBeanValue("user")
>> obtainSystemUserService().addSystemUser(user);
>> user.setPassword(null);
>>
>> UserState userState =
>> (UserState)getManagedBeanValue("userState");
>> userState.setUser(retrieveSystemUser());
>> userState.setLoggedIn(true);
>> return "success";
>> }
>>
>> I have a Local Stateless Session Bean that is acting as a Business
>> Service. The saveObject method is annotated to require a
>> transaction. It delegates to another Local Stateless Session bean
>> that is acting as the DAO. It merely throws any application
>> exceptions that are thrown from the DAO.
>>
>> @TransactionAttribute(TransactionAttributeType.SUPPORTED)
>> public Object addSystemUser(SystemUser user) throws
>> SystemUserServiceException
>> {
>> return getSystemUserDAO().persistEntity(user);
>> }
>>
>>
>> The Local DAO Stateless Session Bean's method annotated to require a
>> transaction. This method is invoking the EntityManager to perform
>> the persist. The call to the persist is surrounded with a try catch
>> to attempt to catch an exception during the persist and wrap it in an
>> Application exception.
>> @TransactionAttribute(TransactionAttributeType.REQUIRED)
>> public SystemUser persistEntity(SystemUser entity)
>> {
>> try
>> {
>> return (SystemUser)super.persistEntity(entity);
>> }
>> catch(Exception e)
>> {
>> throw new SystemUserException("Duplicate user");
>> }
>> }
>>
>>
>> However, if there is an error the catch is not hit and no exception
>> processing is encountered until the stack is back at the POJO JSF
>> backing bean and at that point I am catching an EJBException.
>>
> You may add a System.out.println() in your catch (Exception e) block
> to be sure that you got an exception. May be you are getting the
> exception when the Tx completes.
Hi Bob,

Looks like you want to catch the exception when entity is written to
database. Mahesh is correct. The changes will not be written to database
immediately in response to em.persist(). It will be written when the
transaction completes. One way around it is to call em.flush()
immediately following super.persistEntity(entity) above. It will force
the changes to be written to database.

Thanks,
Mitesh
>
>> I have tried placing try catches at the Business Service Tier as well
>> as I have an EJB interceptor that is wrapping the call to the
>> context.proceed with a try/catch. The only time I can actually catch
>> the EJBException is when I'm out of the transactional processing,
>> which is the POJO backing bean. I have noticed if I change the
>> transactional control on the Business Service method to be
>> NOT_SUPPORTED I can catch the exception at that point, but that means
>> if this was part of a more complex tranasaction all of my
>> transactional control would be lost.
>>
>> Is there a way to catch Exceptions thrown from the
>> EntityManager.persist() and wrap them in a meaningful
>> ApplicationException?
>>
>> Thanks for your assistance
>>
>> Bob Butash
>>
>>
>>