mirror of https://github.com/apache/openjpa.git
OPENJPA-1551:
Storing connectionFactoryName in BrokerImpl - this factory will be used at JDBCStore creation time to override the value from the configuration git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@919557 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a7d613f3bf
commit
4dc0267629
|
@ -35,6 +35,7 @@ import java.util.Set;
|
|||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.openjpa.enhance.PersistenceCapable;
|
||||
import org.apache.openjpa.event.OrphanedKeyAction;
|
||||
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
|
||||
|
@ -43,6 +44,7 @@ import org.apache.openjpa.jdbc.meta.Discriminator;
|
|||
import org.apache.openjpa.jdbc.meta.FieldMapping;
|
||||
import org.apache.openjpa.jdbc.meta.ValueMapping;
|
||||
import org.apache.openjpa.jdbc.meta.strats.SuperclassDiscriminatorStrategy;
|
||||
import org.apache.openjpa.jdbc.schema.DataSourceFactory;
|
||||
import org.apache.openjpa.jdbc.sql.DBDictionary;
|
||||
import org.apache.openjpa.jdbc.sql.JoinSyntaxes;
|
||||
import org.apache.openjpa.jdbc.sql.Joins;
|
||||
|
@ -146,15 +148,48 @@ public class JDBCStoreManager
|
|||
if (lm instanceof JDBCLockManager)
|
||||
_lm = (JDBCLockManager) lm;
|
||||
|
||||
if (!ctx.isManaged() && _conf.isConnectionFactoryModeManaged())
|
||||
_ds = _conf.getDataSource2(ctx);
|
||||
else
|
||||
_ds = _conf.getDataSource(ctx);
|
||||
_ds = getDataSource(ctx);
|
||||
|
||||
if (_conf.getUpdateManagerInstance().orderDirty())
|
||||
ctx.setOrderDirtyObjects(true);
|
||||
}
|
||||
|
||||
private final boolean useConnectionFactory2(StoreContext ctx) {
|
||||
return (!ctx.isManaged() && _conf.isConnectionFactoryModeManaged());
|
||||
}
|
||||
|
||||
private final DataSource getDataSource(StoreContext ctx) {
|
||||
DataSource ds;
|
||||
|
||||
if (useConnectionFactory2(ctx)) {
|
||||
ds = (DataSource) ctx.getConnectionFactory2();
|
||||
if (ds != null) {
|
||||
ds = DataSourceFactory.decorateDataSource(ds, _conf, false);
|
||||
}
|
||||
else {
|
||||
ds = _conf.getDataSource2(ctx);
|
||||
}
|
||||
} else {
|
||||
ds = (DataSource) ctx.getConnectionFactory();
|
||||
if (ds != null) {
|
||||
ds = DataSourceFactory.decorateDataSource(ds, _conf, false);
|
||||
}
|
||||
else {
|
||||
ds = _conf.getDataSource(ctx);
|
||||
}
|
||||
}
|
||||
return ds;
|
||||
}
|
||||
|
||||
private boolean useContextToGetDataSource(StoreContext ctx) {
|
||||
// configuration check to enable goes here.
|
||||
if (StringUtils.isBlank(ctx.getConnectionFactoryName())
|
||||
&& StringUtils.isBlank(ctx.getConnectionFactory2Name())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public JDBCConfiguration getConfiguration() {
|
||||
return _conf;
|
||||
}
|
||||
|
|
|
@ -183,6 +183,11 @@ public abstract class AbstractBrokerFactory
|
|||
}
|
||||
|
||||
public Broker newBroker(String user, String pass, boolean managed, int connRetainMode, boolean findExisting) {
|
||||
return newBroker(user, pass, managed, connRetainMode, findExisting, "", "");
|
||||
}
|
||||
|
||||
public Broker newBroker(String user, String pass, boolean managed, int connRetainMode, boolean findExisting,
|
||||
String cf1Name, String cf2Name) {
|
||||
try {
|
||||
assertOpen();
|
||||
makeReadOnly();
|
||||
|
@ -192,6 +197,8 @@ public abstract class AbstractBrokerFactory
|
|||
broker = findBroker(user, pass, managed);
|
||||
if (broker == null) {
|
||||
broker = newBrokerImpl(user, pass);
|
||||
broker.setConnectionFactoryName(cf1Name);
|
||||
broker.setConnectionFactory2Name(cf2Name);
|
||||
initializeBroker(managed, connRetainMode, broker, false);
|
||||
}
|
||||
return broker;
|
||||
|
|
|
@ -75,6 +75,29 @@ public interface BrokerFactory
|
|||
public Broker newBroker(String user, String pass, boolean managed,
|
||||
int connRetainMode, boolean findExisting);
|
||||
|
||||
/**
|
||||
* Return a new broker using the supplied
|
||||
* <ul>
|
||||
* <li>credentials</li>
|
||||
* <li>transaction management mode</li>
|
||||
* <li>connectionRetainMode</li>
|
||||
* <li>connectionFactories</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param user Username to use when obtaining a connection. Will be ignored if a connection factory is
|
||||
* obtained from JNDI.
|
||||
* @param pass Password to use when obtaining a connection. Will be ignored if a connection factory is
|
||||
* obtained from JNDI.
|
||||
* @param managed Whether managed transactions will be used by this Broker
|
||||
* @param connRetainMode {@link ConnectionRetainMode}
|
||||
* @param findExisting Whether the internal pool of brokers should be used.
|
||||
* @param cfName JTA ConnectionFactory to use
|
||||
* @param cf2Name Non-JTA ConnectionFactory to use.
|
||||
* @return A Broker which matches the provided criteria.
|
||||
*/
|
||||
public Broker newBroker(String user, String pass, boolean managed,
|
||||
int connRetainMode, boolean findExisting, String cfName, String cf2Name);
|
||||
|
||||
/**
|
||||
* Register a listener for lifecycle-related events on the specified
|
||||
* classes. If the classes are null, all events will be propagated to
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.apache.commons.collections.iterators.IteratorChain;
|
|||
import org.apache.commons.collections.map.IdentityMap;
|
||||
import org.apache.commons.collections.map.LinkedMap;
|
||||
import org.apache.commons.collections.set.MapBackedSet;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.openjpa.conf.Compatibility;
|
||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
||||
import org.apache.openjpa.datacache.DataCache;
|
||||
|
@ -60,6 +61,7 @@ import org.apache.openjpa.event.RemoteCommitEventManager;
|
|||
import org.apache.openjpa.event.TransactionEvent;
|
||||
import org.apache.openjpa.event.TransactionEventManager;
|
||||
import org.apache.openjpa.kernel.exps.ExpressionParser;
|
||||
import org.apache.openjpa.lib.conf.Configurations;
|
||||
import org.apache.openjpa.lib.log.Log;
|
||||
import org.apache.openjpa.lib.util.J2DoPrivHelper;
|
||||
import org.apache.openjpa.lib.util.Localizer;
|
||||
|
@ -145,6 +147,9 @@ public class BrokerImpl
|
|||
|
||||
private static final Object[] EMPTY_OBJECTS = new Object[0];
|
||||
|
||||
private String _connectionFactoryName = "";
|
||||
private String _connectionFactory2Name = "";
|
||||
|
||||
private static final Localizer _loc =
|
||||
Localizer.forPackage(BrokerImpl.class);
|
||||
|
||||
|
@ -4970,4 +4975,60 @@ public class BrokerImpl
|
|||
public boolean isFromWriteBehindCallback() {
|
||||
return _fromWriteBehindCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the 'JTA' connectionFactoryName
|
||||
*/
|
||||
public String getConnectionFactoryName() {
|
||||
return _connectionFactoryName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'JTA' ConnectionFactoryName. Input will be trimmed to null before being stored.
|
||||
*/
|
||||
public void setConnectionFactoryName(String connectionFactoryName) {
|
||||
this._connectionFactoryName = StringUtils.trimToNull(connectionFactoryName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the 'NonJTA' ConnectionFactoryName.
|
||||
*/
|
||||
public String getConnectionFactory2Name() {
|
||||
return _connectionFactory2Name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'NonJTA' ConnectionFactoryName. Input will be trimmed to null before being stored.
|
||||
*/
|
||||
public void setConnectionFactory2Name(String connectionFactory2Name) {
|
||||
this._connectionFactory2Name = StringUtils.trimToNull(connectionFactory2Name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the 'JTA' ConnectionFactory, looking it up from JNDI if needed.
|
||||
*
|
||||
* @return the JTA connection factory or null if connectionFactoryName is blank.
|
||||
*/
|
||||
public Object getConnectionFactory() {
|
||||
if(StringUtils.isNotBlank(_connectionFactoryName)) {
|
||||
return Configurations.lookup(_connectionFactoryName, "openjpa.ConnectionFactory", _log );
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the 'NonJTA' ConnectionFactory, looking it up from JNDI if needed.
|
||||
*
|
||||
* @return the NonJTA connection factory or null if connectionFactoryName is blank.
|
||||
*/
|
||||
public Object getConnectionFactory2() {
|
||||
if(StringUtils.isNotBlank(_connectionFactory2Name)) {
|
||||
return Configurations.lookup(_connectionFactory2Name, "openjpa.ConnectionFactory2", _log);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1418,4 +1418,28 @@ public class DelegatingBroker
|
|||
public void setCachePreparedQuery(boolean flag) {
|
||||
_broker.setCachePreparedQuery(flag);
|
||||
}
|
||||
|
||||
public String getConnectionFactoryName() {
|
||||
return _broker.getConnectionFactoryName();
|
||||
}
|
||||
|
||||
public void setConnectionFactoryName(String connectionFactoryName) {
|
||||
_broker.setConnectionFactoryName(connectionFactoryName);
|
||||
}
|
||||
|
||||
public String getConnectionFactory2Name() {
|
||||
return _broker.getConnectionFactory2Name();
|
||||
}
|
||||
|
||||
public void setConnectionFactory2Name(String connectionFactory2Name) {
|
||||
_broker.setConnectionFactory2Name(connectionFactory2Name);
|
||||
}
|
||||
|
||||
public Object getConnectionFactory() {
|
||||
return _broker.getConnectionFactory();
|
||||
}
|
||||
|
||||
public Object getConnectionFactory2() {
|
||||
return _broker.getConnectionFactory2();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,9 +148,13 @@ public class DelegatingBrokerFactory
|
|||
|
||||
public Broker newBroker(String user, String pass, boolean managed,
|
||||
int connRetainMode, boolean findExisting) {
|
||||
return newBroker(user, pass, managed, connRetainMode, findExisting, "", "");
|
||||
}
|
||||
public Broker newBroker(String user, String pass, boolean managed,
|
||||
int connRetainMode, boolean findExisting, String cfName, String cf2Name) {
|
||||
try {
|
||||
return _factory.newBroker(user, pass, managed, connRetainMode,
|
||||
findExisting);
|
||||
findExisting, cfName, cf2Name);
|
||||
} catch (RuntimeException re) {
|
||||
throw translate(re);
|
||||
}
|
||||
|
|
|
@ -456,4 +456,38 @@ public interface StoreContext {
|
|||
* Releases the internal lock.
|
||||
*/
|
||||
public void unlock ();
|
||||
|
||||
/**
|
||||
* Return the 'JTA' connectionFactoryName
|
||||
*/
|
||||
public String getConnectionFactoryName();
|
||||
|
||||
/**
|
||||
* Set the 'JTA' ConnectionFactoryName.
|
||||
*/
|
||||
public void setConnectionFactoryName(String connectionFactoryName);
|
||||
|
||||
/**
|
||||
* Return the 'NonJTA' ConnectionFactoryName.
|
||||
*/
|
||||
public String getConnectionFactory2Name();
|
||||
|
||||
/**
|
||||
* Set the 'NonJTA' ConnectionFactoryName.
|
||||
*/
|
||||
public void setConnectionFactory2Name(String connectionFactory2Name);
|
||||
|
||||
/**
|
||||
* Return the 'JTA' ConnectionFactory, looking it up from JNDI if needed.
|
||||
*
|
||||
* @return the JTA connection factory or null if connectionFactoryName is blank.
|
||||
*/
|
||||
public Object getConnectionFactory();
|
||||
|
||||
/**
|
||||
* Return the 'NonJTA' ConnectionFactory, looking it up from JNDI if needed.
|
||||
*
|
||||
* @return the NonJTA connection factory or null if connectionFactoryName is blank.
|
||||
*/
|
||||
public Object getConnectionFactory2();
|
||||
}
|
||||
|
|
|
@ -712,6 +712,12 @@
|
|||
<artifactId>jaxb-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>simple-jndi</groupId>
|
||||
<artifactId>simple-jndi</artifactId>
|
||||
<version>0.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package org.apache.openjpa.persistence.conf;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Version;
|
||||
|
||||
// override defaults to attempt to prevent collisions.
|
||||
@Entity(name="confPerson")
|
||||
@Table(name="CONF_PERSON")
|
||||
public class Person {
|
||||
|
||||
@Id
|
||||
private int id;
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
@Column(length=16)
|
||||
private String name;
|
||||
|
||||
public Person() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Person(int id) {
|
||||
super();
|
||||
setId(id);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
package org.apache.openjpa.persistence.conf;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.EntityExistsException;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.RollbackException;
|
||||
|
||||
import org.apache.openjpa.persistence.test.AbstractPersistenceTestCase;
|
||||
|
||||
public class TestSwitchConnection extends AbstractPersistenceTestCase {
|
||||
private String defaultJndiName = "jdbc/mocked";
|
||||
private String[] jndiNames = { "jdbc/mocked1" };
|
||||
|
||||
protected void initEMF(String cfName) {
|
||||
EntityManagerFactory emf = getEmf("openjpa.ConnectionFactoryName", cfName);
|
||||
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
em.createQuery("Delete from confPerson").executeUpdate();
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
|
||||
emf.close();
|
||||
}
|
||||
|
||||
protected EntityManagerFactory getEmf(String cfPropertyName, String cfPropertyValue) {
|
||||
// null out the driver to prevent system properties from taking effect.
|
||||
// do not set connectionFactoryModeManaged - or connectionFactory2 will be used.
|
||||
return createEMF(
|
||||
"openjpa.ConnectionDriverName", "",
|
||||
cfPropertyName, cfPropertyValue,
|
||||
Person.class);
|
||||
}
|
||||
|
||||
protected EntityManager getEm(EntityManagerFactory emf, String name, String value) {
|
||||
Map<String, Object> props = new HashMap<String, Object>();
|
||||
props.put(name, value);
|
||||
return emf.createEntityManager(props);
|
||||
}
|
||||
|
||||
protected void createTables() {
|
||||
// create an EMF for each database;
|
||||
initEMF(defaultJndiName);
|
||||
initEMF(jndiNames[0]);
|
||||
}
|
||||
|
||||
public void testConnectionFactoryName() {
|
||||
// split out so that we can try javax.persistence.jtaDataSource in the future.
|
||||
overridePropertyOnEM("openjpa.ConnectionFactoryName", jndiNames[0]);
|
||||
}
|
||||
|
||||
public void overridePropertyOnEM(String name, String value) {
|
||||
// TODO Disable for non derby.
|
||||
createTables();
|
||||
|
||||
// use the default JndiName for the base EntityManagerFactory
|
||||
EntityManagerFactory emf = getEmf(name, defaultJndiName);
|
||||
assertNotNull(emf);
|
||||
|
||||
EntityManager em = emf.createEntityManager();
|
||||
assertNotNull(em);
|
||||
|
||||
EntityManager em1 = getEm(emf, name, value);
|
||||
assertNotNull(em1);
|
||||
|
||||
// 'prove' that we're using a different database by inserting the same row
|
||||
em.getTransaction().begin();
|
||||
em.persist(new Person(1));
|
||||
em.getTransaction().commit();
|
||||
|
||||
em1.getTransaction().begin();
|
||||
em1.persist(new Person(1));
|
||||
em1.getTransaction().commit();
|
||||
|
||||
em.clear();
|
||||
em1.clear();
|
||||
|
||||
// sanity test, make sure inserting the same row again fails.
|
||||
|
||||
em.getTransaction().begin();
|
||||
em.persist(new Person(1));
|
||||
try {
|
||||
em.getTransaction().commit();
|
||||
fail("Should not be able to commit the same row a second time");
|
||||
} catch (RollbackException rbe) {
|
||||
assertTrue(rbe.getCause() instanceof EntityExistsException);
|
||||
// expected
|
||||
}
|
||||
|
||||
em1.getTransaction().begin();
|
||||
em1.persist(new Person(1));
|
||||
try {
|
||||
em1.getTransaction().commit();
|
||||
fail("Should not be able to commit the same row a second time");
|
||||
} catch (RollbackException rbe) {
|
||||
assertTrue(rbe.getCause() instanceof EntityExistsException);
|
||||
// expected
|
||||
}
|
||||
|
||||
em.close();
|
||||
em1.close();
|
||||
emf.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
java.naming.factory.initial=org.osjava.sj.SimpleContextFactory
|
||||
org.osjava.sj.root=src/test/resources/simple-jndi
|
||||
org.osjava.sj.colon.replace=--
|
||||
org.osjava.sj.delimiter=/
|
|
@ -0,0 +1,11 @@
|
|||
mocked/type=javax.sql.DataSource
|
||||
mocked/driver=org.apache.derby.jdbc.EmbeddedDriver
|
||||
mocked/url=jdbc:derby:target/database/jpa-jndi-database;create=true
|
||||
mocked/user=app
|
||||
mocked/password=app
|
||||
|
||||
mocked1/type=javax.sql.DataSource
|
||||
mocked1/driver=org.apache.derby.jdbc.EmbeddedDriver
|
||||
mocked1/url=jdbc:derby:target/database/jpa-jndi-database1;create=true
|
||||
mocked1/user=app
|
||||
mocked1/password=app
|
|
@ -197,7 +197,20 @@ public class EntityManagerFactoryImpl
|
|||
}
|
||||
}
|
||||
|
||||
Broker broker = _factory.newBroker(user, pass, managed, retainMode, false);
|
||||
// javax.persistence.jtaDataSource and openjpa.ConnectionFactory name are equivalent.
|
||||
// prefer javax.persistence for now.
|
||||
String cfName = (String) Configurations.removeProperty("jtaDataSource", props);
|
||||
if(cfName == null) {
|
||||
cfName = (String) Configurations.removeProperty("ConnectionFactoryName", props);
|
||||
}
|
||||
|
||||
String cf2Name = (String) Configurations.removeProperty("nonJtaDataSource", props);
|
||||
|
||||
if(cf2Name == null) {
|
||||
cf2Name = (String) Configurations.removeProperty("ConnectionFactory2Name", props);
|
||||
}
|
||||
|
||||
Broker broker = _factory.newBroker(user, pass, managed, retainMode, false, cfName, cf2Name);
|
||||
|
||||
// add autodetach for close and rollback conditions to the configuration
|
||||
broker.setAutoDetach(AutoDetach.DETACH_CLOSE, true);
|
||||
|
|
Loading…
Reference in New Issue