Hibernate Validator Exceptions - java

I'm using Hibernate Validator in an application with EJB and Spring MVC. I'm using JBoss 5, Hibernate 3 and Spring MVC version 3.
I'd like to try and catch validation exceptions at Spring Exception Resolver level and generate an error message based on the InvalidStateException message. I don't want to put exception handling logic in the data access layer; I want this to be driven by annotations and just handle the validation errors in one centralized place.
The domain model is being correctly verified and an exception of type InvalidStateException is thrown as expected when I try to create an invalid entity (e.g. violate a length constraint on a field). At the point of trying to catch the exception in my instance of a Spring Exception resolver, I find my original exception has disappeared and a javax.ejb.EJBTransactionRolledbackException has taken its place. The original exception is not in the caused by list.
My first guess was that org.hibernate.validator.InvalidStateException wasn't annotated with ApplicationException, so I installed a Hibernate event listener, caught the original exception and rethrew it as a new exception annotated with ApplicationException. This has no effect.
One further complexity is that the web tier is calling EJBs via a Remote interface. I annotated my exception class with WebFault, but to no avail.
What should I do to ensure the exception bubbles all the way up?

Try this?
protected InvalidStateException extractValidationException(Throwable ex) {
Throwable e = ex;
while (e != null) {
if (e instanceof InvalidStateException) {
return (ValidationException) e;
} else if (e instanceof EJBException) {
e = ((EJBException) e).getCausedByException();
} else {
e = e.getCause();
}
}
return null;
}

Related

Does Spring handle Hibernate NonUniqueObjectException?

I'm using Spring MVC to write a RESTful web service, with a database back-end. My save routine is wrapped in a try/catch ...
private void saveData() {
try {
service.saveReport(xmlData);
}
catch(DataAccessException e) { // Spring's DataAccessException
throw new MyException();
}
}
which works for DB errors like a unique constraint violation for instance.
But I'm getting Hibernate's NonUniqueObjectException currently, due to a bug in my code.
I'm curious however, why doesn't Spring's DataAccessException "catch" the NonUniqueObjectException? Is there another Spring Exception which I should use (in addition to DataAccessException) to "catch" this Hibernate Exception?
Or I can certainly catch the Hibernate exception myself. But I didn't know if Spring would/could.
UPDATE -------
My service.save(xmlData) actually does more than just "save" but first does some processing, copying the XML data into the correct (list of) #Entity beans, then looping through the Entity beans, saving each one. The Hibernate Exception occurs during setting up the Entity beans themselves, not during the actual dao.save(entityBean).
Thanks!
Chris
Your DAO neeeds to be proxied to allow for Spring automatic exception translation. Either add the #Repository annotation to your DAO or explictly configure a PersistenceExceptionTranslationPostProcessor bean post processor to your configuration

Getting complete stack trace from application while using Transactional annotation

I am using spring Transactional annotation which is overriding custom exception:
Application exception overriden by commit exception
lets say
#Transactional
method A() {
try {
} catch (MyException e) {
throw MyException(e.getMessage, e);
}
}
Now exception I got from code which is calling A is transaction rollback exception.
I want exact exception thrown by code, but Apache ExceptionUtils.getRootCause is returning transaction rollback messages which doesn't clarify anything.
How can I propagate exact application exception to caller method in this case?

Difference between RuntimeException and Exception with #ApplicationException(rollback=true) in EJB container

I call account EJB method in JSF bean like that :
try{
account.someFunction(...);
}catch(SimRuntimeException e){
logger.log(Level.FATAL, "SimRuntimeException catched !");
}catch(SimNotRuntimeException e){
logger.log(Level.FATAL, "SimNotRuntimeException catched !");
}catch(Exception e){
logger.log(Level.FATAL, "Exception catched !");
}
My Exceptions :
public class SimRuntimeException extends RuntimeException {
public SimRuntimeException() {
super();
}
}
#ApplicationException(rollback=true)
public class SimNotRuntimeException extends Exception {
public SimNotRuntimeException() {
super();
}
}
when account.someFunction(...); throws SimRuntimeException I fall
into Exception block because my SimRuntimeException is wrapped
into EJBException probably by EJB container.
when account.someFunction(...); throws SimNotRuntimeException I fall as expected
into SimNotRuntimeException
So, what is concretely the difference between Exception with #ApplicationException(rollback=true) and RuntimeException please ?
Pal's blog states:
EJB makes a difference in Application Exceptions and System Exceptions. Application exception is something that you define, you throw, and you are aware of. By default the application exception does not cause a rollback, unless you define it that way (and I think it's recommended). Every checked exception that is mentioned in the method signature and also any checked or unchecked exception that is annotated with #ApplicationException, is an application exception.
System exceptions happen in cases, you don't control, and they are unchecked exceptions. They always cause rollback. Good practice is, if you wrap checked exceptions -- that cannot be avoided -- in your method into EJBException e.g. ParseException.

Java - spring console application global exception handler

Java - spring - quartz application
I have Java application with spring 3.x which use quartz scheduler to process some data.
I was looking at the following article where they defined global Global Servlet container exception handler
I want to to configure spring to catch any exception occur into my application.
Above mentioned article uses "org.springframework.web.servlet.handler.HandlerExceptionResolverComposite" it is servlet speicfic implementation that's why i can't use it.
any help is appreciated.
You did not mention what you want to do when an exception is caught. If you just want to log the exception, you could use AOP for that.
A probably simpler solution would be to wrap your tasks with a class that catches the exception.
The class you mention is used in a catch block in the Spring MVC DispatcherServlet for matching specific Exceptions to handlers. AFAIK there isn't a class to do this out-of-the-box with vanilla Spring, but there's no reason you couldn't create a similar execution container for your app:
public interface ExceptionHandler {
public void handle(Exception e);
}
public class ExecutionEnvironment {
private Map<Class, ExceptionHandler> executionHandlers;
public void run() {
try {
// Your app code...
} catch (Exception e) {
if(executionHandlers.get(e.getClass()) != null) {
executionHandlers.get(e.getClass()).handle(e);
} else {
throw new RuntimeException(e);
}
}
}
}
Then use a context configuration to set up your exception handlers. Hope this helps.

EJB3 Getting at original JDBC Errors

I am using EJB3 on Glassfish using the default TopLink persistance manager. Within a Session Bean, when the persistence manager catches a DB exception, it marks the transaction to be rolled back, and throws an EJBException, in turn wrapping a RollbackException. Now I was expecting to be able to get the original jdbc exception out of the caused by exception of one of these exceptions, but it is not.
It is important that I do retrieve the original exception, as I need to report back to the users what the problem is, and to do this I need to analyse the SQL error codes.
Does anyone know if it is possible to get this information from Toplink? Or whether Hibernate makes it possible?
Thanks,
I had the same issue. I ended up using the AroundInvoke interceptor method , that way you can catch any exception on the server side , and extract whatever info you want to and wrap it to throw your own exception , and set the EjbContext to rollback the transaction.
I can provide you with an example if you don't come right.
Good question, Ant
I know you want to throw a database exception but when it occurs the application, in most of the time, is not able to restore its initial state or it does not know how to recover from it. So it should be handled as a runtime exception. Some problems in database exceptions includes
database connection failure
query is wrong
table or column does not exist
Above you see the application is not be able to restore its initial state. If you think it is possible restore its initial state so you should use a application exception. Client will get the same application exception thrown by your business method. If you want to be able to get the exact exception thrown by your business method you have two choices:
Use a business delegate pattern to access your EJB
As you know, runtime exception is wrapped by a EJBException, so you shold use something like
Let's suppose you have this Stateless session bean
#Stateless
public class BeanImpl implements Bean {
public void doSomething() {
try {
// some code
} catch(SomeException e) {
throw new EJBException(e);
}
}
}
So you wrap your session bean through a business delegate
public class BeamBusinessDelegate implements Bean {
// your stateless session bean goes here
private Bean bean;
public BeamImpl() {
InitialContext i = new InitialContext();
bean = (Bean) i.lookup(<GLOBAL_JNDI_ADDRESS_OR_RELATIVE_ENVIRONMENT_NAMING_CONTEXT_ADDRESS>);
}
public void doSomething() {
try {
bean.doSomething()
} catch(EJBException e) {
throw e.getCause();
}
}
}
Or you can extends EJBException according to your needs
public class DatabaseException extends EJBException {
}
So in your business method
#Stateless
public class BeanImpl implements Bean {
public void doSomething() {
try {
// some code
} catch(SomeException e) {
throw new DatabaseException();
}
}
}
regards,
The only way I've found to do what I want, is to force the manager to write to the db using manager.flush(), and then catch the PersistenceException that that throws. I can then log the database error as I want, and throw an EJBException to force rollback. Leaving the container to do the flush seems to irretrievably lose any useful messages with TopLink.
I have the same question : how to get the SQL error message generated from JPA?
I haven't found the solution either but, I added this line in my persistence.xml
<properties>
<property name="toplink.logging.level" value="FINE" />
</properties>
and now, I can see the sql commands issued.
Reference :
http://www.jairrillo.com/blog/2008/09/04/introduction-to-jpa-part-1-getting-started/

Categories