Adopt Maven Bill of Materials Pattern for GeoTools - geotools/geotools GitHub Wiki

Adopt Maven Bill of Materials Pattern for GeoTools

Description

This proposal aims to implement the Maven Bill of Materials (BOM) pattern across GeoTools to improve dependency management, module versioning, and build reproducibility.

  • A BOM (Bill of Materials) is a special POM file that manages dependency versions across a project. Rather than specifying versions for each dependency individually, you can import the BOM which provides consistent versioning.

  • Modern Java projects typically use BOMs to manage dependencies and provide consistent versioning across modules. This approach is used by Spring Boot, Spring Framework, Quarkus, Jakarta EE, and many other large Java projects.

A key principle of this proposal is establishing a single, canonical source of truth for all dependency versions - both GeoTools modules and third-party libraries. Currently, there's a disconnect between internal dependency management (versions scattered across various module POMs and properties in the root POM) and how downstream projects consume GeoTools.

  • By implementing BOMs that are used both internally by GeoTools modules and externally by downstream projects, we avoid the maintenance burden of maintaining two separate dependency management systems.

  • The alternative approach - having BOMs only for downstream use while retaining the current version management for internal modules - would create duplication and potential inconsistencies.

The implementation adds two key BOM modules:

  1. gt-platform-dependencies BOM: Manages all third-party dependency versions
  2. gt-bom: Provides version management for all GeoTools modules

GeoTools currently has several dependency management issues that this proposal addresses:

  1. Module version inconsistency: When modules specify dependencies to other GeoTools modules, they usually include <version>${project.version}</version>.

  2. Third-party dependency version management: External dependencies are declared in various places, sometimes with inconsistent versions.

  3. Complex transitive dependency resolution: Projects consuming GeoTools modules often struggle with version conflicts in transitive dependencies.

  4. Difficulty in upgrading: Upgrades of third-party libraries require changes across many modules.

The BOM pattern provides a clean solution by centralizing version management:

<!-- Current approach with explicit versions -->
<dependency>
  <groupId>org.geotools</groupId>
  <artifactId>gt-main</artifactId>
  <version>${project.version}</version>
</dependency>

<!-- BOM approach without explicit versions -->
<dependency>
  <groupId>org.geotools</groupId>
  <artifactId>gt-main</artifactId>
</dependency>

This proposal is directly related to the "GeoServer 3" project's modernization efforts and will simplify dependency management for all downstream projects that use GeoTools. It is help to do this activity before updating to Java 17 LTS (which will update a lot of dependencies).

References:

Assigned to Release

GeoTools 34.0

Status

  • Under Discussion
  • In Progress
  • Completed
  • Rejected
  • Deferred

Voting:

  • Andrea Aime:
  • Ian Turton: +1
  • Jody Garnett: +1
  • Nuno Oliveira:
  • Simone Giannecchini:
  • Torben Barsballe:

Tasks

  1. Create gt-platform-dependencies BOM module

    • Define third-party dependency versions
    • Organize by library categories
  2. Create gt-bom module

    • Import gt-platform-dependencies
    • Include all GeoTools modules
    • Add test artifacts with proper classifiers
  3. Update module POMs

    • Remove <version>${project.version}</version> from internal dependencies
    • Import BOMs in relevant modules
    • Ensure GeoTools "eats its own dog food" by using its own BOMs internally
  4. Update documentation

    • Create BOM usage guide
    • Update upgrading page with BOM information
    • Add examples in user guide
    • Document the unified approach for internal/external dependency management
  5. Test downstream project compatibility

    • Verify with GeoServer and GeoWebcache
    • Test with other known projects that use GeoTools
  6. Final review and incorporation

API Change

Before:

<!-- In GeoTools module pom.xml -->
<dependencies>
  <dependency>
    <groupId>org.geotools</groupId>
    <artifactId>gt-main</artifactId>
    <version>${project.version}</version>
  </dependency>
  <dependency>
    <groupId>org.locationtech.jts</groupId>
    <artifactId>jts-core</artifactId>
    <version>${jts.version}</version>
  </dependency>
</dependencies>

<!-- In downstream project -->
<dependencies>
  <dependency>
    <groupId>org.geotools</groupId>
    <artifactId>gt-shapefile</artifactId>
    <version>34.0</version>
  </dependency>
  <dependency>
    <groupId>org.geotools</groupId>
    <artifactId>gt-epsg-hsql</artifactId>
    <version>34.0</version>
  </dependency>
</dependencies>

After:

<!-- In GeoTools module pom.xml -->
<dependencies>
  <dependency>
    <groupId>org.geotools</groupId>
    <artifactId>gt-main</artifactId>
  </dependency>
  <dependency>
    <groupId>org.locationtech.jts</groupId>
    <artifactId>jts-core</artifactId>
  </dependency>
</dependencies>

<!-- In downstream project -->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.geotools</groupId>
      <artifactId>gt-bom</artifactId>
      <version>34.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.geotools</groupId>
    <artifactId>gt-shapefile</artifactId>
  </dependency>
  <dependency>
    <groupId>org.geotools</groupId>
    <artifactId>gt-epsg-hsql</artifactId>
  </dependency>
</dependencies>

Why Not Use the Root POM as BOM

Using GeoTools' root POM directly as a BOM in downstream projects (a common but problematic practice) has several significant drawbacks that this proposal addresses:

  • Unintended inheritance: The root POM contains build configuration, plugin management, and profiles designed specifically for building GeoTools itself. Importing it would pull in unnecessary build machinery that could interfere with downstream projects.

  • No separation of concerns: A dedicated BOM focuses solely on dependency management, following the single responsibility principle. The root POM mixes many concerns including build management, plugin configuration, deployment settings, etc.

  • Dependency pollution: The root POM contains dependencies needed for building GeoTools that downstream projects may not need, potentially pulling in large and unnecessary dependency trees.

  • Plugin interference: Maven plugin configurations from the root POM may conflict with downstream project build plugins, causing unexpected build problems.

  • Maintenance burden: Changes to GeoTools' build process would impact all downstream projects, even when those changes have nothing to do with dependencies.

  • Challenging upgrade path: When upgrading GeoTools versions, downstream projects would be forced to deal with build machinery changes unrelated to their needs.

  • Duplicated dependency management: Without dedicated BOMs used both internally and externally, we would need to maintain two parallel systems for dependency management - one for GeoTools modules (e.g. root pom), and another for downstream projects, creating maintenance overhead and risking version inconsistencies between the two systems.

These issues are resolved by creating dedicated BOMs that are:

  • Focused solely on dependency management
  • Lightweight and clearly defined in purpose
  • Designed specifically for consumption by downstream projects
  • Not affected by changes to GeoTools' build machinery
  • Serve as a single source of truth for dependency versions, both internally and externally
⚠️ **GitHub.com Fallback** ⚠️