-1

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

1 Answers1

1

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.

burki
  • 6,741
  • 1
  • 15
  • 31
  • I run mvn dependency:tree -Dverbose and get a lot of "omitted for duplicate" or "omitted for conflict" like for example "org.springframework:spring-core:jar:5.2.3.RELEASE:compile - omitted for conflict with 5.1.14.RELEASE". Does it necessarily mean something is wrong ? How can I make sure all spring framework dependencies have the same version if I need some tools like camel-jpa that uses apparently a different older version of spring ? Is your comment on spring also valid for camel ie. all camel dependencies must have the same version ? – user2415586 Mar 03 '20 at 10:48
  • Normally, yes. It is very helpful to have the same version for all components of a "package" like Camel, Spring etc. In Spring it is a bit tricky because there are multiple packages like SpringBoot, Spring Cloud, Spring Framework with different versions. You can either exclude transitive dependencies you don't want to have or you can explicitly add a dependency in the desired version to "overwrite" another version. The enforcer plugin can help you with this. It lists all conflicts during the maven build. – burki Mar 03 '20 at 11:31
  • I just extended my answer, there is an alternative to the self-management of all dependency versions. You can use a defined eco-system curated by Spring Boot. – burki Mar 03 '20 at 11:46
  • I will first try to do it manually. I was never using as I thought it was when you have multiple parent/child pom.xml and I run separate simple one module programs here. Is dependencymanagement still useful in that case ? (still reading the doc about it and might be an obvious question. apologies for that). About my previous question, if camel-jpa artifact requires spring-core 5.2.3, how can I enforce that dependency on spring 5.1.14.RELEASE and does it even make sense ? Reading about the maven enforcer plugin you suggested, is it relevant in non multi-module project ? – user2415586 Mar 03 '20 at 12:07
  • Dependencies placed inside DependencyManagement are just to declare a desired version. The dependency itself (i.e. the JAR) is not included in your project. So it can be helpful for any Maven project. To prefer spring-core 5.1.14.RELEASE you have to explicitly declare the dependency with this version in your POM. Like this it should have priority. However, if camel-jpa does not work with this older version, you have a problem. – burki Mar 03 '20 at 12:27
  • I suggest that you start with a must-have component version, for example Camel 3.1.0 from your POM. Then you "agree" on the Spring Framework version Camel-3.1.0 needs (5.2.3) and try to align all Spring dependencies to this version. – burki Mar 03 '20 at 12:29
  • And yes, the enforcer plugin can be helpful for a simple project as well as multi-module projects. It is kind of obtrusive upfront, but you can avoid problem like yours in later stages :-) – burki Mar 03 '20 at 12:31
  • I have used the maven enforcer plugin and I see a couple of conflicted dependencies, notably 2 transitive spring dependencies. Following your advice, I began with camel 3-1 and then put almost on top of my pom.xml the desired spring 5.1.14.RELEASE version. However, that doesn't solve it as other spring version are required for activemq-camel artifact for example... and I don't manage to tweak the pom.xml to get only one spring version manually. When the enforcer fails, it doesn't tell you how to solve the conflicts. Is then that boot-spring solution the only one ? I haven't looked at it yet – user2415586 Mar 04 '20 at 10:45
  • is it what exclusions are made for ? if yes, does it mean I use dependency:tree to know the conflicts and then add exclusions in my pom to avoid packages like activemq to add other transitive dependencies ? sorry for basic questions, I will clean the posts later one. – user2415586 Mar 04 '20 at 11:41
  • Exactly! Use Enforcer to easily identify conflicts and then either exclude not needed "sub-dependencies" (transitive dependencies) from your dependencies or put the conflicting dependency in the desired version into the dependencyManagement section so that Maven prefers this version. – burki Mar 04 '20 at 13:38
  • ok I have cleaned manually the transitive dependencies using this technique. Now mvn enforcer:enforce is working and clean. However, it now seems my entityManagerFactory bean cannot be built. I will update the question to show code and error message – user2415586 Mar 04 '20 at 14:56
  • Have you still multiple Spring versions in the dependency tree? – burki Mar 04 '20 at 17:05
  • I don't think so. I've added the result of the command in the question and I don't see any spring conflict. Following your advice, I am with 5.2.3>RELEASE with spring and 5.15.11 with activemq. Also mvn enforcer:enforce is not throwing any error – user2415586 Mar 04 '20 at 17:23
  • I've been trying in the last hours to find simple pom.xml example with spring xml configuration of jpa entitymanagerfactory on the internet but it's all older versions like my previous one which was working (still with conflictual dependencies I previously never cared about until now) – user2415586 Mar 04 '20 at 17:25
  • Have you changed the hibernate version while cleaning up the dependency tree? The error says that the field `parallelCapableClassLoaderAvailable` is not available while it tries to create the entityManagerFactory. Sounds also like a version problem. You are now in the middle of dependency management work. You have to find a combination of needed software packages that is compatible. – burki Mar 05 '20 at 06:28
  • yes I tried to upgrade as many dependencies as possible to get recent versions. I tried another way by doing it incremental and I can indeed upgrade spring, camel, java and activemq without error. The problems arise when I use the recent version of hibernate... However, I see only one version of hibernate in local maven repo .m2/ and mvn enforcer:enforcer gives a clean result. still investigating – user2415586 Mar 05 '20 at 10:04
  • If hibernate does not have a dependency back to Spring, Camel, AMQ, it is (from a dependency perspective) absolutely ok to keep the older hibernate version. But yes, if you don't want to keep this version forever, sooner or later you have to investigate this new issue. – burki Mar 05 '20 at 11:22
  • By the way: to find a solution to your new hibernate problem it would be better to create a new question. If you change your question during the "problem evolution" the answers below it are not at all helpful for other people. – burki Mar 05 '20 at 11:24
  • ok I will conclude this one and tell how i did following your advices (thanks to enforcer plugin essentially) and create a new question. I am ok to keep this hibernate version for the moment but I will have to solve it sooner or later – user2415586 Mar 05 '20 at 12:57