[hibernate-commits] Hibernate SVN: r20803 - in search/trunk/hibernate-search/src: test/java/org/hibernate/search/test/engine and 1 other directory.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Mon Oct 11 14:18:15 EDT 2010


Author: epbernard
Date: 2010-10-11 14:18:15 -0400 (Mon, 11 Oct 2010)
New Revision: 20803

Added:
   search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/engine/TransactionSynchronizationTest.java
Modified:
   search/trunk/hibernate-search/src/main/java/org/hibernate/search/backend/impl/EventSourceTransactionContext.java
Log:
HSEARCH-606 Do not register for tx synchronization on local tx

When the transaction is local (ie the TransactionManager is null - not great but I don't have a better approach atm), avoid registering the Synchronization event to the transaction and exclusively use the actionQueue.registerProcess.

Modified: search/trunk/hibernate-search/src/main/java/org/hibernate/search/backend/impl/EventSourceTransactionContext.java
===================================================================
--- search/trunk/hibernate-search/src/main/java/org/hibernate/search/backend/impl/EventSourceTransactionContext.java	2010-10-11 15:00:05 UTC (rev 20802)
+++ search/trunk/hibernate-search/src/main/java/org/hibernate/search/backend/impl/EventSourceTransactionContext.java	2010-10-11 18:18:15 UTC (rev 20803)
@@ -27,6 +27,7 @@
 import java.io.Serializable;
 import javax.transaction.Status;
 import javax.transaction.Synchronization;
+import javax.transaction.TransactionManager;
 
 import org.slf4j.Logger;
 
@@ -92,12 +93,19 @@
              * In a JTA env, the before transaction completion is called before the flush, so not all changes are yet
              * written. However, Synchronization-s do propagate exceptions, so they can be safely used.
              */
-
 			final ActionQueue actionQueue = eventSource.getActionQueue();
-			actionQueue.registerProcess( new DelegateToSynchronizationOnBeforeTx( synchronization ) );
-			eventSource.getTransaction().registerSynchronization(
-					new BeforeCommitSynchronizationDelegator( synchronization )
-			);
+			boolean isLocal = isLocalTransaction();
+			if ( isLocal ) {
+				//if local tx never use Synchronization
+				actionQueue.registerProcess( new DelegateToSynchronizationOnBeforeTx( synchronization ) );
+			}
+			else {
+				//TODO could we remove the action queue registration in this case?
+				actionQueue.registerProcess( new DelegateToSynchronizationOnBeforeTx( synchronization ) );
+				eventSource.getTransaction().registerSynchronization(
+						new BeforeCommitSynchronizationDelegator( synchronization )
+				);
+			}
 
 			//executed in all environments
 			actionQueue.registerProcess( new DelegateToSynchronizationOnAfterTx( synchronization ) );
@@ -116,7 +124,13 @@
 			}
 		}
 	}
-	
+
+	private boolean isLocalTransaction() {
+		//TODO make it better but I don't know how we can optimize it.
+		final TransactionManager transactionManager = eventSource.getFactory().getTransactionManager();
+		return transactionManager == null;
+	}
+
 	private FullTextIndexEventListener getIndexWorkFlushEventListener() {
 		if ( this.flushListener != null) {
 			//for the "transient" case: might have been nullified.

Added: search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/engine/TransactionSynchronizationTest.java
===================================================================
--- search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/engine/TransactionSynchronizationTest.java	                        (rev 0)
+++ search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/engine/TransactionSynchronizationTest.java	2010-10-11 18:18:15 UTC (rev 20803)
@@ -0,0 +1,67 @@
+package org.hibernate.search.test.engine;
+
+import org.hibernate.Transaction;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.FieldBridge;
+import org.hibernate.search.annotations.Indexed;
+import org.hibernate.search.bridge.builtin.ClassBridge;
+import org.hibernate.search.test.SearchTestCase;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class TransactionSynchronizationTest extends SearchTestCase {
+
+	public void testProperExceptionPropagation() throws Exception {
+		/**
+		 * This test relies on the fact that a bridge accepting an incompatible type raise
+		 * an exception when used.
+		 */
+		FullTextSession fts = Search.getFullTextSession( openSession() );
+		boolean raised = false;
+		final Transaction transaction = fts.beginTransaction();
+		try {
+			Test test = new Test();
+			test.setIncorrectType("not a class");
+			fts.persist(test);
+			transaction.commit();
+			fail("An exception should have been raised");
+		}
+		catch (Exception e) {
+			//good
+			raised = true;
+			transaction.rollback();
+		}
+		assertTrue("An exception should have been raised", raised);
+		fts.close();
+	}
+
+	@Override
+	protected Class<?>[] getAnnotatedClasses() {
+		return new Class<?>[] {
+				Test.class
+		};
+	}
+
+	@Entity
+	@Indexed
+	@Table(name="Test007")
+	public static class Test {
+		@Id @GeneratedValue
+		public Integer getId() { return id; }
+		public void setId(Integer id) { this.id = id; }
+		private Integer id;
+
+		@Field(bridge = @FieldBridge(impl = ClassBridge.class))
+		public String getIncorrectType() { return incorrectType; }
+		public void setIncorrectType(String incorrectType) { this.incorrectType = incorrectType; }
+		private String incorrectType;
+	}
+}



More information about the hibernate-commits mailing list