Search code examples
javaspring-bootjdbcheroku-postgresdispatch

Upgrading Heroku Spring app from Java 7 to Java 11, JDBC is not able to connect to PostgreSQL anymore


I am trying to upgrade my Heroku app from Java 7 to 11. Previously, everything was working fine in the Java 7 version. Since Heroku is now forcing all apps connecting to PostgreSQL to use sslmode=require, I have to upgrade my pom.xml PostgreSQL JDBC driver version to adapt Heroku latest, PostgreSQL 13 I believe.

So the steps I took Are:

  1. Updated my pom.xml with new dependency, I believe these are related dependency need to updated:

    <dependency>
        <groupId>org.hsqldb</groupId>
        <artifactId>hsqldb</artifactId>
        <version>2.2.8</version>
    </dependency>
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.1.4</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-dbcp2</artifactId>
        <version>2.7.0</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>3.6.10.Final</version>
    </dependency>
    
  2. and my dispatcher-servlet.xml config (followed https://devcenter.heroku.com/articles/heroku-postgresql#heroku-postgres-ssl):

    <beans profile="prod">
        <bean class="java.net.URI" id="dbUrl">
            <constructor-arg value="#{systemEnvironment['DATABASE_URL']}"/>
        </bean>
    
        <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
            <property name="url" value="#{ 'jdbc:postgresql://' + @dbUrl.getHost() + ':' + @dbUrl.getPort() + @dbUrl.getPath() + '?sslmode=require' }"/>
            <property name="username" value="#{ @dbUrl.getUserInfo().split(':')[0] }"/>
            <property name="password" value="#{ @dbUrl.getUserInfo().split(':')[1] }"/>
        </bean>
    
        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
            </property>
            <property name="jpaProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
                    <prop key="hibernate.show_sql">true</prop>
                    <!-- change this to 'verify' before running as a production app -->
                    <prop key="hibernate.hbm2ddl.auto">update</prop>
                </props>
            </property>
        </bean>
    </beans>
    
  3. And system.properties

    java.runtime.version=11
    

However, it is giving error:

    : at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
    2021-03-14T15:19:48.608195+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)
    2021-03-14T15:19:48.608195+00:00 app[web.1]: at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
    2021-03-14T15:19:48.608196+00:00 app[web.1]: ... 26 more
    2021-03-14T15:19:48.608473+00:00 app[web.1]: Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#3c1bf779': Cannot resolve reference to bean 'clientAuthenticationEntryPoint' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientAuthenticationEntryPoint' defined in ServletContext resource [/WEB-INF/rest-dispatcher-servlet-security.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
    2021-03-14T15:19:48.608474+00:00 app[web.1]: at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:334)
    2021-03-14T15:19:48.608474+00:00 app[web.1]: at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
    2021-03-14T15:19:48.608475+00:00 app[web.1]: at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:637)
    2021-03-14T15:19:48.608475+00:00 app[web.1]: at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:145)
    2021-03-14T15:19:48.608476+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1077)
    2021-03-14T15:19:48.608476+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:981)
    2021-03-14T15:19:48.608476+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:487)
    2021-03-14T15:19:48.608477+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
    2021-03-14T15:19:48.608477+00:00 app[web.1]: at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:276)
    2021-03-14T15:19:48.608478+00:00 app[web.1]: ... 40 more
    2021-03-14T15:19:48.608479+00:00 app[web.1]: Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientAuthenticationEntryPoint' defined in ServletContext resource [/WEB-INF/rest-dispatcher-servlet-security.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
    2021-03-14T15:19:48.608479+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1039)
    2021-03-14T15:19:48.608479+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:985)
    2021-03-14T15:19:48.608480+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:487)
    2021-03-14T15:19:48.608480+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
    2021-03-14T15:19:48.608481+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
    2021-03-14T15:19:48.608481+00:00 app[web.1]: at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    2021-03-14T15:19:48.608481+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
    2021-03-14T15:19:48.608482+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)
    2021-03-14T15:19:48.608482+00:00 app[web.1]: at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
    2021-03-14T15:19:48.608483+00:00 app[web.1]: ... 48 more
    2021-03-14T15:19:48.608484+00:00 app[web.1]: Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
    2021-03-14T15:19:48.608484+00:00 app[web.1]: at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163)
    2021-03-14T15:19:48.608489+00:00 app[web.1]: at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
    2021-03-14T15:19:48.608489+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1032)
    2021-03-14T15:19:48.608490+00:00 app[web.1]: ... 56 more

Updated error after updating Maven dependency as Flame239 suggested:

The pom.xml looks like this:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.0.1</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.13.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>5.2.13.RELEASE</version>
</dependency>
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <version>2.2.8</version>
</dependency>
<dependency>
  <groupId>org.postgresql</groupId>
  <artifactId>postgresql</artifactId>
  <version>42.2.1</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.7.0</version>
</dependency>       
<!-- API, java.xml.bind module -->
<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>2.3.2</version>
</dependency>

<!-- Runtime, com.sun.xml.bind module -->
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.2</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>5.3.20.Final</version>
</dependency>

I get a different error now:

    2021-03-14T16:42:12.145844+00:00 app[web.1]: at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
2021-03-14T16:42:12.145844+00:00 app[web.1]: at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
2021-03-14T16:42:12.145844+00:00 app[web.1]: at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
2021-03-14T16:42:12.145844+00:00 app[web.1]: at java.base/java.lang.Thread.run(Thread.java:834)
2021-03-14T16:42:12.145855+00:00 app[web.1]: Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customerServiceImpl' defined in file [/app/target/tomcat.4978/work/Tomcat/localhost/_/WEB-INF/classes/com/myproject/service/CustomerServiceImpl.class]: Post-processing of merged bean definition failed; nested exception is java.lang.NoSuchMethodError: 'javax.persistence.SynchronizationType javax.persistence.PersistenceContext.synchronization()'
2021-03-14T16:42:12.145856+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:571)
2021-03-14T16:42:12.145856+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
2021-03-14T16:42:12.145856+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
2021-03-14T16:42:12.145857+00:00 app[web.1]: at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
2021-03-14T16:42:12.145857+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
2021-03-14T16:42:12.145857+00:00 app[web.1]: at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
2021-03-14T16:42:12.145857+00:00 app[web.1]: at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
2021-03-14T16:42:12.145858+00:00 app[web.1]: at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1307)
2021-03-14T16:42:12.145858+00:00 app[web.1]: at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227)
2021-03-14T16:42:12.145858+00:00 app[web.1]: at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657)
2021-03-14T16:42:12.145859+00:00 app[web.1]: ... 25 more
2021-03-14T16:42:12.145859+00:00 app[web.1]: Caused by: java.lang.NoSuchMethodError: 'javax.persistence.SynchronizationType javax.persistence.PersistenceContext.synchronization()'
2021-03-14T16:42:12.145859+00:00 app[web.1]: at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.<init>(PersistenceAnnotationBeanPostProcessor.java:670)
2021-03-14T16:42:12.145860+00:00 app[web.1]: at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.lambda$buildPersistenceMetadata$0(PersistenceAnnotationBeanPostProcessor.java:433)
2021-03-14T16:42:12.145860+00:00 app[web.1]: at org.springframework.util.ReflectionUtils.doWithLocalFields(ReflectionUtils.java:668)
2021-03-14T16:42:12.145860+00:00 app[web.1]: at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.buildPersistenceMetadata(PersistenceAnnotationBeanPostProcessor.java:427)
2021-03-14T16:42:12.145861+00:00 app[web.1]: at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findPersistenceMetadata(PersistenceAnnotationBeanPostProcessor.java:408)
2021-03-14T16:42:12.145861+00:00 app[web.1]: at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(PersistenceAnnotationBeanPostProcessor.java:335)

Any other suggestions?


Solution

  • As errors says: java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException

    In short: in Java 9 JAXB APIs was removed from JDK, so you have to add this dependency manually

    This question will give more details why it happens.

    Here you will find how to fix it for spring and they suggest to add this dependency:

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