How to set a version on a variable out of dependencies tag with Gradle? - gradle

I want to set the version of my dependencies in just one place in my Gradle (app/build.gradle) configuration file , to became easier to change in case of a update.
the problem is:
dependencies {
implementation 'com.google.android.gms:play-services-maps:12.0.0'
implementation 'com.google.android.gms:play-services-auth:12.0.0'
implementation 'com.google.firebase:firebase-core:12.0.0'
implementation 'com.google.firebase:firebase-auth:12.0.0'
implementation 'com.google.firebase:firebase-database:12.0.0'
implementation 'com.google.firebase:firebase-storage:12.0.0'
implementation 'com.google.firebase:firebase-messaging:12.0.0'
implementation 'com.google.android.gms:play-services-ads:12.0.0'
implementation 'com.github.bumptech.glide:glide:4.5.0'
}
Can you see that, i'm repiting the same version many times and this make slow and unprodutive to change all version to the next version.
Like in Maven i could just do like this:
<properties>
<org.springframework.version>5.0.8.RELEASE</org.springframework.version>
</properties>
After set the version, I just add like this:
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
</dependencies>
The last piece of Maven configuration did set the version in this parte:
${org.springframework.version}
How can I do the same in my gradle configuration?

the assumption, that they'd all would have the same version is categorically wrong ...
def glideVersion = "4.5.0"
dependencies {
implementation "com.google.android.gms:play-services-base:16.0.1"
implementation "com.google.android.gms:play-services-auth:16.0.1"
implementation "com.google.android.gms:play-services-maps:16.0.0"
implementation "com.google.android.gms:play-services-ads:16.0.0"
implementation "com.google.firebase:firebase-core:16.0.4"
implementation "com.google.firebase:firebase-auth:16.0.4"
implementation "com.google.firebase:firebase-database:16.0.3"
implementation "com.google.firebase:firebase-storage:16.0.3"
implementation "com.google.firebase:firebase-messaging:17.3.4"
implementation "com.github.bumptech.glide:glide:${glideVersion}"
}
one can also set project.ext properties with version numbers - or load them from external files.
ext {
glideVersion = "4.5.0"
...
}
and then use it with ${rootProject.ext.glideVersion} or ${project.ext.glideVersion}.
in general, it's not easier to change... just another way of organizing it.

Related

Dependency table for spring boot 2.4.3

I have a difficulty defining what dependencies versions are compatible with each other.
In my case i have this
I don't know for the spring boot 2.4.3 what versions of the dependencies below go with it or the cloud version to 2020.0.1.
How can i fix this for example i want to migrate the spring boot and spring cloud to its latest versions.
It is a good rule of thumb to not define the versions yourself but use BOMs and let them define the versions for you:
spring-boot-dependencies
spring-cloud-dependencies
In order to find out which BOMs to use, you can use this compatibility matrix or the endpoint that #spencergibb mentioned: https://start.spring.io/actuator/info.
If you want to use a Spring Project that is not in the BOM, most probably that Spring Project is not supported (e.g.: Netflix libraries by latest Spring Cloud as #spencergibb mentioned).
Update: here's a Gradle example but you can generate a whole project using Spring Initializer:
plugins {
id 'org.springframework.boot' version '2.4.3'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
repositories {
mavenCentral()
}
dependencyManagement {
imports {
mavenBom 'org.springframework.cloud:spring-cloud-dependencies:2020.0.1'
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j'
}
It might be because there are collisions between dependencies included from the start and your explicitly defined dependencies. For example, take this dependency: spring-cloud-contract
Your version: 2.1.5
2020.0.1 Spring cloud's supported version: 3.0.1 (check this link mentioned by #Jonatan)
Try to exclude built-in dependencies that you have explicitly defined. For Maven it would be:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.1</version>
<type>pom</type>
<scope>import</scope>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-verifier</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
But that might not work because not all libraries are backward compatible. I would suggest using default libraries provided by spring cloud and remove explicit dependencies.

spring-boot-starter-parent: Can this be included as dependency

I was understanding something in spring boot and to being with, used a very simple snippet, like adding this in pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
</parent>
As I understand <parent> in this context means that in my pom.xml, there we have a parent pom.xml (saw the pom.xml file for spring-boot-starter-parent) which will have list of dependencies.
The important thing is that it is only pom packaging, and NOT a real jar / binary (please correct if I am wrong)
I saw the following in mvn repository:
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<type>pom</type>
</dependency>
My doubt is:
How can we include it as an dependency , it is just a pom packaging (and not a real jar / war), which acts as central place which holds common dependencies? Is it allowed? I tried adding in my project, but saw errors in STS IDE.
How does this get downloaded? Can we see the contents of this "parent"
First off, you've probably missed the meaning of parent pom in this case.
Spring boot of any specific version (2.2.1 in this case) comes with a bunch of possible integrations with many technologies / libraries. So it provides "default" versions of the libraries to work with because its very hard to check that it compatible with all possible versions of all libraries. You can of course provide your own version but then you should test a compatibility as an application maintainer.
So If you'll checkout the source code of spring-boot-starter-parent pom, you'll see that it provides some plugins and plugin management and more importantly inherits from another pom called spring-boot-dependencies
Note it doesn't add any dependencies to your project. It only defines a dependencyManagement section. This means that once you'll use the dependency in your project (that inherits) from this pom, you don't have to specify a version, only group id and artifact id.
Again, that's because spring boot offers by default very specific versions of thirdparties - the version that it was verified that it's compatible with...
Now as for the second part of the question - indeed it doesn't make sense to include dependency with packaging pom like you've posted, could you please provide a link where exactly you've seen this?
Sometimes when people adopt spring boot in their projects they already have have some parent, so they can't use the inheritance, in this case they can use a very special maven scope "import" and use the dependency on pom treating it as BOM (bill of materials) - frankly a pretty advanced stuff in maven. But spring boot uses this feature for these cases.
The dependency inclusion looks like this:
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
Note, the `import line. From maven's site: This is meant to allow dependency management information such as versions and excludes be retrieved from a remote POM file.
Here is a tutorial about this topic
#CuriousMind, including the spring-boot-starter-parent as a dependency is like trying to instantiate an interface or Abstract Class in Java. As you noticed, its packaging is pom, meaning it is just a maven artifact to help configure your maven project. Jar and War will contain some java binaries. I think the MVN repository code automatically generate all sample as dependencies..

How to use gradle feature variant dependecies in tests?

I am migrating a Maven library project to Gradle. The original project also has optional dependencies. I use the java-library plugin but moving the formerly optional dependencies to implementation results in runtime dependencies instead of compile. So I tried the gradle feature variants which results in the right dependencies in the pom.xml. But doing so results is failing test compile as the dependencies of the feature variant are missing on the test compile classpath!
Here is my current setup in build.gradle:
apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'maven-publish'
sourceCompatibility = 1.8
java {
registerFeature('oSupport') {
usingSourceSet(sourceSets.main)
}
}
dependencies {
api 'my.compile:dep-a:1.0.0'
implementation 'my.runtime:dep-i:1.0.0'
oSupportApi 'my.optional:dep-o:1.0.0'
}
Let's assume there is a class O available from my.optional:dep-o. If I import O in any class in src/main/java it works perfectly. Also the dependencies are exported right to Maven (using gradle generatePomFileForMavenJavaPublication, see the dependencies from the generated pom.xml below). But any test in src/test/java using class O will not compile (import my.optional.O; creates error: package my.optional does not exist)
<dependencies>
<dependency>
<groupId>my.compile</groupId>
<artifactId>dep-a</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>my.rintime</groupId>
<artifactId>dep-r</artifactId>
<version>1.0.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>my.optional</groupId>
<artifactId>dep-0</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
</dependencies>
How to solve this? I know I could have used the nebula.optional-base plugin instead of the buildin Gradle feature variant but I would prefer the new gradle builtin support for optional dependencies instead.
PS: I use Java 8 and Gradle 5.6.2
This looks like a bug when the feature source set uses the main source set. Can you report on https://github.com/gradle/gradle/issues?
In the meantime, this should fix it:
configurations {
testCompileClasspath.extendsFrom(oSupportApi)
testRuntimeClasspath.extendsFrom(oSupportApi)
testRuntimeClasspath.extendsFrom(oSupportImplementation)
}
Really weird, I agree with #melix this seems to be a Gradle bug.
The following will fix it but should not be needed, imho:
dependencies {
api 'my.compile:dep-a:1.0.0'
implementation 'my.runtime:dep-i:1.0.0'
oSupportApi 'my.optional:dep-o:1.0.0'
testImplementation(project(":${project.name}")) {
capabilities {
requireCapability("${project.group}:${project.name}-o-support")
}
}
}
For this simplified setup with only one feature dependency could be replaced by testImplementation 'my.optional:dep-o:1.0.0' but for a general larger dependency list this approch avoids repetition of the dependencies as the extendsFrom solution of #melix.

Force latest version for maven dependencies

I have the following dependency (only so far) pom.xml
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.6.2.RELEASE</version>
</dependency>
This dependency obviously depends on other "dependencies" via it's pom.xml... when maven finished downloading these dependencies I noticed that it didn't grab the latest version of the Spring stuff (4.0.6.RELEASE)... it grabbed a 3.2.x version.
How can I force maven to grab the latest version of the Spring stuff? Do I need to explicitly modify my pom.xml to include all the dependencies or is there some "magic" I can use for this?
Thanks.
Spring "Bill Of Materials"
Salvation may come from special "bill of materials" POMs supported by Maven and published by Spring. Quoting from Maven "Bill Of Materials" Dependency in their manual:
It is possible to accidentally mix different versions of Spring JARs when using Maven. For example, you may find that a third-party library, or another Spring project, pulls in a transitive dependency to an older release. If you forget to explicitly declare a direct dependency yourself, all sorts of unexpected issues can arise.
To overcome such problems Maven supports the concept of a "bill of materials" (BOM) dependency. You can import the spring-framework-bom in your dependencyManagement section to ensure that all spring dependencies (both direct and transitive) are at the same version.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.0.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Would this work for you?
Looking at the spring-data-jpa artifact pom file, we can see that it has a parent called spring-data-parent with current version 1.4.2.RELEASE. It's pom describes dependencies and their versions. Currently spring version is at 3.2.10.RELEASE
One way you can possibly accomplish what you want is to add explicit dependency on spring artifacts. But you would still have to define their versions.

Is there a simple way to use a different Spring version?

I want to use latest Spring 4.1.x snapshot in my Spring Boot project.
Is there a simple way to override the version of all Spring dependencies, or should I include all required Spring dependencies with it's desired version manually?
Reason is I want experiment with Spring 4.1 #JsonView annotation in REST services.
If you're using Maven with spring-boot-starter-parent as the parent, you can override the spring.version property in your pom to change the version of Spring that you're using:
<properties>
<spring.version>4.1.0.BUILD-SNAPSHOT</spring.version>
</properties>
If you're using Gradle, you can achieve the same effect by using a resolution strategy to override the version of everything with the org.springframework group id:
configurations.all {
resolutionStrategy {
eachDependency {
if (it.requested.group == 'org.springframework') {
it.useVersion '4.1.0.BUILD-SNAPSHOT'
}
}
}
}
I once again needed this and previous block doesn't work anymore, causing already dependencies to be failed.
Anyway this works:
configurations.all {
resolutionStrategy {
eachDependency { DependencyResolveDetails details ->
if (details.requested.group == "org.springframework") {
details.useVersion "4.1.0.RC1"
}
}
}
}
Given that you're using Spring Boot, I'm guessing that you must be using either Maven or Gradle, but you don't say which. For Maven, you have a couple of things you might be able to do.
First, you could have a go at just forcing the Spring version in your pom.xml:
<properties>
<spring.version>4.1.0.BUILD-SNAPSHOT</spring.version>
</properties>
That ought to override the property which is defined in the spring-boot-dependencies project.
For more fine-grained control, use dependency management:
<dependencyManagement>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.0.BUILD-SNAPSHOT</version>
</dependency>
</dependencyManagement>

Resources