Reputation: 964
We have file payment.jar
that developed with Spring Framework 3.1.2 . We need to use it as a dependency on a new project that its version is Spring Framework 5.x .
Problem: When payment.jar
used as a dependency, the payment.jar
transitive dependencies add to project class-path so in cause conflicting Spring Framework 3 and Spring Framework 5.
I tried solutions:
create-an-executable-jar-with-dependencies-using-maven
there is no success, the fat JAR, adds Spring Framework 3 to project. (what I am doing wrong!)
because of using spring-ibatis
implementation in payment.jar
it is not worked. Spring Framework new versions do not support ibatis.
Error:
Caused by: java.lang.ClassNotFoundException: org.springframework.orm.ibatis.support.SqlMapClientDaoSupport
my requirement:
I need to use payment.jar
(with Spring Framework 3.1.2) as a dependency on new project with Spring Framework 5.x without problem mentioned above.
Upvotes: 4
Views: 1235
Reputation: 3196
The ideal solution would be to update everything to Spring 5 or deploy payment.jar separately as a microservice as others mentioned. But this is not the core part of your question, maybe you have some unavoidable requirements. So as @tomer-shahar said the solution is to use maven shade plugin.
This kind of conflicts happen a lot when you use open source libraries sharing the same libraries but with different versions.
The maven shade plugin allows renaming/recolocating the packages selected avoiding conflicts within versions. The drawback is that some classes will be duplicated (so it is far from ideal). See the example below:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>spring321-payment-shaded</finalName>
<relocations>
<relocation>
<pattern>spring.package</pattern>
<shadedPattern>shaded.spring.package</shadedPattern>
</relocation>
</relocations>
<artifactSet>
<includes>
<include>*:*</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
And then add as dependency to the Spring 5 project this shaded library with all the renaming/rellocation done. I used this interesting article where all the details are fully described.
Upvotes: 1
Reputation: 21
The best option for this is to upgrade this manually. Even if you will do this with Spring 3 jar, you will land with a lot of issues while compiling and running.
Upvotes: 1
Reputation: 343
Though I have not done this with spring specifically, the general concept of what you are trying to accomplish is called shading.
https://softwareengineering.stackexchange.com/questions/297276/what-is-a-shaded-java-dependency
The reason the fat jar didn't work is because all jars were loaded to the classpath, and the wrong one will be chosen for at least on of the dependencies.
What you need to do is change the package name in both a dependency and the depending jar (in your case spring 3 and payment jar), so you basically end up with two pairs of dependencies that don't overlap.
This is relatively simple to do in maven and similar tools. See the link for more details.
Upvotes: 0
Reputation: 52746
Your wish
I need to use payment.jar (with Spring Framework 3.1.2) as a dependency on new project with Spring Framework 5.x without problem mentioned above.
You cannot do it. Because the mismatching of version of dependencies. It is not backward compatible between many things, many version of iBatis, Spring Framework, payment.jar
and other dependencies.
You must upgrade it manually.
Upvotes: 2
Reputation: 4838
I suggest you to convert your jar in Spring 5 and MyBatis. I think it's the better solution in terms of mantenibility and compatibility. Migrate to iBatis to MyBatis does not a big problem, I think.
I had a working project that uses Spring 5 and My-Batis 3. I encountered some problem to configure it, but in the end, I solved everything. Just check the POM configuration and the Spring configuration.
In the following lines of code, you can read the project pom (I removed useless part of the file for your problem).
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>it.dummy</groupId>
<artifactId>dummy</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Dummy App</name>
<url>http://maven.apache.org</url>
<properties>
<java-source.version>1.8</java-source.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.skip.tests>true</maven.skip.tests>
<servlet-api.version>3.1.0</servlet-api.version>
<spring.version>5.0.7.RELEASE</spring.version>
<swagger.version>2.9.2</swagger.version>
<jackson.version>2.9.6</jackson.version>
<mybatis-spring>1.3.2</mybatis-spring>
<junit.version>4.12</junit.version>
<frontend-maven-plugin.version>1.4</frontend-maven-plugin.version>
<mapstruct.version>1.2.0.Final</mapstruct.version>
</properties>
<dependencies>
<!-- -->
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct -->
<!-- https://github.com/mapstruct/mapstruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<!-- cucumber -->
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.14.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/info.cukes/cucumber-java -->
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>1.2.5</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/info.cukes/cucumber-junit -->
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>1.2.5</version>
<scope>test</scope>
</dependency>
<!-- test -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet-api.version}</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-rest-core -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-core</artifactId>
<version>3.0.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring Security Artifacts - START -->
<!-- http://mvnrepository.com/artifact/org.springframework.security/spring-security-web%20 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- http://mvnrepository.com/artifact/org.springframework.security/spring-security-config%20 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring Security Artifacts - END -->
<!-- Swagger - BEGIN -->
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<!-- Swagger - END -->
<!-- json -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9</version>
</dependency>
</dependencies>
</project>
Just remember to check always the dependencies tree to avoid to have indesiderate Spring jars.
I have different file for Spring configuration. I attach only the interesting one.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close">
<property name="URL" value="jdbc:oracle:thin:@xxx:yyy:zzz" />
<property name="user" value="aaa"/>
<property name="password" value="bbb"/>
<property name="connectionCachingEnabled" value="true" />
</bean>
<bean id="transactionManagerNG" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="sqlSessionFactoryNG" class="org.mybatis.spring.SqlSessionFactoryBean" name="SqlSessionFactoryOrarioStandardDao">
<property name="dataSource" ref="dataSource" />
<!-- 1. Where is the xml for query's definitions -->
<property name="mapperLocations" value="classpath:com/dummy/persistence/dao/*.xml" />
<!-- 2. My-batis configuration -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!-- 3. My-batis type alias package -->
<property name="typeAliasesPackage" value="com.dummy.persistence.model" />
</bean>
<!-- 4. needed to parse Java DAO interfaces -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="it.insiel.sanita.farmacieng.persistence.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryNG"/>
</bean>
<tx:annotation-driven/>
</beans>
In the above Spring file you will find:
Last but not least the My-batis configuration file mybatis-config.xml
, that I put in the same folder of Spring configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- http://mybatis.org/dtd/ -->
<configuration>
<settings>
<setting name="logImpl" value="LOG4J"/>
<setting name="cacheEnabled" value="true"/>
<setting name="defaultStatementTimeout" value="3000"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="jdbcTypeForNull" value="NULL" />
</settings>
</configuration>
Upvotes: 0
Reputation: 311
If the Spring versions are as incompatible as it sounds as though they are, you're probably going to have to recompile either the jar or the project so that they're using the same version of Spring.
If that's impossible (e.g. if you don't have source for the jar), you might be able to wrap the payment jar up in a microservice so that it's running in a different process, and talk to it via XML-RPC or SOAP.
Upvotes: 7