We are currently bumping dependency versions of a Spring project with persistence based on JPA with Eclipselink. During the upgrade process I learned about Eclipselink switching to Jakarta namespace starting with version 3.0 due to legal reasons as explained in this thread.
We succeeded in updating the code so that we use Jakarta Persistence API 3.0.0 independently from Spring Data. The migration is quite straight forward:
- Bump Eclipselink version to 3.0.x
- Add an explicit dependency to Jakarta 3
- Replace
javax.persistence
withjakarta.persistence
in the code and inpersistence.xml
Now I am looking into configuring Spring Data to use Eclipselink with Jakarta 3.0.0, but I noticed Spring still depends on JAXB 2.2.3. When I override the version in my Maven project, Spring Data complains on startup:
java.lang.NoClassDefFoundError: javax/persistence/EntityManagerFactory
at org.springframework.data.jpa.util.BeanDefinitionUtils.<clinit>(BeanDefinitionUtils.java:57)
at org.springframework.data.jpa.repository.support.EntityManagerBeanDefinitionRegistrarPostProcessor.postProcessBeanFactory(EntityManagerBeanDefinitionRegistrarPostProcessor.java:72)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:325)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:191)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:302)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290)
at com.mycompany.sandbox.springjpaeclipselinkfix.SpringApp.main(SpringApp.java:12)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.ClassNotFoundException: javax.persistence.EntityManagerFactory
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
... 18 common frames omitted
Apparently, it tries to create a persistence unit called default
and fails to load javax/persistence/EntityManagerFactory
(obviously, it is now in the jakarta.persistence
package).
My understanding is that Spring Data's code depends on Jakarta 2 and using Jakarta 3 is not supported. However, it should be possible to use Eclipselink as Spring Data persistence provider and Eclipselink does support Jakarta 3. I am puzzled at this point and I cannot find any current examples for this, only old stuff relating to javax.persistence
.
- Is it possible to configure Spring Data to use Eclipselink 3 and Jakarta 3, or should I stick to the old namespace for now?
- And if it's possible, can you point me to some current examples?
Obviously, one could fork Spring Data JPA's code and do the migration but I have not enough resources to maintain a branch.
I am posting also the relevant parts of my pom.xml (the rest resembles a standard Spring Data project):
<project>
...
<properties>
...
<jakarta-persistence.version>3.0.0</jakarta-persistence.version>
<eclipselink.version>3.1.0-M1</eclipselink.version>
</properties>
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</exclusion>
<exclusion>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
</dependency>
...
</dependencies>
<dependencyManagement>
<dependencies>
...
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>${eclipselink.version}</version>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>${jakarta-persistence.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
...
</project>
Other tags: Jakarta EE 9, Jakarta Persistence 3.0, Java 17.