Issue
I am trying to migrate a maven project that used to work with camel 2 and jdk 8. I am trying at the same time to use more recent version of spring and hibernate.
After cleaning my local maven .m2/ repo, "mvn clean install" works then trying to "mvn clean package exec:java", I have a java.lang.NoSuchMethodError that seems to be linked to spring-core
My spring xml configuration file imports a databaseconfig.xml file which is :
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd">
<!-- bean post processor to add advisor to repository bean so platform specific exceptions are caught efficiently ie. unchecked -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<!-- needed so entitymanager can be injected in spring inside pricevectordaojpa -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<context:property-placeholder location="classpath:config.properties"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driverClassName}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="${db.type}" />
<property name="showSql" value="false" />
</bean>
</property>
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.nodenet.domain" />
<property name="jpaProperties">
<props>
<prop key="hibernate.ejb.naming_strategy">${db.namingStrategy}</prop>
<prop key="hibernate.hbm2ddl.auto">${db.hbm2ddl}</prop>
</props>
</property>
</bean>
<bean id="jpa" class="org.apache.camel.component.jpa.JpaComponent">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="jpaTransactionManager"/>
</beans>
It looks like this is the file creating some issue because some spring-core class/dependency is not found because I receive the following error :
Following burki's comments, I have cleaned the transitive spring dependencies using enforcer maven plugin and exclusions in my pom.xml and it worked
Solution
I guess you have a mix of Spring dependencies with different versions. Probably there are transitive Spring dependencies pulled by other dependencies like ActiveMQ or whatever.
All Spring framework dependencies must have the same version, in your case 5.1.14.RELEASE.
Use the dependency management of your IDE to get a list of all project dependencies or use Maven dependency plugin to list a tree of your dependencies.
You can also use Maven enforcer plugin to resolve dependency conflicts. But I think it would not complain about individual Spring dependencies with an older version.
Alternative to self-management
Another strategy is to use the excellent work of the Spring Boot community to build an eco-system of dependency versions that works quite well.
Notice that the following definitions just add dependency management, not real dependencies!
You can use it by declaring the Spring Boot POM as your parent POM.
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.1.7.RELEASE</version>
<relativePath />
</parent>
If you don't use Spring Boot or your parent is already in use, you can also use only the dependency management part. This version only defines dependency versions while the parent POM also defines Maven plugin versions.
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.7.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
With one of these definitions in your POM you can omit most dependency versions to use the versions already defined by Spring Boot.
See here for the dependency definitions of Spring Boot version 2.1.7 as an example.
Both variations are described in the Spring Boot docs for further details.
Answered By - burki
Answer Checked By - David Marino (JavaFixing Volunteer)