persistence@glassfish.java.net

Re: EJB 3 and JPA Exception Handling

From: Marina Vatkina <Marina.Vatkina_at_Sun.COM>
Date: Tue, 03 Oct 2006 15:46:47 -0700

Bob,

It can be complicated...

The persistence provider can throw an exception right away if it detects an
error in comparison with the known instances in the cache, or it can throw
an exception at commit (both cases are permitted by the spec).

In the 1st case, you'll never get a SQL exception, or any wrapper around it.
In the 2nd case, there is no guarantee how many wrappers each persistence
provider would add around the actual exception.

Also, keep in mind that the exception itself can be about anything else
(like e.g. wrong table name) as well.

And another problem that you observe - the commit processing that happens
only when the *container* transaction commits, i.e. only the client would
know that there is something wrong that happened with the request.

Your safest approach would be to check yourself first, by calling find
or executing a query, if that particular constraint is not part of the PK.
The next one, is to try flush().

HTH,
-marina

Butash, Bob wrote:
> I have stepped through the code and when the EntityManager throws an
> exception due to an SQL issue, in my case a uniqueness constraint, the
> EJBException is thrown to the first class that is outside of the
> container managed transaction's control. I would like to catch the SQL
> Exception, or it's equivalent, and throw a meaningful application
> exception. I do not want to clutter my Model tier throwing
> EJBExceptions to the Client tier.
>
> Thanks
>
> -----Original Message-----
> From: Mahesh.Kannan_at_Sun.COM [mailto:Mahesh.Kannan_at_Sun.COM]
> Sent: Monday, October 02, 2006 2:36 PM
> To: ejb_at_glassfish.dev.java.net
> Cc: persistence_at_glassfish.dev.java.net
> Subject: Re: EJB 3 and JPA Exception Handling
>
> 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.
>
>
>>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
>>
>>
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: ejb-unsubscribe_at_glassfish.dev.java.net
> For additional commands, e-mail: ejb-help_at_glassfish.dev.java.net