Home > Software design >  Using Spring Data 2.6.1 with Eclipselink and Jakarta 3, is it possible?
Using Spring Data 2.6.1 with Eclipselink and Jakarta 3, is it possible?

Time:12-10

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 with jakarta.persistence in the code and in persistence.xml

Now I am looking into configuring Spring Data to use Eclipselink with Jakarta 3.0.0, but I noticed Spring still depends on Jakarta 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.

  1. Is it possible to configure Spring Data to use Eclipselink 3 and Jakarta 3, or should I stick to the old namespace for now?
  2. 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.

CodePudding user response:

I found the answer in the Spring blog. Apparently the roadmap includes switching to the jakarta namespace "in Q4 2022":

As announced at SpringOne yesterday, Spring Framework 6 and Spring Boot 3 are planned towards a high-end baseline for their general availability in Q4 2022:

Java 17  (from Java 8-17 in the Spring Framework 5.3.x line)
Jakarta EE 9  (from Java EE 7-8 in the Spring Framework 5.3.x line)

This forward-looking baseline will provide significant benefits in our API design and integration efforts, shining through to your application code and future-proofing the framework as well as your applications for many years to come. However, it comes at a cost, of course: Spring Framework 6 and Spring Boot 3 based applications will require a minimum of JDK 17 at runtime, as well as a minimum of Tomcat 10 / Jetty 11 (for Jakarta EE 9 compatibility). Even more importantly, there might be some changes required in your application source code: e.g. the javax to jakarta namespace change in Jakarta EE 9 wherever you’re touching the Servlet API, JPA, Bean Validation, etc.

It is thus a matter of waiting until the change is rolled out by Spring.

  • Related