Project

General

Profile

« Previous | Next » 

Revision 35726797

Added by Niels Hoffmann almost 15 years ago

fixed an issue with pring not correctly handling the datasource after a transaction

View differences:

cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/conversation/ConversationHolder.java
3 3
 */
4 4
package eu.etaxonomy.cdm.api.conversation;
5 5

  
6
import java.util.Map;
7

  
6 8
import javax.sql.DataSource;
7 9

  
8 10
import org.apache.log4j.Logger;
......
20 22
import org.springframework.transaction.support.ResourceHolder;
21 23
import org.springframework.transaction.support.TransactionSynchronizationManager;
22 24

  
23
import eu.etaxonomy.cdm.persistence.hibernate.CdmPostCrudObservableListener;
25
import eu.etaxonomy.cdm.persistence.hibernate.CdmPostDataChangeObservableListener;
24 26

  
25 27
/**
26 28
 * This is an implementation of the session-per-conversation pattern for usage
......
46 48
	private PlatformTransactionManager transactionManager;
47 49

  
48 50

  
51
	
49 52
	/**
50 53
	 * The persistence context for this conversation
51 54
	 */
......
86 89
	 */
87 90
	public void bind() {
88 91
		
89

  
90
		if(TransactionSynchronizationManager.hasResource(getSessionFactory())){
91
			TransactionSynchronizationManager.unbindResource(getSessionFactory());
92
		}
93

  
94
		/*
95
		 * FIXME it is a rather strange behaviour that HibernateTransactionManager 
96
		 * binds a dataSource and then complains about that later on. At least that 
97
		 * is what happens in the editor.
98
		 * 
99
		 *  With this in the code the tests will not run, but the editor for now.
100
		 * 
101
		 */
102
//		if(TransactionSynchronizationManager.hasResource(getDataSource())){
103
//			TransactionSynchronizationManager.unbindResource(getDataSource());
104
//		}
105
	
92
		logger.info("Binding resources for ConversationHolder: [" + this + "]");	
106 93
		
107 94
		if(TransactionSynchronizationManager.isSynchronizationActive()){
108 95
			TransactionSynchronizationManager.clearSynchronization();
109 96
		}
110

  
111
		
112
		logger.info("Binding resources for ConversationHolder: [" + this + "]");
113 97
		
114
		// lazy creation of session
115
		if (longSession == null) {
116
			longSession = SessionFactoryUtils.getNewSession(getSessionFactory());
117
			longSession.setFlushMode(FlushMode.MANUAL);
118

  
119
			// TODO set the ConnectionReleaseMode to AFTER_TRANSACTION, possibly in applicationContext
98
		try{
99
			// FIXME for debugging -> remove
100
			Map resourceMap = TransactionSynchronizationManager.getResourceMap();
120 101
			
121
			logger.info("Creating Session: [" + longSession + "]");
122
		}
102
			
103
			logger.info("Starting new Synchronization in TransactionSynchronizationManager.");
104
			TransactionSynchronizationManager.initSynchronization();
105
			
106
			if(TransactionSynchronizationManager.hasResource(getSessionFactory())){
107
				TransactionSynchronizationManager.unbindResource(getSessionFactory());
108
			}
109
			
110
			logger.info("Binding Session to TransactionSynchronizationManager.");
111
			TransactionSynchronizationManager.bindResource(getSessionFactory(), getSessionHolder());
112
			
113
		}catch(Exception e){
114
			logger.error("Error binding resources for session", e);
115
		}			
123 116
		
124

  
125
		// lazy creation of session holder
126
		if(sessionHolder == null){
127
			sessionHolder = new SessionHolder(longSession);
117
	}
118
	
119
	public SessionHolder getSessionHolder(){
120
		if(this.sessionHolder == null){
128 121
			logger.info("Creating SessionHolder: [" + sessionHolder + "]");
122
			this.sessionHolder = new SessionHolder(getSession());
129 123
		}
130
		
131
		// connect dataSource with session
132
		if (!longSession.isConnected()){
133
			
134
			longSession.reconnect(DataSourceUtils.getConnection(dataSource));
135
			logger.info("Reconnecting DataSource: [" + dataSource + "]" );
136
		}
137
		
138
		
139
		logger.info("Binding Session to TransactionSynchronizationManager.");
140
		TransactionSynchronizationManager.bindResource(getSessionFactory(), sessionHolder);
141

  
142
		logger.info("Starting new Synchronization in TransactionSynchronizationManager.");
143
		TransactionSynchronizationManager.initSynchronization();
144
		
145
		
124
		return this.sessionHolder;
146 125
	}
147 126
	
127
	
128
	
148 129
	/**
149 130
	 * @return
150 131
	 */
151
	private DataSource getDataSource() {
132
	public DataSource getDataSource() {
152 133
		return this.dataSource;
153 134
	}
154 135

  
......
171 152
			logger.warn("We allow only one transaction at the moment but startTransaction " +
172 153
					"was called a second time.\nReturning the transaction already associated with this " +
173 154
					"ConversationManager");
174
		}else{	
155
		}else{				
175 156
			transactionStatus = transactionManager.getTransaction(definition);
176

  
177 157
			
178 158
			logger.info("Transaction started: [" + transactionStatus + "]");
179 159
		}
......
205 185
			
206 186
			// commit the changes
207 187
			transactionManager.commit(transactionStatus);
208
						
188
			
189
			// propagate transaction end
190
			CdmPostDataChangeObservableListener.getDefault().delayedNotify();	
191
			
209 192
			// Reset the transactionStatus.
210 193
			transactionStatus = null;
211 194
			
......
235 218
	 * @return the session associated with this conversation manager 
236 219
	 */
237 220
	public Session getSession() {
221
		if(longSession == null){
222
			logger.info("Creating Session: [" + longSession + "]");
223
			longSession = SessionFactoryUtils.getNewSession(getSessionFactory());
224
			longSession.setFlushMode(FlushMode.MANUAL);
225
		}
226
		
227
		// connect dataSource with session
228
		if (!longSession.isConnected()){
229
			longSession.reconnect(DataSourceUtils.getConnection(getDataSource()));
230
			logger.info("Reconnecting DataSource: [" + dataSource + "]" );
231
		}
232
		
238 233
		return longSession;
239 234
	}
240 235
	
......
274 269
	 * Register to get updated after any interaction with the datastore
275 270
	 */
276 271
	public void registerForDataStoreChanges(IConversationEnabled observer) {
277
		CdmPostCrudObservableListener.getDefault().register(observer);
272
		CdmPostDataChangeObservableListener.getDefault().register(observer);
278 273
	}
279 274
}
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/conversation/IConversationEnabled.java
9 9

  
10 10
package eu.etaxonomy.cdm.api.conversation;
11 11

  
12
import eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver;
12
import eu.etaxonomy.cdm.persistence.hibernate.ICdmPostDataChangeObserver;
13 13

  
14 14

  
15 15
/**
......
19 19
 * @created 17.03.2009
20 20
 * @version 1.0
21 21
 */
22
public interface IConversationEnabled extends ICdmPostCrudObserver {
22
public interface IConversationEnabled extends ICdmPostDataChangeObserver {
23 23
	
24 24
	/** 
25 25
	 * @return the conversation holder
cdmlib-services/src/test/java/eu/etaxonomy/cdm/test/function/TestConcurrentSession.java
357 357
	public void testProofOfDataPersistency(){
358 358
		// first conversation
359 359
		conversationHolder1.bind();
360
		TransactionStatus txStatusOne = transactionManager.getTransaction(definition);
360
		conversationHolder1.startTransaction();
361 361
		// get a taxon
362 362
		TaxonBase taxonBase = taxonService.getTaxonByUuid(taxonUuid1);
363 363
		// get a reference
......
368 368
		taxonBase.setSec(reference);
369 369
		// save and commit
370 370
		taxonService.save(taxonBase);
371
		transactionManager.commit(txStatusOne);
371
		conversationHolder1.commit();
372 372
		
373 373
		
374 374
		// second conversation
375 375
		conversationHolder2.bind();
376
		TransactionStatus txStatusTwo = transactionManager.getTransaction(definition);
376
		conversationHolder2.startTransaction();
377 377
		// load the same taxon in a different session
378 378
		TaxonBase taxonBaseInSecondTransaction = taxonService.getTaxonByUuid(taxonUuid1);
379 379
		// load the reference
......
479 479
		conversationHolder1.commit();		
480 480
	}
481 481
	
482
	@Test
483
	@DataSet("ConcurrentSessionTest.xml")
484
	public void testMultipleTransactionsInMultipleSessions(){
485
		conversationHolder1.bind();
486
		conversationHolder1.startTransaction();
487
		
488
		conversationHolder2.bind();
489
		conversationHolder2.startTransaction();
490
		
491
		conversationHolder3.bind();
492
		conversationHolder3.startTransaction();
493
	}
494
	
495
	
482 496
	@Test
483 497
	@DataSet("ConcurrentSessionTest.xml")
484 498
	public void testInsert(){
cdmlib-services/src/test/java/eu/etaxonomy/cdm/test/function/TestConversationEnabled.java
10 10

  
11 11
package eu.etaxonomy.cdm.test.function;
12 12

  
13
import java.util.List;
13 14
import java.util.Observable;
14 15

  
15 16
import org.apache.log4j.Logger;
16 17

  
17 18
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
18 19
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
19
import eu.etaxonomy.cdm.persistence.hibernate.CdmCrudEvent;
20
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeEvent;
20 21

  
21 22
/**
22
 * @author nho
23
 * @author n.hoffmann
23 24
 * @created 25.03.2009
24 25
 * @version 1.0
25 26
 */
......
40 41
	/* (non-Javadoc)
41 42
	 * @see eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu.etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
42 43
	 */
43
	public void update(CdmCrudEvent event) {
44
		logger.warn("CdmCrudEvent fired: " + event.getEventType() + " : " + event.getEntity());
44
	public void update(List<CdmDataChangeEvent> events) {
45
		for(CdmDataChangeEvent event : events){
46
			logger.warn("CdmCrudEvent fired: " + event.getEventType() + " : " + event.getEntity());
47
		}
45 48
	}
46 49

  
47 50
	/* (non-Javadoc)
cdmlib-services/src/test/resources/eu/etaxonomy/cdm/applicationContext-test.xml
13 13
 	<context:component-scan base-package="eu/etaxonomy/cdm/api"/>
14 14
    
15 15
    <!-- enable the configuration of transactional behavior based on annotations -->
16
<!--    <tx:annotation-driven transaction-manager="transactionManager"/>      -->
17
  
18
  	<bean id="conversationHolder" class="eu.etaxonomy.cdm.api.conversation.ConversationHolder" scope="prototype"/>
19
	
20

  
16
    <tx:annotation-driven transaction-manager="transactionManager"/>      
17
  
21 18
    <bean id="dataSource" class="org.unitils.database.UnitilsDataSourceFactoryBean"/>
22 19
    
23 20
    <bean id="hibernateProperties" 

Also available in: Unified diff