Maven - Force to use dependency - spring

I made custom dependency which uses spring 4.x version and I include it in a project which uses spring 3.x version. When a method from this dependency is called it uses classes from spring 3.x version not from 4.x. Is it possible to force this dependency to use spring 4.x whereas the project itself will use spring 3.x ?

I don't think that is possible due to the fact that, when finally project is running, the dependencies are resolved on the basis of group id and artifact id and not on their version. Which is why your application is using 3.x dependency as it is overriding the one mentioned in the parent project. Hope this helps.

Yes, you can if you separate your application (which you probably don't want to). Another approach: You might think about using another class loader within the same JVM. This, however, leads to a probably bigger bunch of problems, especially using Spring.
Dzone article about loading the same class from libs with different versions.

As pvpkiran noted, you want to exclude the spring v3 transitive dependency from your custom artifact. From the maven documentation - Optional Dependencies and Dependency Exclusions:
<project>
...
<dependencies>
<dependency>
<groupId>sample.ProjectA</groupId>
<artifactId>Project-A</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion> <!-- declare the exclusion here -->
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

Related

Why does H2 database use Hibernate Core in Springboot application

I have a simple springboot application which uses H2 in memory db. I have used following dependency in my POM
spring-boot-starter-data-jpa
com.h2database.h2
When I start application, It automatically create Entity tables using Hibernate Dialect. I have no where mentioned about Hibernate in my POM. So why does this happening. Why Spring is using Hibernate Dialect. Do we have any option to change this dialect to some other dialect. please help.
Starter poms in the SpringBoot ecosystem bring a bag of dependencies, which have been tested and are proven to work together. It also saves you the hustle of managing the right dependencies versions.
You're using spring-boot-starter-data-jpa - which is a starter pom for JPA - the opinionated choice here is the usage of Hiberante as JPA provider.
If you look at the source of the pom file, you will see this definition:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<exclusions>
<exclusion>
<groupId>org.jboss.spec.javax.transaction</groupId>
<artifactId>jboss-transaction-api_1.2_spec</artifactId>
</exclusion>
</exclusions>
</dependency>
This is what brings hibernate to your project, although you have not explicitly declared it in your pom. The hibernate is downloaded as implicit dependency because of your spring-boot-starter-data-jpa starter pom.
Well you using "spring-boot-starter-data-jpa" and "starter" notion means that it has everythingfor it to work. If you would look to https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa/2.1.3.RELEASE , this dependency also includes hibernate-core.

Using spring-boot-starter dependency on a non boot project, Is a good practice?

lets say that I need to develop a not boot app to develop an application that uses redis cache to store and retrive data.
I can use the spring-boot-starter dependency instead adding multiple dependencies, and it is working fine.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>1.5.1.RELEASE</version>
</dependency>
Now my question..
Is it a good practice to add spring-boot-starter dependency on a non boot project?
Sure you can, just keep in mind that it will bring some transitive dependencies into your project, like org.springframework.spring-{context,beans,core,tx,...}.

What are the consequences of not using Spring Boot as the parent pom?

I have a multi module Maven project that share a common parent pom. Some of these modules will use Spring Boot but some will not. I don't want to use Spring Boot as the parent of MY parent pom and have unnecessary dependencies in modules that don't use them.
What are the consequences of not using the Spring Boot parent pom? Will everything still work with all the auto configured goodness? I am considering the following solution of putting this in my parent pom as an alternative
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.4.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
But I am pretty new to all this Maven stuff and Spring Boot so I don't want any unintended consequences or to declaw the capabilities of Spring Boot in any way. Can someone explain what (if anything) I will lose out on if I do this? Thanks!
The Reference Guide explains how to use Spring Boot without the spring-boot-starter-parent and what will happen. This answer also explains the difference between spring-boot-starter-parent and spring-boot-dependencies.
Summary: With both ways you get the powerful dependency management of all Spring Boot components and third party libraries. The spring-boot-starter-parent also configures some Maven plugins like spring-boot-maven-plugin for running mvn spring-boot:run.

Spring framework compatibility between various projects

I am learning Spring framework and while trying "various" sub-projects within this, I got this doubt.
Spring framework has "core spring" at the heart of it. Now, as the project grows, e.g. trying other features like: spring-mvc, spring-web flow , spring security etc. Are all those sub-projects part of same release. For example, if I look for spring 4.0.2 release, would all these sub-projects be included in this? (hence release for various sub-project with same number: 4.0.2).
If this is not correct, then how do we ensure to chose the compatible sub-projects?
Thanks
spring-mvc is part of the spring framework, the others are separate projects following their own versioning. In general there is a minimum version for the projects and most work fine with newer versions.
If you want to be sure use the Spring IO Platform to manage your dependencies.
In your pom add
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>1.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Then you can simply add the dependencies (without version) to your dependencies section
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
</dependencies>
For a list of managed dependencies (and version) check Appendix A of the reference guide.
Spring framework has "core spring" at the heart of it. Now, as the
project grows, e.g. trying other features like: spring-mvc, spring-web
flow , spring security etc. Are all those sub-projects part of same
release
spring-mvc and spring-web are both individual artifacts that you'll find within a single Spring release. They are versioned together, and you should always use the same version for all of them in any given project.
spring-security, however, is a completely different beast. It sits on top of Spring, but it's versioned completely separately. You need to make sure that the version of Spring Security you use is combined with a compatible version of Spring.

spring-boot-starter versus spring-boot-starter-xxx

I noticed that the Spring Boot Sample Data Redis declares the following dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
See here for full POM: https://github.com/spring-projects/spring-boot/blob/v1.0.0.RC4/spring-boot-samples/spring-boot-sample-data-redis/pom.xml
I see no mention of the <artifactId>spring-boot-starter-redis</artifactId>
My question is: when do I use spring-boot-starter versus spring-boot-starter-xxx where xxx is the name of the project (here Redis)?
The answer to the specific question: spring-boot-starter is a baseline for the others, and for standalone (non-web) apps that don't use any other Spring components - it has basic support for Spring, Logging, and Testing, but nothing else (no webapp features, no database etc.). Since all the other starters depend on it, once you use another one you can remove the vanilla starter. EDIT: see here https://github.com/spring-projects/spring-boot/commit/77fd127e09963a844f8fb4e574e1f0d9d3424d4e.
Up to you on the redis starter, but I would use the starter if it exists, since it will typically cut down on the number of dependencies you need to declare. The redis one actually doesn't add a lot of value (hence it didn't exist until recently), but it probably ought to be used in the sample.

Resources