in container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java [1355:1838]
private void deploy(final AppModule app, final PersistenceModule persistenceModule) throws OpenEJBException {
if (!autoCreateResources) {
return;
}
final Persistence persistence = persistenceModule.getPersistence();
for (final PersistenceUnit unit : persistence.getPersistenceUnit()) {
if (unit.getProvider() != null) {
logger.info("Configuring PersistenceUnit(name=" + unit.getName() + ", provider=" + unit.getProvider() + ")");
} else {
logger.info("Configuring PersistenceUnit(name=" + unit.getName() + ")");
}
if (unit.getJtaDataSource() == null && unit.getNonJtaDataSource() == null
&& "true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.force-unit-type", unit.getProperty("openejb.force-unit-type", "true")))) {
unit.setTransactionType(TransactionType.JTA); // 8.2.1.5 of JPA 2.0 spec
}
// if jta datasource is specified it can be used as model fo rnon jta datasource
final boolean resourceLocal = TransactionType.RESOURCE_LOCAL.equals(unit.getTransactionType()) && unit.getJtaDataSource() == null;
if (resourceLocal && unit.getNonJtaDataSource() == null && isDataSourcePropertiesConfigured(unit.getProperties())) {
continue;
}
final Properties required = new Properties();
// if (unit.getJtaDataSource() == null && unit.getNonJtaDataSource() == null){
// unit.setJtaDataSource("JtaDataSource");
// unit.setNonJtaDataSource("NonJtaDataSource");
// } else if (unit.getJtaDataSource() == null){
// unit.setJtaDataSource(unit.getNonJtaDataSource()+"Jta");
// } else if (unit.getNonJtaDataSource() == null){
// unit.setNonJtaDataSource(unit.getJtaDataSource()+"NonJta");
// }
if ("org.apache.openjpa.persistence.PersistenceProviderImpl".equals(unit.getProvider())) {
if (unit.getJtaDataSource() == null) {
unit.setJtaDataSource(unit.getProperty("openjpa.ConnectionFactoryName"));
}
if (unit.getNonJtaDataSource() == null) {
unit.setNonJtaDataSource(unit.getProperty("openjpa.ConnectionFactory2Name"));
}
}
logger.debug("raw <jta-data-source>" + unit.getJtaDataSource() + "</jta-datasource>");
logger.debug("raw <non-jta-data-source>" + unit.getNonJtaDataSource() + "</non-jta-datasource>");
final String originalJtaDataSource = unit.getJtaDataSource(); // keep it can start with java:global for instance
unit.setJtaDataSource(normalizeResourceId(originalJtaDataSource));
final String originalNonJtaDataSource = unit.getNonJtaDataSource();
unit.setNonJtaDataSource(normalizeResourceId(originalNonJtaDataSource));
logger.debug("normalized <jta-data-source>" + unit.getJtaDataSource() + "</jta-datasource>");
logger.debug("normalized <non-jta-data-source>" + unit.getNonJtaDataSource() + "</non-jta-datasource>");
if (logger.isDebugEnabled()) {
required.put("JtaManaged", "true");
final List<String> managed = configFactory.getResourceIds("DataSource", required);
required.put("JtaManaged", "false");
final List<String> unmanaged = configFactory.getResourceIds("DataSource", required);
required.clear();
final List<String> unknown = configFactory.getResourceIds("DataSource", required);
logger.debug("Available DataSources");
for (final String name : managed) {
logger.debug("DataSource(name=" + name + ", JtaManaged=true)");
}
for (final String name : unmanaged) {
logger.debug("DataSource(name=" + name + ", JtaManaged=false)");
}
for (final String name : unknown) {
if (managed.contains(name)) {
continue;
}
if (unmanaged.contains(name)) {
continue;
}
logger.debug("DataSource(name=" + name + ", JtaManaged=<unknown>)");
}
}
final String prefix = app.getModuleId() + "/";
String jtaDataSourceId = null;
String nonJtaDataSourceId = null;
// first try exact matching without JtaManaged which is not mandatory actually (custom DS + JTADataSourceWrapperFactory)
final String jtaWithJavaAndSlash = replaceJavaAndSlash(unit.getJtaDataSource());
for (final String potentialName : asList(prefix + jtaWithJavaAndSlash, originalJtaDataSource, jtaWithJavaAndSlash)) {
if(potentialName == null) {
// If unit.getJtaDataSource() is null, one of the potentialName is also null.
continue;
}
final ResourceInfo jtaInfo = configFactory.getResourceInfo(potentialName);
if (jtaInfo != null) {
if (!"false".equalsIgnoreCase(jtaInfo.properties.getProperty("JtaManaged")) // don't test true since it can be missing
&& (jtaInfo.types.contains("DataSource") || jtaInfo.types.contains(DataSource.class.getName()))) {
jtaDataSourceId = jtaInfo.id;
break;
} else {
logger.warning("Found matching datasource: " + jtaInfo.id + " but this one is not a JTA datasource");
}
}
}
final String nonJtaWithJavaAndSlash = replaceJavaAndSlash(unit.getNonJtaDataSource());
for (final String potentialName : asList(prefix + nonJtaWithJavaAndSlash, originalNonJtaDataSource, nonJtaWithJavaAndSlash)) {
if(potentialName == null) {
// If unit.getNonJtaDataSource() is null, one of the potentialName is also null.
continue;
}
final ResourceInfo info = configFactory.getResourceInfo(potentialName);
if (info != null) {
if (!"true".equalsIgnoreCase(info.properties.getProperty("JtaManaged"))
&& (info.types.contains("DataSource") || info.types.contains(DataSource.class.getName()))) {
nonJtaDataSourceId = info.id;
break;
} else {
logger.warning("Found matching datasource: " + info.id + " but this one is a JTA datasource");
}
}
}
// then that's ok to force configuration
if (jtaDataSourceId == null && !resourceLocal) {
required.put("JtaManaged", "true");
jtaDataSourceId = findResourceId(prefix + jtaWithJavaAndSlash, "DataSource", required, null);
if (jtaDataSourceId == null) { // test with javax.sql.DataSource before DataSource since RA can register resources without our shortcut
jtaDataSourceId = findResourceId(jtaWithJavaAndSlash, "javax.sql.DataSource", required, null);
}
/* this shouldn't be mandatory anymore since our DataSource has as alias javax.sql.DataSource
if (jtaDataSourceId == null) {
jtaDataSourceId = findResourceId(replaceJavaAndSlash(unit.getJtaDataSource()), "DataSource", required, null);
}
*/
}
if (nonJtaDataSourceId == null) {
required.put("JtaManaged", "false");
nonJtaDataSourceId = findResourceId(prefix + nonJtaWithJavaAndSlash, "DataSource", required, null);
if (nonJtaDataSourceId == null) {
nonJtaDataSourceId = findResourceId(nonJtaWithJavaAndSlash, "DataSource", required, null);
}
}
if ((jtaDataSourceId != null || resourceLocal) && nonJtaDataSourceId != null) {
// Both DataSources were explicitly configured.
if (jtaDataSourceId != null) {
setJtaDataSource(unit, jtaDataSourceId);
}
setNonJtaDataSource(unit, nonJtaDataSourceId);
continue;
}
//
// If the jta-data-source or the non-jta-data-source link to
// third party resources, then we can't do any auto config
// for them. We give them what they asked for and move on.
//
if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
required.put("JtaManaged", ServiceUtils.NONE);
if (!resourceLocal) {
jtaDataSourceId = findResourceId(unit.getJtaDataSource(), "DataSource", required, null);
}
nonJtaDataSourceId = findResourceId(unit.getNonJtaDataSource(), "DataSource", required, null);
if (jtaDataSourceId != null || nonJtaDataSourceId != null) {
if (jtaDataSourceId != null) {
setJtaDataSource(unit, jtaDataSourceId);
}
if (nonJtaDataSourceId != null) {
setNonJtaDataSource(unit, nonJtaDataSourceId);
}
continue;
}
}
// We are done with the most optimal configuration.
//
// If both the jta-data-source and non-jta-data-source
// references were explicitly and correctly configured
// to existing datasource, we wouldn't get this far.
//
// At this point we see if either we can't figure out
// if there's an issue with their configuration or
// if we can't intelligently complete their configuration.
//
// Do both the jta-data-source and non-jta-data-source references
// point to the same datasource?
//
// If so, then unlink the invalid one so defaulting rules can
// possibly fill in a good value.
//
required.put("JtaManaged", ServiceUtils.ANY);
final String possibleJta = findResourceId(jtaWithJavaAndSlash, "DataSource", required, null);
final String possibleNonJta = findResourceId(nonJtaWithJavaAndSlash, "DataSource", required, null);
if (possibleJta != null && possibleJta.equals(possibleNonJta)) {
final ResourceInfo dataSource = configFactory.getResourceInfo(possibleJta);
final String jtaManaged = (String) dataSource.properties.get("JtaManaged");
logger.warning("PeristenceUnit(name=" +
unit.getName() +
") invalidly refers to Resource(id=" +
dataSource.id +
") as both its <jta-data-source> and <non-jta-data-source>.");
if ("true".equalsIgnoreCase(jtaManaged)) {
nonJtaDataSourceId = null;
unit.setNonJtaDataSource(null);
} else if ("false".equalsIgnoreCase(jtaManaged)) {
jtaDataSourceId = null;
unit.setJtaDataSource(null);
}
}
//
// Do the jta-data-source and non-jta-data-source references
// point to innapropriately configured Resources?
//
checkUnitDataSourceRefs(unit);
//
// Do either the jta-data-source and non-jta-data-source
// references point to the explicit name of a ServiceProvider?
//
if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
jtaDataSourceId = findResourceProviderId(unit.getJtaDataSource());
nonJtaDataSourceId = findResourceProviderId(unit.getNonJtaDataSource());
// if one of them is not null we have a match on at least one
// we can just create the second resource using the first as a template
if (jtaDataSourceId != null || nonJtaDataSourceId != null) {
final Resource jtaResource = new Resource(jtaDataSourceId, "DataSource", jtaDataSourceId);
jtaResource.getProperties().setProperty("JtaManaged", "true");
final Resource nonJtaResource = new Resource(nonJtaDataSourceId, "DataSource", nonJtaDataSourceId);
nonJtaResource.getProperties().setProperty("JtaManaged", "false");
if (jtaDataSourceId == null) {
jtaResource.setId(nonJtaDataSourceId + "Jta");
jtaResource.setProvider(nonJtaDataSourceId);
} else if (nonJtaDataSourceId == null) {
nonJtaResource.setId(jtaDataSourceId + "NonJta");
nonJtaResource.setProvider(jtaDataSourceId);
}
final ResourceInfo jtaResourceInfo = configFactory.configureService(jtaResource, ResourceInfo.class);
final ResourceInfo nonJtaResourceInfo = configFactory.configureService(nonJtaResource, ResourceInfo.class);
if (jtaDataSourceId != null && nonJtaDataSourceId == null) {
nonJtaResourceInfo.originAppName = jtaResourceInfo.originAppName;
}
logAutoCreateResource(jtaResourceInfo, "DataSource", unit.getName());
jtaDataSourceId = installResource(unit.getName(), jtaResourceInfo);
logAutoCreateResource(nonJtaResourceInfo, "DataSource", unit.getName());
nonJtaDataSourceId = installResource(unit.getName(), nonJtaResourceInfo);
setJtaDataSource(unit, jtaDataSourceId);
setNonJtaDataSource(unit, nonJtaDataSourceId);
continue;
}
}
// No data sources were specified:
// Look for defaults, see https://issues.apache.org/jira/browse/OPENEJB-1027
if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
// We check for data sources matching the following names:
// 1. The persistence unit id
// 2. The web module id
// 3. The web module context root
// 4. The application module id
final List<String> ids = new ArrayList<>();
ids.add(unit.getName());
for (final WebModule webModule : app.getWebModules()) {
ids.add(webModule.getModuleId());
ids.add(webModule.getContextRoot());
}
ids.add(app.getModuleId());
// Search for a matching data source
for (final String id : ids) {
//Try finding a jta managed data source
required.put("JtaManaged", "true");
jtaDataSourceId = findResourceId(id, "DataSource", required, null);
if (jtaDataSourceId == null) {
//No jta managed data source found. Try finding a non-jta managed
required.clear();
required.put("JtaManaged", "false");
nonJtaDataSourceId = findResourceId(id, "DataSource", required, null);
}
if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
// Neither jta nor non-jta managed data sources were found. try to find one with it unset
required.clear();
required.put("JtaManaged", ServiceUtils.NONE);
jtaDataSourceId = findResourceId(id, "DataSource", required, null);
}
if (jtaDataSourceId != null || nonJtaDataSourceId != null) {
//We have found a default. Exit the loop
break;
}
}
}
//
// If neither of the references are valid yet, then let's take
// the first valid datasource.
//
// We won't fill in both jta-data-source and non-jta-data-source
// this way as the following code does a great job at determining
// if any of the existing data sources are a good match or if
// one needs to be generated.
//
if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
required.clear();
required.put("JtaManaged", "true");
jtaDataSourceId = firstMatching(prefix, "DataSource", required, null);
if (jtaDataSourceId == null) {
required.clear();
required.put("JtaManaged", "false");
nonJtaDataSourceId = firstMatching(prefix, "DataSource", required, null);
}
}
//
// Does the jta-data-source reference point an existing
// Resource in the system with JtaManaged=true?
//
// If so, we can search for an existing datasource
// configured with identical properties and use it.
//
// If that doesn't work, we can copy the jta-data-source
// and auto-create the missing non-jta-data-source
// using it as a template, applying the overrides,
// and finally setting JtaManaged=false
//
if (jtaDataSourceId != null && nonJtaDataSourceId == null) {
final ResourceInfo jtaResourceInfo = configFactory.getResourceInfo(jtaDataSourceId);
final Properties jtaProperties = jtaResourceInfo.properties;
if (jtaProperties.containsKey("JtaManaged")) {
// Strategy 1: Best match search
required.clear();
required.put("JtaManaged", "false");
for (final String key : asList("JdbcDriver", "JdbcUrl")) {
if (jtaProperties.containsKey(key)) {
required.put(key, jtaProperties.get(key));
}
}
nonJtaDataSourceId = firstMatching(prefix, "DataSource", required, null);
// Strategy 2: Copy
if (nonJtaDataSourceId == null) {
final ResourceInfo nonJtaResourceInfo = copy(jtaResourceInfo);
nonJtaResourceInfo.id = jtaResourceInfo.id + "NonJta";
nonJtaResourceInfo.originAppName = jtaResourceInfo.originAppName;
suffixAliases(nonJtaResourceInfo, "NonJta");
configureImplicitDataSource(nonJtaResourceInfo);
final Properties overrides = ConfigurationFactory.getSystemProperties(nonJtaResourceInfo.id, nonJtaResourceInfo.service);
nonJtaResourceInfo.properties.putAll(overrides);
nonJtaResourceInfo.properties.setProperty("JtaManaged", "false");
nonJtaResourceInfo.properties.remove("Definition"); // if created from annotation we just want live config
logAutoCreateResource(nonJtaResourceInfo, "DataSource", unit.getName());
logger.info("configureService.configuring", nonJtaResourceInfo.id, nonJtaResourceInfo.service, jtaResourceInfo.id);
nonJtaDataSourceId = installResource(unit.getName(), nonJtaResourceInfo);
}
}
}
//
// Does the jta-data-source reference point an existing
// Resource in the system with JtaManaged=false?
//
// If so, we can search for an existing datasource
// configured with identical properties and use it.
//
// If that doesn't work, we can copy the jta-data-source
// and auto-create the missing non-jta-data-source
// using it as a template, applying the overrides,
// and finally setting JtaManaged=false
//
final String deduceJtaFromNonJta = unit.getProperty(AUTOCREATE_JTA_DATASOURCE_FROM_NON_JTA_ONE_KEY,
SystemInstance.get().getOptions().get(AUTOCREATE_JTA_DATASOURCE_FROM_NON_JTA_ONE_KEY, (String) null));
if (nonJtaDataSourceId != null && jtaDataSourceId == null
// hibernate uses the fact that this ds is missing to get a non jta em instead of a JTA one
&& (!resourceLocal || deduceJtaFromNonJta != null)
&& (deduceJtaFromNonJta == null || deduceJtaFromNonJta != null && Boolean.parseBoolean(deduceJtaFromNonJta))) {
final ResourceInfo nonJtaResourceInfo = configFactory.getResourceInfo(nonJtaDataSourceId);
final Properties nonJtaProperties = nonJtaResourceInfo.properties;
if (nonJtaProperties.containsKey("JtaManaged")) {
// Strategy 1: Best match search
required.clear();
required.put("JtaManaged", "true");
for (final String key : asList("JdbcDriver", "JdbcUrl")) {
if (nonJtaProperties.containsKey(key)) {
required.put(key, nonJtaProperties.get(key));
}
}
jtaDataSourceId = firstMatching(prefix, "DataSource", required, null);
// Strategy 2: Copy
if (jtaDataSourceId == null) {
final ResourceInfo jtaResourceInfo = copy(nonJtaResourceInfo);
jtaResourceInfo.id = nonJtaResourceInfo.id + "Jta";
suffixAliases(jtaResourceInfo, "Jta");
configureImplicitDataSource(jtaResourceInfo);
final Properties overrides = ConfigurationFactory.getSystemProperties(jtaResourceInfo.id, jtaResourceInfo.service);
jtaResourceInfo.properties.putAll(overrides);
jtaResourceInfo.properties.setProperty("JtaManaged", "true");
jtaResourceInfo.properties.remove("Definition"); // if created from annotation we just want live config
logAutoCreateResource(jtaResourceInfo, "DataSource", unit.getName());
logger.info("configureService.configuring", jtaResourceInfo.id, jtaResourceInfo.service, nonJtaResourceInfo.id);
jtaDataSourceId = installResource(unit.getName(), jtaResourceInfo);
}
}
}
//
// By this point if we've found anything at all, both
// jta-data-source and non-jta-data-source should be
// filled in (provided they aren't using a third party
// data source).
//
// Should both references still be null
// we can just take a shot in the dark and auto-create
// them them both using the built-in templates for jta
// and non-jta default datasources. These are supplied
// via the service-jar.xml file.
//
if (jtaDataSourceId == null && nonJtaDataSourceId == null) {
if (!resourceLocal) {
required.put("JtaManaged", "true");
jtaDataSourceId = autoCreateResource("DataSource", required, unit.getName());
}
required.put("JtaManaged", "false");
nonJtaDataSourceId = autoCreateResource("DataSource", required, unit.getName());
}
if (jtaDataSourceId != null) {
setJtaDataSource(unit, jtaDataSourceId);
}
if (nonJtaDataSourceId != null) {
setNonJtaDataSource(unit, nonJtaDataSourceId);
}
}
}