How do big bundled open source projects like Spring Boot ensure compatibility between modules? - spring

Spring Boot contains loads of dependencies: Spring Framework, Spring Data, etc. How do the Spring maintainers accomplish releasing everything while different teams work on different Spring projects?
We have a similar situation, we have 4-5 teams each making different libraries which are used by other teams. We prefer to be able to allow teams to release independently but this is a huge undertaking to ensure binary compatibility of interface and behaviour.

Each release of Spring Boot provides a curated list of dependencies it supports. In practice, you do not need to provide a version for any of these dependencies in your build configuration as Spring Boot is managing that for you. When you upgrade Spring Boot itself, these dependencies will be upgraded as well in a consistent way.
The curated list contains all the spring modules that you can use with Spring Boot as well as a refined list of third party libraries. The list is available as a standard Bills of Materials (spring-boot-dependencies) and additional dedicated support for Maven and Gradle are available as well.
URL: https://docs.spring.io/spring-boot/docs/1.3.8.RELEASE/reference/html/using-boot-build-systems.html

Related

Is it possible to write lib for projects using different versions of Spring?

I'm writing a lib for projects using different versions of Spring. The lib itself is based on Spring too ( more precisely, Spring Cloud Sleuth). For now, I use different versions for different projects( version1 for projects using Spring boot 2.0.x, version2 for projects using Spring boot 2.3.x, etc). Apparently, the maintenance took a lot of time and made some confusion. Is there a runtime mechanism like #Conditional but for dependencies?
First, check the Spring Cloud compatibility matrix. As you can see, different Spring Cloud versions support different Boot versions.
I would do the same for your library and maintain different versions of it.
Your can have optional dependencies on Sleuth and set things up using #Conditional annotations (e.g.: #ConditionalOnClass) but I would not recommend that.
Sleuth 2.2.x (Hoxton) uses Brave's API (btw 2.x is not supported anymore, you should upgrade). Sleuth 3.0.x (2020.0.x aka Ilford) and 3.1.x (2021.0.x aka Jubilee) have their own API and they abstract the tracer libraries away. You can use these interfaces/classes to detect the version and configure them differently but when you compile your library you can have classpath issues because you have 2.2.x, 3.0.x, and 3.1.x on your classpath.
Another thing you can do is modularize your library and put all of those things that does not depend on Spring into a "core" module then create smaller adapter/autoconfiguration/starter modules for every version of Spring Cloud you want to support.

Spring starter dependencies

I just started out learning spring boot and I can immediately see that there are two types of dependencies, at least those I have encountered,those labelled starter and those that are not. My question is what is the difference and when should I use one over the other.
The starter dependencies are just dependencies that contain a bunch of transitive dependencies. Try to Ctrl + Click them, you will see what other dependencies they contain.
Spring has packaged these dependencies to make your life easier and make you able to add all common dependencies needed to do certain tasks.
This is all based on their motto of convention over configuration.
The short answer is that those "starter" packages are autoconfigurable. They don't need any particular configuration to work out of the box, but you may configure them to fit your particular needs, which makes them perfect for the Spring Boot's focus on simplicity.
Those dependencies are thought to be used with Spring Boot, but the others were/are there for Spring (non Boot) projects. I haven't really dived in to them to pinpoint specific differences, but they pretty much work the same (I've successfuly build and run projects with autoconfigurable dependencies in Spring non Boot projects, but take that with a grain of salt, as those were practice projects in controlled environments).
Ideally you'd want to use 'regular' dependencies with non Boot projects and you'd want to use 'starters' for Boot projects, but it is not a hard rule. Just make sure to use properly mantained dependencies.

Is bad practice to have spring boot starter project for starter project?

Spring boot starter project provides extensive set of functionalities auto configured. But for our application we want to have only a subset of functionality. May be only one feature out of the spring boot starter project. So is it advised to have custom starter project on top of spring boot provided starter project to mask some of the features or write new starter project directly from lower level libraries?
Spring boot starter project provides extensive set of functionalities
auto configured
There are two separate concerns you are talking about.
I think the auto configured part is something which is Spring boot's opinionated way of configuring. As an example if in classpath it finds a in-memory database library ( like H2) it automatically creates a datasource (pointing to embedded in-memory database) which is available for autowiring without you writing the configuration in a Java config class. Of course you can create you own datasource of choice by including appropriate driver jar for that database. Similarly lots of other configurations are done by default by classpath scanning and availability of certain jars and classes.
The second part - is more of a dependency issue in general. Say you want to use web mvc part in Spring boot. This will require a consistent set of dependencies and transitive dependencies as well. Rather than finding and declaring the dependency in your build tool of choice ( maven, gradle etc) it has created the concept of starter projects where you simply mention the parent and all the right dependencies would be pulled on. This gives a great way to correctly lock your dependencies. However if you want to include any different version than what is provided by boot starter ( provided there is no compatibility issues with those different versions) you can still add explicitly in your build tool. For e.g., maven will by default include the highest version of a particular dependency among all available via transitive dependencies when it resolves dependency for an artifact.

Spring Boot: starter modules - do i need to keep them?

I am starting yet another project based on spring boot.
For start it's pretty obvious and easy to go with spring-boot-starter dependencies. But for example I have projects which already live for 2 years and it becomes more challenging and time consuming to upgrade versions of those modules. Mostly because lot's of things auto-confugured under the hood, and there is only hidden knowledge to control them.
What would be the best practice to plan the new project for long term support and be able without any problems upgrade spring boot versions?
Are starter modules really just for start? After some time they should be fully replaced with pure modules from Spring framework?
The intention of Spring Starter modules is not necessarily intended to be aimed at being replaced by manually defining your dependencies. In fact, it's more the opposite, as the set of dependencies defined in starters are tested to work as expected as it provides an opinionated set.
The pattern laid out by Spring Boot is two fold, autoconfigure modules and starter modules:
Autoconfigure modules that generally do not, unless necessary, require dependencies downstream. Autoconfigure modules will compile against one or many modules, and then enable configurations within your application context based on rules generally governed by what libraries and components are available at context initialization. This is useful as it provides reasonable baseline configurations that can be used in a variety of scenarios, without enforcing what particular libraries/vendors downstream consumers must use. However, because they are intended to be used in a variety of scenarios, it is incumbent upon you as the consumer to ensure you have a valid context.
Starter modules are complimentary to autoconfigure modules. They provide an opinionated set of dependencies downstream, along with autoconfigure dependencies, to allow consumers to get started. Generally, but not necessarily, starter modules themselves are fairly empty and often do not contain any classes, as their main purpose is to just provide a POM that can be used for transitive dependencies.
Although your query is not about developing custom auto-configuration, the Spring Boot documentation regarding developing your own auto-configuration does a good job explaining the pattern.
Traditionally when we develop a Spring application, we need to include all the required dependencies (spring or other framework jar) by ourself. Starter is intended to minimize such configuration . It does not have any codes or logic inside . You can think that it is just a configuration setting which pre-defines some dependencies. Including a starter will automatically include all of the dependencies defined by this starter to your project thanks to the build system (e.g Maven) 's "transitive dependencies" features.
So you can see that starter provides one of the SpringBoot philosophy, which enable developer to create a Spring app that can "just run" quickly without much configuration , it definitely will not be replaced by the Spring.

adding spring-data-rest ontop of spring-data-jpa

i created a maven project, and added all dependencies i need.
i have some repositories using the spring-data-jpa, and i added some integration tests.
now i need to add ontop of it spring-data-rest, if i understand it is based on springmvc.
but all examples i found, i need to add spring boot to start the app.
i noticed also all new spring projects use spring boot.
this means that i have to learn and use it for my projects?
how can i use spring-data-jpa+spring-data-jpa with an existing servlet3 project
The reason all examples are written using Boot is that Boot is indeed the way you should start a new Spring project these days. It free's from a lot of the tedious work of setting up the infrastructure, finding dependencies in the right version etc.
To use Spring Data REST without Boot, simply add the necessary dependencies to your project. The easiest way to do this is to use the Spring Data Release Train BOM (which will help you pulling in the correct matching versions) along side the version-less dependency declarations for Spring Data REST WebMVC and - in your case - Spring Data JPA.
Then go ahead and either register RepositoryRestMvcConvfiguration as Spring bean (either through XML configuration or JavaConfig).
All of this is also documented in the reference documentation.

Resources