[jboss-user] [JBoss Seam] - Transaction management in EntityHome subclass

mbertelsen do-not-reply at jboss.com
Fri Jul 6 12:20:42 EDT 2007


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:


  | @Name("databaseServerHome")
  | public class DatabaseServerHome extends EntityHome<DatabaseServer> {
  | 	@In
  | 	EntityManager entityManager;
  | 	
  | 	@In FacesMessages facesMessages;
  | 
  | 	@Override
  | 	public EntityManager getEntityManager() {
  | 		return entityManager;
  | 	}
  | 
  | 	@Override
  | 	@Factory("databaseServer")
  | 	public DatabaseServer getInstance() {
  | 		return super.getInstance();
  | 	}
  | 
  | // ... (removed for clarity)
  | 
  | 	@Override
  | 	@Rollback(ifOutcome="invalid")
  | 	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
  | 		getEntityManager().setFlushMode(FlushModeType.COMMIT); 
  | 		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?

Thanks!

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4061382#4061382

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4061382



More information about the jboss-user mailing list