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

Problem with HibernateJpaConfiguration after migrating from com.sun.xml.bind:jaxb-impl to org.glassfish.jaxb:jaxb-runtime #606

Open
rcsilva83 opened this issue Oct 16, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@rcsilva83
Copy link

What version of OpenRewrite are you using?

I am using

  • Maven plugin v5.42.2
  • rewrite-spring v5.21.0

How are you running OpenRewrite?

I am using the Maven plugin, and my project is a single module project.

<plugin>
        <groupId>org.openrewrite.maven</groupId>
        <artifactId>rewrite-maven-plugin</artifactId>
        <version>5.42.2</version>
        <configuration>
          <activeRecipes>
            <recipe>org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_3</recipe>
          </activeRecipes>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.openrewrite.recipe</groupId>
            <artifactId>rewrite-spring</artifactId>
            <version>5.21.0</version>
          </dependency>
        </dependencies>
      </plugin>

What is the smallest, simplest way to reproduce the problem?

    <dependency>
      <groupId>com.sun.xml.bind</groupId>
      <artifactId>jaxb-impl</artifactId>
      <version>2.3.1</version>
    </dependency>

What did you expect to see?

No change.

What did you see instead?

    <dependency>
      <groupId>org.glassfish.jaxb</groupId>
      <artifactId>jaxb-runtime</artifactId>
    </dependency>

What is the full stack trace of any errors you encountered?

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: javax/xml/bind/annotation/XmlElement
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1806)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:954)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352)
	at my.company.app.App.main(App.java:14)
Caused by: java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlElement
	at com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector.<init>(JaxbAnnotationIntrospector.java:137)
	at com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector.<init>(JaxbAnnotationIntrospector.java:124)
	at com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule.setupModule(JaxbAnnotationModule.java:98)
	at com.fasterxml.jackson.databind.ObjectMapper.registerModule(ObjectMapper.java:908)
	at com.fasterxml.jackson.databind.ObjectMapper.registerModules(ObjectMapper.java:1110)
	at com.fasterxml.jackson.databind.ObjectMapper.findAndRegisterModules(ObjectMapper.java:1194)
	at org.hibernate.type.format.jackson.JacksonJsonFormatMapper.<init>(JacksonJsonFormatMapper.java:27)
	at org.hibernate.type.format.jackson.JacksonIntegration.<clinit>(JacksonIntegration.java:18)
	at org.hibernate.boot.internal.SessionFactoryOptionsBuilder.lambda$determineJsonFormatMapper$7(SessionFactoryOptionsBuilder.java:833)
	at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.resolveStrategy(StrategySelectorImpl.java:220)
	at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.resolveDefaultableStrategy(StrategySelectorImpl.java:180)
	at org.hibernate.boot.internal.SessionFactoryOptionsBuilder.determineJsonFormatMapper(SessionFactoryOptionsBuilder.java:829)
	at org.hibernate.boot.internal.SessionFactoryOptionsBuilder.<init>(SessionFactoryOptionsBuilder.java:313)
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.<init>(SessionFactoryBuilderImpl.java:50)
	at org.hibernate.boot.internal.DefaultSessionFactoryBuilderService.createSessionFactoryBuilder(DefaultSessionFactoryBuilderService.java:26)
	at org.hibernate.boot.internal.MetadataImpl.getSessionFactoryBuilder(MetadataImpl.java:169)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502)
	at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75)
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390)
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802)
	... 15 common frames omitted
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.XmlElement
	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:525)
	... 39 common frames omitted

Are you interested in contributing a fix to OpenRewrite?

Yes

@rcsilva83 rcsilva83 added the bug Something isn't working label Oct 16, 2024
@timtebeek
Copy link
Contributor

Hi @rcsilva83 , welcome back! The change made here might be spread across multiple repositories:
https://github.com/openrewrite/rewrite-hibernate
https://github.com/openrewrite/rewrite-migrate-java
https://github.com/openrewrite/rewrite-spring

We'd need to figure out if there's a missing parallel change to be made in rewrite-hibernate, or whether there's more to the one to one replacement that's done currently. Any help appreciated as I lack a bit of detail on which version of Hibernate you're using, as the HibernateJpaConfiguration class for v3.3.x itself does not refer to javax/xml/bind/annotation/XmlElement, but does refer to javax.sql.DataSource also referenced in

@rcsilva83
Copy link
Author

rcsilva83 commented Oct 21, 2024

Hi, @timtebeek !

I tracked this problem and it isn't related to HibernateJpaConfiguration but to Jackson. We use some Jackson annotations on some @Entity classes, so the error occurred on 'entityManagerFactory' bean initialization. We use jackson-module-jaxb-annotations package that depends on javax.xml.bind classes... So we had the javax.xml.bind:jaxb-api dependency declared, as we are using Java 11/17.

The problem is that, after running the UpgradeSpringBoot_3_3 recipe, javax.xml.bind:jaxb-api as replaced by jakarta.xml.bind:jakarta.xml.bind-api which is managed para Spring Boot to version 4.0.2. This version doesn't provide javax.xml.bind classes.

I found some recipes that do this change:

  • org.openrewrite.java.migrate.javax.AddJaxbDependencies which is called by org.openrewrite.java.migrate.Java8toJava11 called by org.openrewrite.java.migrate.UpgradeToJava17 called by org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0
  • org.openrewrite.java.migrate.jakarta.JavaxXmlBindMigrationToJakartaXmlBind which is called by org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta called by org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0

Given that, is there any way to tell OpenRewrite not to run that recipes or to ignore that dependency and leave it as it is?

@timtebeek
Copy link
Contributor

Thanks for diving in! The most convenient way to customizing an existing composite recipe is through the recipe builder at https://app.moderne.io/. We're working on getting that integrated into docs.openrewrite.org now that it's using Docusaurus, but that might take a while longer.

That said; looking at the changes I wonder if instead of removing recipes we should be adding a migration step instead:

With a change dependency to go from jackson-module-jaxb-annotations to jackson-module-jakarta-xmlbind-annotations and a change type to go from JaxbAnnotationModule to JakartaXmlBindAnnotationModule. What are your thoughts on adding those?

@rcsilva83
Copy link
Author

Actually, these dependencies are being pulled by external packages we depend on and they aren't update yet, unfortunately... I think, for my use case, it is better to make a new recipe using UpgradeSpringBoot_3_3 and then add javax.xml.bind:jaxb-api dependency. This way, we wouldn't need to maintain a custom UpgradeSpringBoot_3_3 recipe and having to manually update it, which seams a lot of work...

On the long term, don't you think this kind of change is a bit intrusive to make? I think situations like this, where the developer don't have full control on the migration to jakarta packages, may be quite common. What do you think?

In this case, I see 2 solutions:

  1. modify org.openrewrite.java.migrate.javax.AddJaxbDependencies and org.openrewrite.java.migrate.jakarta.JavaxXmlBindMigrationToJakartaXmlBind to, instead of changing the dependencies, just add jakarta.xml.bind:jakarta.xml.bind-api;
  2. Create a way to bypass certain changes on OpenRewrite, with 2 options:
    1. define a <inactiveRecipes> tag
    2. adding an comment like <!-- OpenRewrite OFF --> around the dependency we don't want OpenRewrite change;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Status: Backlog
Development

No branches or pull requests

2 participants