13

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?

3
  • 1
    If 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. Commented Dec 5, 2012 at 6: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 Commented Dec 5, 2012 at 8:17
  • So, After struggling with intellij/jboss/wildfly/maven the whole afternoon. I decided to use a node.js script Then, on Intellij wildfly configuration I added a "Before Launch "Script You can check my repo if you're interested in this apporach. github.com/talesmgodois/togglejta/blob/main/README.md Commented Apr 19, 2024 at 19:58

7 Answers 7

12

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); 
Sign up to request clarification or add additional context in comments.

2 Comments

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?
I have tried different variants and couldn't make it work. From here eclipse.org/eclipselink/documentation/2.4/jpa/extensions/… Currently, this property is used only for the canonical model generator. In the future, it may be used for customizing weaving and application bootstrapping.
8

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"); 

4 Comments

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.
In Spring I would consider static.springsource.org/spring/docs/3.2.x/… in the first place
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?
Thank you very much for nice idea. Based on you answer I found and posted answer for EclipseLink 2.7.0.
2

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 Comment

It seems I've found a working solution, please take a look at my answer
1

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.

Comments

1

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:

  1. Pay attention that when creating new class loader I pass there previous classloader otherwise it doesn't work.
  2. We set property eclipselink.persistencexml. If we don't do that then default descriptorPath will be equal to META-INF/persistence.xml and we would need to keep our persistence.xml on /home/Smith/program/META-INF/persistence.xml to be found.

2 Comments

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 I am really glad that the post helped you.
0

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" } } } 

Running Command Line in Java

Comments

0

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); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.