{"id":3802,"date":"2026-04-20T09:29:50","date_gmt":"2026-04-20T13:29:50","guid":{"rendered":"https:\/\/www.mymiller.name\/wordpress\/?p=3802"},"modified":"2026-04-20T09:29:50","modified_gmt":"2026-04-20T13:29:50","slug":"taming-version-chaos-with-gradle-version-catalogs","status":"publish","type":"post","link":"https:\/\/www.mymiller.name\/wordpress\/gradle\/taming-version-chaos-with-gradle-version-catalogs\/","title":{"rendered":"Taming Version Chaos with Gradle Version Catalogs"},"content":{"rendered":"\n<div class=\"wp-block-jetpack-markdown\"><p>Keeping track of dependencies and their versions across a project can quickly become a nightmare, especially as your project grows. Manually updating versions in every module is tedious and error-prone. Enter <strong>Gradle Version Catalogs<\/strong>, your new best friend for managing dependencies!<\/p>\n<p>Version catalogs provide a centralized, type-safe way to define and access dependency versions and libraries in your Gradle projects. This means less code duplication, improved maintainability, and fewer headaches.<\/p>\n<p>Here\u2019s how to use version catalogs with Groovy Gradle and Kotlin Gradle:<\/p>\n<p><strong>1. Define Your <code>libs.versions.toml<\/code><\/strong><\/p>\n<p>Create a file named <code>libs.versions.toml<\/code> in the <code>gradle<\/code> directory of your project. This is where you\u2019ll define your versions and libraries:<\/p>\n<pre><code class=\"language-toml\">[versions]\nkotlin = &quot;1.8.20&quot;\nandroidx-core = &quot;1.10.1&quot;\nretrofit = &quot;2.9.0&quot;\nokhttp = &quot;4.11.0&quot;\nmy-app-version = &quot;1.2.3&quot; \/\/ Project version\n\n[libraries]\nandroidx-core = { module = &quot;androidx.core:core-ktx&quot;, version.ref = &quot;androidx-core&quot; }\nretrofit = { module = &quot;com.squareup.retrofit2:retrofit&quot;, version.ref = &quot;retrofit&quot; }\nokhttp = { module = &quot;com.squareup.okhttp3:okhttp&quot;, version.ref = &quot;okhttp&quot; }\n\n[bundles]\nnetwork = [&quot;retrofit&quot;, &quot;okhttp&quot;] \n<\/code><\/pre>\n<ul>\n<li><strong><code>[versions]<\/code>:<\/strong> Declare your dependency versions and your project version here.<\/li>\n<li><strong><code>[libraries]<\/code>:<\/strong> Define your dependencies, referencing the versions you declared.<\/li>\n<li><strong><code>[bundles]<\/code>:<\/strong> Group related libraries together (optional, but helpful).<\/li>\n<\/ul>\n<p><strong>2. Accessing in Your Build Files<\/strong><\/p>\n<p>Now, let\u2019s see how to use these versions in your different Gradle setups:<\/p>\n<p><strong>a) Groovy Gradle (<code>build.gradle<\/code>)<\/strong><\/p>\n<pre><code class=\"language-groovy\">android {\n    defaultConfig {\n        versionName libs.versions.myAppVersion.get()\n        versionCode 123 \/\/ You'll usually calculate this based on versionName\n        \/\/... other configurations\n    }\n}\n\ndependencies {\n    implementation libs.androidx.core\n    implementation libs.network \/\/ Using a bundle\n}\n<\/code><\/pre>\n<p><strong>b) Kotlin Gradle (<code>build.gradle.kts<\/code>)<\/strong><\/p>\n<pre><code class=\"language-kotlin\">android {\n    defaultConfig {\n        versionName = libs.versions.myAppVersion.get()\n        versionCode = 123 \/\/ You'll usually calculate this based on versionName\n        \/\/... other configurations\n    }\n}\n\ndependencies {\n    implementation(libs.androidx.core)\n    implementation(libs.network) \n}\n<\/code><\/pre>\n<p><strong>Important Notes on Versioning:<\/strong><\/p>\n<ul>\n<li><strong><code>versionName<\/code>:<\/strong> This is the user-facing version string (e.g., \u201c1.2.3\u201d).<\/li>\n<li><strong><code>versionCode<\/code>:<\/strong> This is an integer used internally by app stores to determine update order. It must increase with each release. You\u2019ll often have a scheme to calculate <code>versionCode<\/code> from <code>versionName<\/code> components.<\/li>\n<\/ul>\n<p><strong>Benefits of Version Catalogs<\/strong><\/p>\n<ul>\n<li><strong>Centralized Management:<\/strong> Single source of truth for all your dependency versions and your project version.<\/li>\n<li><strong>Type Safety:<\/strong> Reduces errors caused by typos or incorrect version names (especially helpful in Kotlin).<\/li>\n<li><strong>Improved Readability:<\/strong> Makes your build files cleaner and easier to understand.<\/li>\n<li><strong>Maintainability:<\/strong> Updating versions becomes much simpler \u2013 just change the value in the <code>libs.versions.toml<\/code> file.<\/li>\n<\/ul>\n<p><strong>Go Forth and Catalog!<\/strong><\/p>\n<p>Version catalogs are a powerful tool for managing dependencies and project versions in your Gradle projects. Embrace them and bring order to the chaos of versioning!<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":3804,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[460],"tags":[],"series":[],"class_list":["post-3802","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-gradle"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/01\/folder-154899_1280-png.avif","jetpack-related-posts":[{"id":3451,"url":"https:\/\/www.mymiller.name\/wordpress\/java\/streamlining-java-project-development-with-gradle-a-comprehensive-configuration-guide\/","url_meta":{"origin":3802,"position":0},"title":"Streamlining Java Project Development with Gradle: A Comprehensive Configuration Guide","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Setting up a Gradle project with subprojects involves a thoughtful configuration to ensure a smooth development process. In this article, we'll walk through the step-by-step process of configuring a Gradle project to incorporate essential tools and plugins such as Spotless, Javadoc, Dependency Check, License Info, SonarLint, JaCoCo, and Test Reporting.\u2026","rel":"","context":"In &quot;JAVA&quot;","block_context":{"text":"JAVA","link":"https:\/\/www.mymiller.name\/wordpress\/category\/java\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/04\/spreadsheet-309088_640.png?fit=640%2C626&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/04\/spreadsheet-309088_640.png?fit=640%2C626&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/04\/spreadsheet-309088_640.png?fit=640%2C626&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":3806,"url":"https:\/\/www.mymiller.name\/wordpress\/gradle\/sharing-is-caring-publishing-your-android-library-to-maven-central-with-gradle\/","url_meta":{"origin":3802,"position":1},"title":"Sharing is Caring: Publishing Your Library to Maven Central with Gradle","author":"Jeffery Miller","date":"December 23, 2025","format":false,"excerpt":"You\u2019ve built an awesome library, and now you want to share it with the world! Publishing to Maven Central makes your library easily accessible to developers through Gradle, Maven, and other build tools. This guide walks you through the process of publishing your Android library to Maven Central using both\u2026","rel":"","context":"In &quot;Gradle&quot;","block_context":{"text":"Gradle","link":"https:\/\/www.mymiller.name\/wordpress\/category\/gradle\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/01\/shelf-159852_1280-png.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/01\/shelf-159852_1280-png.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/01\/shelf-159852_1280-png.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/01\/shelf-159852_1280-png.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/01\/shelf-159852_1280-png.avif 3x"},"classes":[]},{"id":3811,"url":"https:\/\/www.mymiller.name\/wordpress\/angular\/streamline-your-workflow-generate-angular-services-from-spring-boot-rest-apis-with-gradle\/","url_meta":{"origin":3802,"position":2},"title":"Streamline Your Workflow: Generate Angular Services from Spring Boot REST APIs with Gradle","author":"Jeffery Miller","date":"February 24, 2025","format":false,"excerpt":"Integrating your Angular frontend with a Spring Boot backend can be a breeze if you automate the process of creating your Angular services. This post will show you how to leverage Gradle, OpenAPI (Swagger), and the OpenAPI Generator to generate type-safe Angular TypeScript services directly from your Spring Boot REST\u2026","rel":"","context":"In &quot;Angular&quot;","block_context":{"text":"Angular","link":"https:\/\/www.mymiller.name\/wordpress\/category\/angular\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/immune-defense-1359197_1280-jpg.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/immune-defense-1359197_1280-jpg.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/immune-defense-1359197_1280-jpg.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/immune-defense-1359197_1280-jpg.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/immune-defense-1359197_1280-jpg.avif 3x"},"classes":[]},{"id":3784,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_ai\/integrating-openl-tablets-with-a-spring-boot-microservice\/","url_meta":{"origin":3802,"position":3},"title":"Integrating OpenL Tablets with a Spring Boot Microservice","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"This post explains how to integrate OpenL Tablets with your Spring Boot microservice. We'll cover adding the necessary dependencies, configuring OpenL Tablets, and creating a service to use it. 1. Project Setup and Dependencies Begin by creating a Spring Boot project. Then, add the following OpenL Tablets dependencies to your\u2026","rel":"","context":"In &quot;Spring AI&quot;","block_context":{"text":"Spring AI","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_ai\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/business-1754904_1280-jpg.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/business-1754904_1280-jpg.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/business-1754904_1280-jpg.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/business-1754904_1280-jpg.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/business-1754904_1280-jpg.avif 3x"},"classes":[]},{"id":3444,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_discovery\/spring-boot-admin-server-with-spring-cloud-discovery\/","url_meta":{"origin":3802,"position":4},"title":"Spring Boot Admin Server with Spring Cloud Discovery","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Spring Boot Admin Server is a powerful tool for monitoring and managing Spring Boot applications. It provides a centralized dashboard for viewing application health, metrics, and logs. Spring Cloud Discovery, on the other hand, enables service registration and discovery for microservices-based applications. By integrating Spring Boot Admin Server with Spring\u2026","rel":"","context":"In &quot;Spring Discovery&quot;","block_context":{"text":"Spring Discovery","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_discovery\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2023\/11\/manhattan-3866140_640.jpg?fit=640%2C427&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2023\/11\/manhattan-3866140_640.jpg?fit=640%2C427&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2023\/11\/manhattan-3866140_640.jpg?fit=640%2C427&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":3961,"url":"https:\/\/www.mymiller.name\/wordpress\/spring\/spring4\/architecting-spring-boot-4-with-official-spring-grpc-support\/","url_meta":{"origin":3802,"position":5},"title":"Architecting Spring Boot 4 with Official Spring gRPC Support","author":"Jeffery Miller","date":"January 15, 2026","format":false,"excerpt":"For years, the Spring community relied on excellent third-party starters (like net.devh) to bridge the gap between Spring Boot and gRPC. With the evolution of Spring Boot 4 and the official Spring gRPC project, we now have native support that aligns perfectly with Spring's dependency injection, observability, and configuration models.\u2026","rel":"","context":"In &quot;Spring4&quot;","block_context":{"text":"Spring4","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring\/spring4\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/01\/Gemini_Generated_Image_3yqio33yqio33yqi.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/01\/Gemini_Generated_Image_3yqio33yqio33yqi.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/01\/Gemini_Generated_Image_3yqio33yqio33yqi.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/01\/Gemini_Generated_Image_3yqio33yqio33yqi.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/01\/Gemini_Generated_Image_3yqio33yqio33yqi.avif 3x"},"classes":[]}],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3802","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/comments?post=3802"}],"version-history":[{"count":1,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3802\/revisions"}],"predecessor-version":[{"id":3805,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3802\/revisions\/3805"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media\/3804"}],"wp:attachment":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media?parent=3802"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/categories?post=3802"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/tags?post=3802"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/series?post=3802"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}