[jboss-svn-commits] JBL Code SVN: r28146 - in labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943: spec/entitymanager and 1 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Fri Jul 17 10:21:59 EDT 2009
Author: whitingjr
Date: 2009-07-17 10:21:59 -0400 (Fri, 17 Jul 2009)
New Revision: 28146
Modified:
labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/entitymanager/STMEntityManagerFactoryImpl.java
labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/spec/entitymanager/STMEntityManagerFactory.java
labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/persistence/STMPersistenceProviderImpl.java
Log:
Updated factory and provider classes.
Made the factory thread safe.
Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/entitymanager/STMEntityManagerFactoryImpl.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/entitymanager/STMEntityManagerFactoryImpl.java 2009-07-17 14:21:19 UTC (rev 28145)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/entitymanager/STMEntityManagerFactoryImpl.java 2009-07-17 14:21:59 UTC (rev 28146)
@@ -10,7 +10,6 @@
import java.util.concurrent.atomic.AtomicBoolean;
import javax.naming.InitialContext;
-import javax.naming.NameAlreadyBoundException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
@@ -25,7 +24,7 @@
import uk.ac.ncl.sdia.a8905943.stm.persistence.STMPersistenceProviderImpl;
/**
- * This object is responsible for choosing the transactional type, creating a persistence contxt, entity manager
+ * This object is responsible for validating the transactional type, creating a persistence context, entity manager
* and providing the entity manager with the persistence context.
* This implemenation creates a new instance of EntityManager for each request.
* This factory will bind an object to the JNDI tree and remove it when asked to close.
@@ -43,13 +42,17 @@
* EntityManager is created. Use it and treat it as read only.*/
private volatile Map properties ;
private static final Logger logger = Logger.getLogger(STMEntityManagerFactoryImpl.class);
- // this field is an enum field
+ // enum field to indicate the type.
private volatile PersistenceUnitTransactionType transactionType ;
// immutable field
+ //TODO this field cannot be static, refactor necessary
private volatile static IsolationLevel isolationLevel ;
private volatile boolean isOpen = true;
- private volatile STMPersistenceContext persistenceContext;
- private volatile String persistenceContextName;
+ /* The peristence context is shared amongst threads so the instance here still
+ * requires concurrent access controll.*/
+ private ThreadLocal<STMPersistenceContext> persistenceContext = new ThreadLocal<STMPersistenceContext>();
+ private ThreadLocal<String> persistenceContextName = new ThreadLocal<String>();
+
private AtomicBoolean isPCnotBoundToJNDI = new AtomicBoolean(false);
private static final String ERROR_MISSING_ISOLATION_LEVEL_PROPERTY = "Problem occured when creating an EntityManager. ISOLATION_LEVEL not configured.";
@@ -59,7 +62,6 @@
private static final String ERROR_EMPTY_ISOLATION_LEVEL_VALUE = "Empty isolation value.";
private static final String ERROR_NULL_PERSISTENCE_CONTEXT = "Persistence Context object is null and will cause a problem.";
private static final String ERROR_NULL_PERSISTENCE_CONTEXT_NAME = "Persistence name is and will cause a problem.";
- private static final String ERROR_FAILED_TO_BIND = "Failed to bind the persistence context to JNDI";
private static final String ERROR_FAILED_TO_UNBIND = "Failed to unbind the persistence context from JNDI";
private static final String WARN_PC_NOT_FOUND = "EntityManagerFactory attempted to unbind the Persistence Context and it could not be found.";
private static final String WARN_ALREADY_CLOSED = "EntityManagerFactory is already closed and is being closed again.";
@@ -75,7 +77,7 @@
try
{
InitialContext context = new InitialContext();
- context.unbind(getBindingName(persistenceContextName));
+ context.unbind(getBindingName(persistenceContextName.get()));
}
catch (NameNotFoundException nnfe)
{
@@ -162,25 +164,11 @@
{
logger.info(INFO_ATTEMPTING_PC_BIND);
}
- try
- {
- InitialContext context = new InitialContext();
- context.bind(this.persistenceContextName, this.persistenceContext);
- }
- catch (NameAlreadyBoundException nabe)
- {
- // this is acceptable
- }
- catch (NamingException ne)
- {
- isPCnotBoundToJNDI.compareAndSet(true, false);
- logger.error(ERROR_FAILED_TO_BIND, ne);
- throw new RuntimeException(ERROR_FAILED_TO_BIND);
- }
+
}
// allow the persistence context to escape
- return new STMEntityManagerImpl(this.persistenceContext);
+ return new STMEntityManagerImpl(this.persistenceContext.get());
}
@Override
@@ -191,12 +179,29 @@
/**
- * Create a new STMEntityManagerFactoryImpl. Needs initialising
+ * Create a new STMEntityManagerFactoryImpl. The initialization
+ * of this object relies on serialization by the caller. Use the
+ * {@link STMPersistenceProviderImpl} object to protect access.
*
*/
- public STMEntityManagerFactoryImpl()
+ public STMEntityManagerFactoryImpl(String persistenceName, STMPersistenceContext persistenceContext)
{
-
+ if (StringUtils.isNotBlank( persistenceName))
+ {
+ this.persistenceContextName.set( persistenceName);
+ }
+ else
+ {
+ logger.error(ERROR_NULL_PERSISTENCE_CONTEXT_NAME);
+ }
+ if (null != persistenceContext)
+ {
+ this.persistenceContext.set(persistenceContext);
+ }
+ else
+ {
+ logger.error(ERROR_NULL_PERSISTENCE_CONTEXT);
+ }
}
/**
@@ -238,33 +243,6 @@
return returnValue;
}
- /**
- * Initialise the factory object with persistence context details.
- *
- * @param persistenceName
- * @param persistenceContext
- */
- public void initialise(String persistenceName, STMPersistenceContext persistenceContext)
- {
- //TODO: this method is not thread safe, needs changing to make it safe
- if (StringUtils.isNotBlank( persistenceName))
- {
- this.persistenceContextName = persistenceName;
- }
- else
- {
- logger.error(ERROR_NULL_PERSISTENCE_CONTEXT_NAME);
- }
- if (null != persistenceContext)
- {
- this.persistenceContext = persistenceContext;
- }
- else
- {
- logger.error(ERROR_NULL_PERSISTENCE_CONTEXT);
- }
- }
-
private boolean notEmpty(Map map)
{
return !map.isEmpty();
@@ -286,4 +264,10 @@
{
throw new CloneNotSupportedException("Cloning of this object is not supported.");
}
+
+ @Override
+ public STMPersistenceContext getPersistenceContext()
+ {
+ return null;
+ }
}
Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/spec/entitymanager/STMEntityManagerFactory.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/spec/entitymanager/STMEntityManagerFactory.java 2009-07-17 14:21:19 UTC (rev 28145)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/spec/entitymanager/STMEntityManagerFactory.java 2009-07-17 14:21:59 UTC (rev 28146)
@@ -10,7 +10,9 @@
import javax.persistence.EntityManagerFactory;
+import uk.ac.ncl.sdia.a8905943.ejb3.persistence.STMPersistenceContext;
+
public interface STMEntityManagerFactory extends EntityManagerFactory, Serializable
{
-
+ public STMPersistenceContext getPersistenceContext();
}
Modified: labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/persistence/STMPersistenceProviderImpl.java
===================================================================
--- labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/persistence/STMPersistenceProviderImpl.java 2009-07-17 14:21:19 UTC (rev 28145)
+++ labs/jbosstm/workspace/whitingjr/trunk/MVCCSampleSTM/src/main/java/uk/ac/ncl/sdia/a8905943/stm/persistence/STMPersistenceProviderImpl.java 2009-07-17 14:21:59 UTC (rev 28146)
@@ -7,14 +7,17 @@
package uk.ac.ncl.sdia.a8905943.stm.persistence;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.naming.InitialContext;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NamingException;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.PersistenceUnitTransactionType;
import org.apache.log4j.Logger;
-import org.jgroups.annotations.GuardedBy;
import uk.ac.ncl.sdia.a8905943.ejb3.persistence.STMPersistenceContext;
import uk.ac.ncl.sdia.a8905943.entitymanager.STMEntityManagerFactoryImpl;
@@ -22,8 +25,12 @@
/**
* This object is responsible for creating an EntityManagerFactory for this
* provider STM system. This object is used by the container to create a factory
- * which in turn can create an EntityManager. There is the expectation of there
- * only being a single instance of the EMF in the JVM.
+ * which in turn can create an EntityManager. In a single JVM there can be multiple
+ * persistence contexts. A persistence context has only one EntityManagerFactory
+ * so ensure that concurrent threads access the correct persistence context and
+ * the EMF associated with it.
+ * This implementation relies on an EJB being allocated to a persistence context and
+ * for the full lifecycle of the thread the persistence context not changing.
*
* This implementation supports only:
* JTA transaction type
@@ -40,11 +47,13 @@
public static final String PROPERTY_JTA_DATASOURCE = "javax.persistence.jtaDataSource";
public static final String PROPERTY_PERSISTENCE_PROVIDER = "javax.persistence.provider";
public static final String PROPERTY_ISOLATION_LEVEL = "ISOLATION_LEVEL";
+ private static final String ERROR_FAILED_TO_BIND = "Failed to bind the persistence context to JNDI";
+ private static final String WARN_ALREADY_BOUND = "The STM persistence provider does not support application managed entity manager factory creation. Only containers can create this.";
+ private static final String PC_NAME= "java/PersistenceContext/";
- //TODO: jrw make factory a singleton
- @GuardedBy("this")
- private static final STMEntityManagerFactoryImpl factory = new STMEntityManagerFactoryImpl();
- private static final STMPersistenceContext context = new STMPersistenceContext();
+ //shared hashmap of factories, uniquness is based on persistence name
+ private final ConcurrentHashMap<String, STMEntityManagerFactoryImpl> factories = new ConcurrentHashMap<String, STMEntityManagerFactoryImpl>();
+ private final ConcurrentHashMap<String, STMPersistenceContext> contexts = new ConcurrentHashMap<String, STMPersistenceContext>();
@Override
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map)
@@ -67,10 +76,34 @@
{
throw new UnsupportedOperationException("Attempt to use resource-local persistence provider which is not supported. Only JTA is supported.");
}
- factory.initialise(info.getPersistenceUnitName(), this.context);
-
- returnValue = factory;
-
+ synchronized(this)
+ {
+ STMEntityManagerFactoryImpl factory = new STMEntityManagerFactoryImpl(info.getPersistenceUnitName(), new STMPersistenceContext());
+ final STMEntityManagerFactoryImpl concurrentValue = factories.putIfAbsent(info.getPersistenceUnitName(), factory);
+ // using the factory to indicate if this persistence provider has been 'initialised'
+ if (null == concurrentValue)
+ {// bind to jndi the persistence context
+ returnValue = factory;
+ try
+ {
+ InitialContext context = new InitialContext();
+ context.bind( getBindingName(info.getPersistenceUnitName()), factory.getPersistenceContext());
+ }
+ catch (NameAlreadyBoundException nabe)
+ {
+ logger.warn(WARN_ALREADY_BOUND);
+ }
+ catch (NamingException ne)
+ {
+ logger.error(ERROR_FAILED_TO_BIND, ne);
+ throw new RuntimeException(ERROR_FAILED_TO_BIND);
+ }
+ }
+ else
+ {// persistence context is already bound to jndi
+ returnValue = concurrentValue; // the factory instance created earlier in method is discarded
+ }
+ }
return returnValue;
}
@@ -79,9 +112,17 @@
{
if (true)
{
- throw new UnsupportedOperationException("The STM persistence provider does not support application managed entity manager factory creation. Only containers can create this.");
+ throw new UnsupportedOperationException();
}
return null;
}
-
+
+ public STMPersistenceProviderImpl()
+ {
+ }
+
+ private String getBindingName(String pcName)
+ {
+ return new StringBuffer().append(PC_NAME).append(pcName).toString();
+ }
}
More information about the jboss-svn-commits
mailing list