Skip to content
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

Allow eclipselink config outside classpath #95

Conversation

guitcastro
Copy link

@guitcastro guitcastro commented Aug 6, 2024

Description

As today, It's impossible to load configurations outside the classpath using eclipse-link. This PR allow do load config files from any path.

Fixes # (issue)

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

I've update the PolarisEclipseLinkMetaStoreTest to ensure that the file is being loaded from outside the classpath.

Checklist:

Please delete options that are not relevant.

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules
  • If adding new functionality, I have discussed my implementation with the community using the linked GitHub issue
  • I have signed and submitted the ICLA and if needed, the CCLA. See Contributing for details.

@guitcastro guitcastro requested a review from a team as a code owner August 6, 2024 03:09
@@ -124,7 +124,7 @@ private Map<String, String> loadProperties(String confFile, String persistenceUn
}

try {
InputStream input = this.getClass().getClassLoader().getResourceAsStream(confFile);
FileInputStream input = new FileInputStream(confFile);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine but Persistence.createEntityManagerFactory(persistenceUnitName, properties) puts the limitation which can only loads the configuration from a jar. I'm making a change to workaround that. #88

Copy link
Author

@guitcastro guitcastro Aug 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was able to fix this in the last commit. Please see the this comment in #79

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I replied in another thread.

@guitcastro Actually it's not because of the properties. Of course we need the properties because we want to replace realm in the database name - each realm will have its own database.

Persistence.createEntityManagerFactory() will still load configuration file from resource even without properties.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aihuaxu only if you specify the ECLIPSELINK_PERSISTENCE_XML property. I've tested and it worked.

From their docs:

This property is only used by EclipseLink when it is locating the configuration file.
When used within an EJB/Spring container in container managed mode the locating and reading of this file is done by the container and will not use this configuration.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added unit test to ensure config loads from outside the classpath is working.

Copy link
Contributor

@aihuaxu aihuaxu Aug 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@guitcastro Can you list the steps how you get it to work? It's possible the unit test found the persistence.xml from the embedded jar. That's why it doesn't fail for you.

I don't see the changes or unit tests in the PR. Did you forget to include that?

I only see
properties.put(ECLIPSELINK_PERSISTENCE_XML, confFile); -- removed

FileInputStream input = new FileInputStream(confFile);

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aihuaxu Sorry, I have forgot to push it. Can you please take a look now? I also added a test to ensure that the config is not being loaded from the classpath.

@eric-maynard
Copy link
Contributor

eric-maynard commented Aug 6, 2024

This looks similar to #79, which did not work when tested.

@guitcastro
Copy link
Author

guitcastro commented Aug 6, 2024

This looks similar to #79, which did not work when tested.

I fix this in the last commit. Please see the this comment in #79

@eric-maynard
Copy link
Contributor

Hi @guitcastro, I tested this change and found that it did not work. See my notes below:

I copied the default persistence.xml to my desktop and updated the polaris-server.yml to point to it:

. . .
metaStoreManager:
  type: eclipse-link
  persistence-unit: polaris-dev
  conf-file: /Users/emaynard/Desktop/persistence.xml
. . .

I then modified the default persistence.xml at .../resources/META-INF/persistence.xml to use a different persistence-unit -- polaris-fake instead of polaris-dev. When I attempt to bootstrap, I see this:

jakarta.persistence.PersistenceException: No Persistence provider for EntityManager named polaris-dev
	at jakarta.persistence.Persistence.createEntityManagerFactory(Persistence.java:86)
	at io.polaris.extension.persistence.impl.eclipselink.PolarisEclipseLinkMetaStoreSessionImpl.<init>(PolarisEclipseLinkMetaStoreSessionImpl.java:109)
. . .

If I revert the default persistence.xml back to using polaris-dev, it bootstraps normally.

Based on this, I suspect that your change is in fact just loading the default persistence.xml which is on the classpath, and that it does not actually allow us to load a persistence.xml outside of the classpath. This makes sense when you consider your change is deleting the config that is supposed to point to the location of the persistence.xml. Is it possible you were observing the same in your testing?

@guitcastro
Copy link
Author

Hi @guitcastro, I tested this change and found that it did not work. See my notes below:

I copied the default persistence.xml to my desktop and updated the polaris-server.yml to point to it:

. . .
metaStoreManager:
  type: eclipse-link
  persistence-unit: polaris-dev
  conf-file: /Users/emaynard/Desktop/persistence.xml
. . .

I then modified the default persistence.xml at .../resources/META-INF/persistence.xml to use a different persistence-unit -- polaris-fake instead of polaris-dev. When I attempt to bootstrap, I see this:

jakarta.persistence.PersistenceException: No Persistence provider for EntityManager named polaris-dev
	at jakarta.persistence.Persistence.createEntityManagerFactory(Persistence.java:86)
	at io.polaris.extension.persistence.impl.eclipselink.PolarisEclipseLinkMetaStoreSessionImpl.<init>(PolarisEclipseLinkMetaStoreSessionImpl.java:109)
. . .

If I revert the default persistence.xml back to using polaris-dev, it bootstraps normally.

Based on this, I suspect that your change is in fact just loading the default persistence.xml which is on the classpath, and that it does not actually allow us to load a persistence.xml outside of the classpath. This makes sense when you consider your change is deleting the config that is supposed to point to the location of the persistence.xml. Is it possible you were observing the same in your testing?

Maybe the /Users/emaynard/Desktop/persistence.xml is not defining a polaris-dev. I just commit two unit test that ensure that the default config is not being loaded. If you test the lasted version it should at least throw an exception instead of loading the default one.

}

@Test
void ensureNotLoadingDefaultClassPersistence() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this test that you're not still loading the file from /META-INF/persistence.xml?

@eric-maynard
Copy link
Contributor

No @guitcastro it was definitely there -- like I mentioned, I copied it directly from the existing default file. Have you done an end-to-end test using this change including bootstrapping Polaris? If so can you share the steps?

PolarisDiagnostics diagServices = new PolarisDefaultDiagServiceImpl();
PolarisEclipseLinkStore store = new PolarisEclipseLinkStore(diagServices);
PolarisEclipseLinkMetaStoreSessionImpl session =
new PolarisEclipseLinkMetaStoreSessionImpl(
store, Mockito.mock(), () -> "realm", null, "polaris-dev");
store, Mockito.mock(), () -> "realm", tmpFile.toString(), "polaris-dev");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this, Persistence.createEntityManagerFactory() will use the one in the jar, not the /tmp/%s-persistence.xml.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can try to remove persistence.xml from the project and see the issue.

@guitcastro
Copy link
Author

@aihuaxu @eric-maynard You are right, what happened is that my external configuration had a persistence unit also named polaris-dev and got merged with the one in the classpath. Thus my jakarta.persistence.jdbc.url took precedence from the class path and I was able to connect with my database (postgres).

@sfc-gh-aixu
Copy link
Contributor

@aihuaxu @eric-maynard You are right, what happened is that my external configuration had a persistence unit also named polaris-dev and got merged with the one in the classpath. Thus my jakarta.persistence.jdbc.url took precedence from the class path and I was able to connect with my database (postgres).

Yeah. So let's move forward with my workaround solution for now until we have a better one?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants