in geronimo-jpa_2.0_spec/src/main/java/javax/persistence/Persistence.java [78:191]
public static EntityManagerFactory createEntityManagerFactory(
String persistenceUnitName, Map properties) {
EntityManagerFactory factory = null;
Map props = properties;
if (props == null) {
props = Collections.EMPTY_MAP;
}
// get the discovered set of providers
PersistenceProviderResolver resolver =
PersistenceProviderResolverHolder.getPersistenceProviderResolver();
// following will throw PersistenceExceptions for invalid services
List<PersistenceProvider> providers = resolver.getPersistenceProviders();
/*
* Geronimo/OpenJPA 1.0 unique behavior - Start by loading a provider
* explicitly specified in the properties and return any exceptions.
* The spec doesn't forbid providers that aren't a service - it only
* states that they "should" be implemented as services in Sect. 9.2.
*
* For 2.0 - We only perform the above behavior if the specified
* provider is not in the discovered list.
*
* Note: This special non-spec defined case will rethrow any encountered
* Exceptions as a PersistenceException.
*/
Object propVal = props.get(PERSISTENCE_PROVIDER_PROPERTY);
if ((propVal != null) && (propVal instanceof String)) {
boolean isLoaded = false;
String providerName = propVal.toString();
// search the discovered providers for this explicit provider
for (PersistenceProvider provider : providers) {
if (provider.getClass().getName().compareTo(providerName) == 0) {
isLoaded = true;
break;
}
}
/*
* Only try to explicitly create this provider if we didn't
* find it as a service, while rethrowing any exceptions to
* match the old 1.0 behavior
*/
if (!isLoaded) {
factory = createFactory(
providerName.toString(),
persistenceUnitName,
props);
if (factory != null) {
return factory;
}
}
}
/*
* Now, the default JPA2 behavior of loading a provider from our resolver
*
* Note: Change in behavior from 1.0, which always returned exceptions:
* Spec states that a provider "must" return null if it
* cannot fulfill an EMF request, so that if we have more than one
* provider, then the other providers have a chance to return an EMF.
* Now, we will return any exceptions wrapped in a
* PersistenceException to match 1.0 behavior and provide more
* diagnostics to the end user.
*/
// capture any provider returned exceptions
Map<String, Throwable> exceptions = new HashMap<String, Throwable>();
// capture the provider names to use in the exception text if needed
StringBuffer foundProviders = null;
for (PersistenceProvider provider : providers) {
String providerName = provider.getClass().getName();
try {
factory = provider.createEntityManagerFactory(persistenceUnitName, props);
} catch (Exception e) {
// capture the exception details and give other providers a chance
exceptions.put(providerName, e);
}
if (factory != null) {
// we're done
return factory;
} else {
// update the list of providers we have tried
if (foundProviders == null) {
foundProviders = new StringBuffer(providerName);
} else {
foundProviders.append(", ");
foundProviders.append(providerName);
}
}
}
// make sure our providers list is initialized for the exceptions below
if (foundProviders == null) {
foundProviders = new StringBuffer("NONE");
}
/*
* Spec doesn't mention any exceptions thrown by this method if no emf
* returned, but old 1.0 behavior always generated an EMF or exception.
*/
if (exceptions.isEmpty()) {
// throw an exception with the PU name and providers we tried
throw new PersistenceException("No persistence providers available for \"" + persistenceUnitName +
"\" after trying the following discovered implementations: " + foundProviders);
} else {
// we encountered one or more exceptions, so format and throw as a single exception
throw createPersistenceException(
"Explicit persistence provider error(s) occurred for \"" + persistenceUnitName +
"\" after trying the following discovered implementations: " + foundProviders,
exceptions);
}
}