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

IllegalArgumentException: Unable to locate persister [SPR-16233] #20780

Open
spring-projects-issues opened this issue Nov 25, 2017 · 5 comments
Open

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented Nov 25, 2017

Mohamad ABBAS opened SPR-16233 and commented

Hello,

I've created a sample project with two modules:

  • The first module example-project is a spring project that contains a JPA entity + a service class and a DAO class for this entity. (I configure this entity inside an orm.xml file + the persistence unit inside a persist.xml file).
  • The second module example-project-boot is a simple spring-boot project that calls the service class of the first module.

Please find below the codebase of this project (you can also find it here).

When I run this project with IntelliJ or Eclipse, everything works as expected.

When I package this same project as a fat jar, then I try to run it, I am getting an

IllegalArgumentException: Unable to locate persister.

I noticed that, on startup, a call is made to method

org.springframework.orm.jpa.persistenceunit.PersistenceUnitReader#determinePersistenceUnitRootUrl

with /Users/mabbas/example-project-parent/example-project-boot/target/example-project-boot-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/example-project.jar!/META-INF/persist.xml

and this method is returning /Users/mabbas/example-project-parent/example-project-boot/target/example-project-boot-0.0.1-SNAPSHOT.jar

instead of

/Users/mabbas/example-project-parent/example-project-boot/target/example-project-boot-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/example-project.jar (the root of persist.xml is example-project and not example-project-boot).

Because of this result, I think that the entity defined inside example-project.jar is never loaded and then the exception is thrown.

I have first created a spring-boot issue here, but it seems that this problem is more about spring-orm than spring-boot.

Thanks in advance,


Affects: 4.3.12

Reference URL: spring-projects/spring-boot#11144

Attachments:

1 votes, 4 watchers

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Nov 28, 2017

Stéphane Nicoll commented

Thanks for the sample.

That setup is super unusual, have you considered migrating it (i.e. let Spring Boot creates the datasource rather than doing everything yourself? or configure things at least in one place?). Looking at the code you are creating the entity manager in one module and the persistence unit in another. Yet the persistence unit is linked so you have an inverse dependency from a configuration standpoint.

The URL that is computed is actually correct (remember, it is a default URL that we compute as a fallback because JPA requires one). I've tried to force the use of orm.xml by adding the following to your java configuration but didn't manage to start your application.

persistenceUnitManager.setMappingResources("classpath:/META-INF/orm.xml");

Loading

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Nov 28, 2017

Mohamad ABBAS commented

Thank you, Stéphane for your comment.

I completely agree with you; it is super unusual. But unfortunately, in my real project, I have a dependency on three legacy JARs, each of them declares a persistent unit, and those JARs cannot be modified.

I made a test by intercepting the call, in my IDE, to method

org.springframework.orm.jpa.persistenceunit.PersistenceUnitReader#determinePersistenceUnitRootUrl

and when i replace the result of this method with

/Users/mabbas/m2/repository/com/example/example-project/0.0.1-SNAPSHOT/example-project-0.0.1-SNAPSHOT.jar

instead of

/Users/mabbas/example-project-parent/example-project-boot/target/example-project-boot-0.0.1-SNAPSHOT.jar

it resolves the problem. This is why I was thinking about a bug in determinePersistenceUnitRootUrl.

As a workaround to this problem, and instead of building a fat jar, i can extract all the dependencies of my project to a 'lib' directory and point the classpath to this directory when running the application. It resolves my problem but of course, it is not the perfect solution.

Loading

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Nov 29, 2017

Stéphane Nicoll commented

Understood. Just to confirm, the behaviour of determinePersistenceUnitRootUrl is correct but won't work in a Spring Boot app. I am actually surprised that setting the path to mapping resources doesn't work either. Perhaps Juergen Hoeller can chime in here?

Loading

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jul 24, 2018

Thomas Heigl commented

I ran into this issue with my app as well. I solved it by deleting all my persistence.xml files and using Spring support for entity scanning like this:

final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(dataSource());
emf.setPackagesToScan("com.my.module1", "com.my.module2"); 

My orm.xml files are still picked up and everything works as expected.

Loading

@ajacob
Copy link

@ajacob ajacob commented May 1, 2020

I have a very similar setup as Mohamad, in my case using EclipseLink.

The persistence.xml is in an inner jar of the spring-boot fat jar, configured with exclude-unlisted-classes to false.

When spring configures the PersistenceUnitInfo it uses PersistenceUnitReader.determinePersistenceUnitRootUrl which gives as a root URL the fat jar (and not the inner jar containing the persistence.xm).

When EclipseLink tries to load it's entities through classpath scanning, it's not going to get down to inner jars but will only consider classes from the fat jar.

In turn, entities present in the inner jar that holds the persistence.xml file are not seen.

I tested to change the root url returned by PersistenceUnitReader.determinePersistenceUnitRootUrl to point to the inner jar and it fixes the issue.

@snicoll if you confirm that it is the correct behavior, may be I should open an issue in EclipseLink project ?

It's quite misleading because it works well inside IDE's but fails when running as a spring boot fat jar.

Loading

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

Successfully merging a pull request may close this issue.

None yet
2 participants