1 Reply Latest reply on Jul 6, 2007 2:23 PM by Gavin King

    Transaction management in EntityHome subclass

    Mattias Bertelsen Newbie

      I have an entity with a two-field unique constraint. Due to not being able to write a validator that validates two fields of an entity at once (or am I wrong here?), I ended up subclassing the EntityHome in order to run my object-level validation before the superclass update() and persist() get called. However, because the instance entity is managed, and EntityHome uses the seam-managed persistence context and transaction management, by the time my code for validation runs, the managed entity has already been updated by JSF. So when I try to run a select query to determine if the two fields together are unique, hibernate is automatically flushing the write to the entity, which throws the EntityExistsException i'm trying to avoid.

      I ended up with the following solution, and would like to know if there's a better way:

      public class DatabaseServerHome extends EntityHome<DatabaseServer> {
       EntityManager entityManager;
       @In FacesMessages facesMessages;
       public EntityManager getEntityManager() {
       return entityManager;
       public DatabaseServer getInstance() {
       return super.getInstance();
      // ... (removed for clarity)
       public String update() {
       // set flush mode to COMMIT so that validateUnique can run a query to
       // check uniqueness without triggering a flush
       // This is required because we have a managed entity with dirty changes
       // (already applied by JSF) and now need to validate them after the
       // changes have been made
       if (validateUnique()) {
       return super.update();
       } else {
       return "invalid";
       protected boolean validateUnique() {
       DatabaseServer ds = getInstance();
       String existenceQuery = "select ds from DatabaseServer ds where ds.serverName = :serverName and ds.port = :port";
       try {
       DatabaseServer ds1 = (DatabaseServer) entityManager.createQuery(existenceQuery)
       .setParameter("serverName", ds.getServerName()).setParameter("port", ds.getPort()).getSingleResult();
       if (ds1 != null && !(ds1.getId().equals(ds.getId()))) {
       facesMessages.add(FacesMessage.SEVERITY_ERROR,"You cannot have two database servers with the same Name and Port");
       return false;
       } else {
       return true;
       } catch (NoResultException nre) {
       return true;

      One last minor annoyance is that Seam is adding a FacesMessage that reads "Transaction Failed" when it rolls back - how do I alter this behavior?