Friday, October 30, 2009

Constraint violated, transaction rolled back

When using bean validation on JPA entities within an EJB 3 bean you would actually get an EJBTransactionRolledbackException if there is a constraint violation.
javax.ejb.EJBTransactionRolledbackException: Invalid object at persist time for groups [javax.validation.groups.Default, ]
Caused by: javax.validation.ConstraintViolationException: Invalid object at persist time for groups [javax.validation.groups.Default, ]
This is all nicely according to specification, but not really interesting information. You don't really want to know what happened, you want to know what went wrong.

So I recommend adding the following to your ejb-jar.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
version="3.0">
<assembly-descriptor>
<application-exception>
<exception-class>javax.validation.ConstraintViolationException</exception-class>
<rollback>true</rollback>
</application-exception>
</assembly-descriptor>
</ejb-jar>
That way you can directly access your violations.

Exceptions should tell a story

So I was happily plumbing along to get bean validation to work in AS 5.2, when I got this client side:
org.jboss.serial.exception.SerializationException: Could not create instance of org.hibernate.validator.engine.ConstraintViolationImpl - org.hibernate.validator.engine.ConstraintViolationImpl
Caused by: java.lang.InstantiationException: org.hibernate.validator.engine.ConstraintViolationImpl
For some reason jboss-serialization was looking for a default constructor, which obviously wasn't there.

Now the most recent release showed ConstraintViolationImpl implementing Serializable, so I crossed that out as a problem. (I didn't realize at this point that I was using an old version, but that's not the point of this post. :-) )

Using the JDK serializer gave it away:
java.io.NotSerializableException: org.hibernate.validator.engine.ConstraintViolationImpl
At which point it was obvious that I was using the wrong version.

At the end of the day I only have a complaint about the exception in jboss-serialization. If it said something in lines of: "class is not serializable and has no default constructor" I would have been a happy camper.

So the moral is: always let an exception tell a story.

Tuesday, October 27, 2009

Remember: MC == Necromancer Magic

While working on EJBTHREE-1889 I stumbled right into an assumption boobytrap. In my mind I figured that a MicroContainer bean would have a state diagram as shown on the left side. In reality MC bean instances can be 'destroyed' and then 'created', because for MC it's just a state change with no additional semantics.

"Specifically the beans named in the @Depends or values will reach their CREATE states before the bean declaring the dependencies reaches its CREATE state. The same is true for the START, STOP and DESTROY states." [MC 12.3]

So MC is voodoo magic, it will resurrect your bean. :-)