-
Notifications
You must be signed in to change notification settings - Fork 176
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support external config file for eclipselink #88
Support external config file for eclipselink #88
Conversation
If we can't support |
Yeah. It's awkward to do such configuration and it can only be used for workaround. One more improvement we can do is to dynamically add the jar to classpath so the user doesn't need to do that. |
InputStream input = null; | ||
int splitPosition = confFile.indexOf("!/"); | ||
if (splitPosition == -1) { | ||
input = this.getClass().getClassLoader().getResourceAsStream(confFile); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typically, I use Thread.currentThread().contextClassLoader()
so that if the plugin jar happens to be loaded by a child classloader, rather than this one, we can still find it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I made the change to create a new ClassLoader with the conf jar and I'm using Thread.currentThread().contextClassLoader() now.
String jarPrefixPath = confFile.substring(0, splitPosition); | ||
String descPath = confFile.substring(splitPosition + 2); | ||
URL prefixUrl = this.getClass().getClassLoader().getResource(jarPrefixPath); | ||
URLClassLoader child = | ||
new URLClassLoader(new URL[] {prefixUrl}, this.getClass().getClassLoader()); | ||
input = child.getResourceAsStream(descPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I don't understand what's going on. This InputStream
is not being used to setup eclipselink? Cause this InputStream
could be coming from anywhere. Why is there a restriction that the resource is on the classpath?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is used to parse it, but then EclispeLink again tries to load the resource directly when we call Persistence.createEntityManagerFactory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since each realm has its only database, I have the following configuration in persistence.xml. I read this configuration and replace the realm then pass it to Persistence.createEntityManagerFactory()
which will again read persistence.xml for the rest of the configurations. Persistence.createEntityManagerFactory()
assumes the persistence.xml is a resource file inside a jar.
<property name="jakarta.persistence.jdbc.url" value="jdbc:h2:file:/tmp/eclipseLink/{realm}"/>
e6cacd2
to
9e925cd
Compare
9e925cd
to
19667fe
Compare
Due to the limitation of eclipselink, the config file has to be a resource inside a jar so a config file like /tmp/persistence.xml can't be supported directly. To workaround the issue, 1. create a jar file from persistence.xml through 'jar /tmp/cf conf.jar ./persistence.xml' 3. configure eclipselink in polaris-server.yml metaStoreManager: type: eclipse-link persistence-unit: polaris conf-file: /tmp/conf.jar!/persistence.xml
19667fe
to
023bb41
Compare
I was able to fix this in #95 . |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, hacky but... it works I guess
} | ||
URLClassLoader currentClassLoader = | ||
new URLClassLoader(new URL[] {prefixUrl}, this.getClass().getClassLoader()); | ||
Thread.currentThread().setContextClassLoader(currentClassLoader); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a logging statement here stating that we're changing the classloader temporarily
String jarPrefixPath = confFile.substring(0, splitPosition); | ||
confFile = confFile.substring(splitPosition + 2); | ||
URL prefixUrl = this.getClass().getClassLoader().getResource(jarPrefixPath); | ||
if (prefixUrl == null) { | ||
prefixUrl = new File(jarPrefixPath).toURI().toURL(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add logs here specifying the jar we found and how we're altering the classpath
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't see the comments before merging. Let me add that in a follow up.
} catch (Exception e) { | ||
throw new RuntimeException(e); | ||
} finally { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
catch RuntimeException separately and just rethrow
String.format( | ||
"Cannot find or parse the configuration file %s for persistence-unit %s", | ||
confFile, persistenceUnitName); | ||
LOG.error(str); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
log the original exception so we can see the stacktrace
@aihuaxu @collado-mike I think, we need a follow-up of this one, because it adds binary content (a jar file). |
Ack. Let me think of a way to address that since that is only used for testing. |
Description
Due to the limitation of eclipselink which requires the config file to be a resource inside a jar so a config file like /tmp/persistence.xml can't be supported directly. Persistence.createEntityManagerFactory() implementation searches the configuration file, checks if it's an archive (zip or jar file) and fails if it's not.
To workaround the issue, the PR supports the external configuration file format
/tmp/conf.jar!/persistence.xml
, adds /tmp/conf.jar in the classpath and then load the configuration. Here are the steps:jar -cf /tmp/conf.jar ./persistence.xml
The extra step is to run is
jar -cf /tmp/conf.jar ./persistence.xml
after updating the file.Also updated persistence_unit name that the one for test should be
polaris-dev
and the default one for production should bepolaris
in persistence.xml.Fixes #45
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
confFile =/tmp/ conf.jar!/persistence.xml
Test Configuration:
Checklist:
Please delete options that are not relevant.