I want to have my persistence.xml in conf folder of my app. How can I tell Persistence.createEntityManagerFactory that it should read it from there?
-
1If you're using Spring, you can achieve this at least by using `org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean` and specifying the property `persistenceXmlLocation` to point to the file. – RJo Dec 05 '12 at 06:27
-
which JPA implementation? DataNucleus JPA allows you to specify where it is stored. Maybe other do too. Not part of the JPA spec obviously – DataNucleus Dec 05 '12 at 08:17
7 Answers
If you are using EclipseLink you can set the persistence.xml location with the persistence unit property, "eclipselink.persistencexml".
properties.put("eclipselink.persistencexml", "/org/acme/acme-persistence.xml");
EntityManagerFactory factory = Persistence.createEntityManagerFactory("acme", properties);

- 17,965
- 11
- 91
- 146
-
It it possible to use this solution when persistence.xml is outside jar, for example when persistence.xml path is `/home/foo/downloads/persistence.xml`? – Pavel_K Oct 09 '17 at 19:43
-
I have tried different variants and couldn't make it work. From here http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/p_persistencexml.htm `Currently, this property is used only for the canonical model generator. In the future, it may be used for customizing weaving and application bootstrapping.` – Pavel_K Oct 10 '17 at 15:19
This solution worked for me
Thread.currentThread().setContextClassLoader(new ClassLoader() {
@Override
public Enumeration<URL> getResources(String name) throws IOException {
if (name.equals("META-INF/persistence.xml")) {
return Collections.enumeration(Arrays.asList(new File("conf/persistence.xml")
.toURI().toURL()));
}
return super.getResources(name);
}
});
Persistence.createEntityManagerFactory("test");

- 133,369
- 30
- 199
- 275
-
Can you elaborate a bit more on your answer? I dont know enough about spring internals to interpolate where I need to add the above snippet. – niken Jul 05 '13 at 14:28
-
In Spring I would consider http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/new-in-3.1.html#new-in-3.1-jpa-without-xml in the first place – Evgeniy Dorofeev Jul 06 '13 at 03:39
-
I would use your solution but it is not working with my configuration: Java 1.6.0_24, EclipseLink 2.3.2. I have an exception "javax.persistence.PersistenceException: No Persistence provider for EntityManager named XXX". Do you have an idea of why? – njames Aug 12 '13 at 14:57
-
Thank you very much for nice idea. Based on you answer I found and posted answer for EclipseLink 2.7.0. – Pavel_K Oct 10 '17 at 18:01
The createEntityManagerFactory methods search for persistence.xml files within the META-INF directory of any CLASSPATH element. if your CLASSPATH contains the conf directory, you could place an EntityManagerFactory definition in conf/META-INF/persistence.xml

- 1,731
- 1
- 11
- 13
-
It seems I've found a working solution, please take a look at my answer – Evgeniy Dorofeev Dec 21 '12 at 06:20
The ClassLoader may be a URLClassLoader, so try it this way:
final URL alternativePersistenceXmlUrl = new File("conf/persistence.xml").toURI().toURL();
ClassLoader output;
ClassLoader current = Thread.currentThread().getContextClassLoader();
try{
URLClassLoader parent = (URLClassLoader)current;
output = new URLClassLoader(parent.getURLs(), parent){
@Override
public Enumeration<URL> getResources(String name) throws IOException {
if (name.equals("META-INF/persistence.xml")) {
return Collections.enumeration(Arrays.asList(alternativePersistenceXmlUrl));
}
return super.getResources(name);
}
};
}catch(ClassCastException ignored) {
output = new ClassLoader() {
@Override
public Enumeration<URL> getResources(String name) throws IOException {
if (name.equals("META-INF/persistence.xml")) {
return Collections.enumeration(Arrays.asList(alternativePersistenceXmlUrl));
}
return super.getResources(name);
}
};
}
It should work. Works for me under certain test etc conditions. Please this is a hack and should not be used in production.

- 281
- 2
- 4
My solution is for EclipseLink 2.7.0 and Java 9 and it is modified and detailed version of @Evgeniy Dorofeev answer.
In org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor
on line 236
we see the following code:
URL puRootUrl = computePURootURL(descUrl, descriptorPath);
This code is used by EclipseLink to compute root url of the persistence.xml path. That's very important because final path will be made by adding descriptorPath
to puRootUrl
.
So, let's suppose we have file on /home/Smith/program/some-folder/persistence.xml
, then we have:
Thread currentThread = Thread.currentThread();
ClassLoader previousClassLoader = currentThread.getContextClassLoader();
Thread.currentThread().setContextClassLoader(new ClassLoader(previousClassLoader) {
@Override
public Enumeration<URL> getResources(String name) throws IOException {
if (name.equals("some-folder/persistence.xml")) {
URL url = new File("/home/Smith/program/some-folder/persistence.xml").toURI().toURL();
return Collections.enumeration(Arrays.asList(url));
}
return super.getResources(name);
}
});
Map<String, String> properties = new HashMap<>();
properties.put("eclipselink.persistencexml", "some-folder/persistence.xml");
try {
entityManagerFactory = Persistence.createEntityManagerFactory("unit-name", properties);
} catch (Exception ex) {
logger.error("Error occured creating EMF", ex);
} finally {
currentThread.setContextClassLoader(previousClassLoader);
}
Details:
- Pay attention that when creating new class loader I pass there previous classloader otherwise it doesn't work.
- We set property
eclipselink.persistencexml
. If we don't do that then default descriptorPath will be equal toMETA-INF/persistence.xml
and we would need to keep our persistence.xml on/home/Smith/program/META-INF/persistence.xml
to be found.

- 10,748
- 13
- 73
- 186
-
I searched and tried different methods for two days, trying to get my persistence.xml out of my distribution jar (so the end user could modify persistence.xml without needing to recompile). Since I am using EcliplseLink 2.5.2, this worked great for me. – Tihamer Oct 04 '21 at 15:06
-
I tried these ways when the program is starting (at first line of main function):
Write your persistence.xml to the resources/META-INF/persistence.xml of the jar
I had problem with this way: Java write .txt file in resource folder
Create META-INF folder in the jar directory and put your persistence.xml into it, then execute this command:
jar uf $jarName META-INF/persistence.xml
This command will replace META-INF/persistence.xml (your file) in the jar
private fun persistence() {
val fileName = "META-INF/persistence.xml"
val jarName: String?
val done = try {
jarName = javaClass.protectionDomain.codeSource.location.path
if (File(fileName).exists() && !jarName.isNullOrBlank()
&& jarName.endsWith(".jar") && File(jarName).exists()) {
Command().exec("jar uf $jarName META-INF/persistence.xml", timeoutSec = 30)
true
} else false
} catch (e: Exception) {
false
}
if (done) {
logger.info { "$fileName exist and will be loaded :)" }
} else {
logger.info {
"$fileName not exist in current folder so it will be read from .jar :(" +
" you can run: jar uf jarName.jar META-INF/persistence.xml"
}
}
}

- 61
- 3
A solution by creating tweaked PersistenceUnitDescriptor.
import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
import org.hibernate.jpa.boot.spi.Bootstrap;
import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder;
public class HibernateEntityManagerFactoryBuilder {
public static final EntityManagerFactory build(URL xmlUrl) {
final ParsedPersistenceXmlDescriptor xmlDescriptor = PersistenceXmlParser.locateIndividualPersistenceUnit(xmlUrl);
final HibernatePersistenceUnitDescriptor hibernateDescriptor = new HibernatePersistenceUnitDescriptor(xmlDescriptor);
final EntityManagerFactoryBuilder builder = Bootstrap.getEntityManagerFactoryBuilder(hibernateDescriptor, Collections.emptyMap(), (ClassLoader) null);
final EntityManagerFactory factory = builder.build();
return factory;
}
public static final EntityManagerFactory build(URL xmlUrl, final String name) {
final ParsedPersistenceXmlDescriptor xmlDescriptor = PersistenceXmlParser.locateNamedPersistenceUnit(xmlUrl, name);
if(xmlDescriptor == null) throw new RuntimeException("Persistence unit with name '"+name+ "' not found.");
final HibernatePersistenceUnitDescriptor hibernateDescriptor = new HibernatePersistenceUnitDescriptor(xmlDescriptor);
final EntityManagerFactoryBuilder builder = Bootstrap.getEntityManagerFactoryBuilder(hibernateDescriptor, Collections.emptyMap(), (ClassLoader) null);
final EntityManagerFactory factory = builder.build();
return factory;
}
public static void main(String[] args) {
try {
final EntityManagerFactory factory = build(new File("D:/ini/persistence.xml").toURI().toURL());
} catch (Exception e) {e.printStackTrace();}
}
}
public class HibernatePersistenceUnitDescriptor implements PersistenceUnitDescriptor {
private final PersistenceUnitDescriptor descriptor;
public HibernatePersistenceUnitDescriptor(PersistenceUnitDescriptor descriptor) {
this.descriptor = descriptor;
}
@Override
public URL getPersistenceUnitRootUrl() {
return null;
}
@Override
public String getName() {
return descriptor.getName();
}
@Override
public String getProviderClassName() {
return descriptor.getProviderClassName();
}
@Override
public boolean isUseQuotedIdentifiers() {
return descriptor.isUseQuotedIdentifiers();
}
@Override
public boolean isExcludeUnlistedClasses() {
return descriptor.isExcludeUnlistedClasses();
}
@Override
public PersistenceUnitTransactionType getTransactionType() {
return descriptor.getTransactionType();
}
@Override
public ValidationMode getValidationMode() {
return descriptor.getValidationMode();
}
@Override
public SharedCacheMode getSharedCacheMode() {
return descriptor.getSharedCacheMode();
}
@Override
public List<String> getManagedClassNames() {
return descriptor.getManagedClassNames();
}
@Override
public List<String> getMappingFileNames() {
return descriptor.getMappingFileNames();
}
@Override
public List<URL> getJarFileUrls() {
return descriptor.getJarFileUrls();
}
@Override
public Object getNonJtaDataSource() {
return descriptor.getNonJtaDataSource();
}
@Override
public Object getJtaDataSource() {
return descriptor.getJtaDataSource();
}
@Override
public Properties getProperties() {
return descriptor.getProperties();
}
@Override
public ClassLoader getClassLoader() {
return descriptor.getClassLoader();
}
@Override
public ClassLoader getTempClassLoader() {
return descriptor.getTempClassLoader();
}
@Override
public void pushClassTransformer(EnhancementContext enhancementContext) {
descriptor.pushClassTransformer(enhancementContext);
}
}

- 425
- 4
- 14