16

We have a project layout with sub-modules and dependencies in bom files:

projectA
    bom           
    module1
    module2

The actual version numbers are defined as properties in the bom file, so for each dependency we have something like

    <properties>
        <guice-version>4.1.0</guice-version>
    </properties>

<dependencies>
    <dependency>
        <groupId>com.google.inject</groupId>
        <artifactId>guice</artifactId>
        <version>${guice-version}</version>
    </dependency>
</dependencies>

The top-level pom in projectA import the bom in the dependecyManagement section with

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>group</groupId>
            <artifactId>bom</artifactId>
            <version>1.0.0</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</dependencyManagement>

This all works fine and we have centralized dependency definitions.

However, at one point during the build process we need to use the version of one of the dependencies. I was hoping that importing the bom in the dependencyManagement section would also import the properties into the top-level pom, but that is not the case. It is also not possible to make the bom a children of the top-level pom with a section because this creates a cyclic dependency between pom files.

I thought about putting the properties into an external file and read it with the maven properties plugin where needed. That would be obviously in the bom and in the pom file where we need to get the version of the dependency. However, since the bom is not packaged as a jar, so the path would have to be hard-coded.

I could fix it by duplicating the properties to two places, but I don't want to do that. Is there a way to get the version of a dependency, e.g. using a property defined by the dependency?

The problem seems to be common enough and I am wondering if we did something wrong in the project structure. What is the standard way to centralize properties in this case?

Jens
  • 9,058
  • 2
  • 26
  • 43
  • Please take a look at this question, and its accepted answer: https://stackoverflow.com/questions/30164134/how-to-use-properties-maven-plugin. I don't think there's any other way to centralize properties than using parent poms. – gjoranv Dec 01 '17 at 01:01
  • 2
    no I dont think you missed something. The bom support in maven is a bit "on top" and might deserve clearer support in the future. There is another question that may help: https://stackoverflow.com/questions/50698654/access-maven-property-using-dependency-management - in case the dependency you are interested in contains some meta data file in the jar the classpath: variant may work. Other than that: did you consider writing your own maven plugin? to read the bom and then the property you want to? There is a similar plugin: https://github.com/apifocal/bom-maven-plugin that may work for you. – wemu Jun 21 '19 at 15:13

2 Answers2

4

You can try using the BOM as the parent of your parent module as a BOM is technically some kind of minimal version of a POM. This is what the official Maven project describes here:

http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

I don't like this solution, because if you already extend from a parent, you get into a multi-inheritance problem here.

It appears that a BOM is not fulfilling your requirements. It only assembles a bunch of dependencies like an extract of a dependency management section of a parent project. However its internal structure should not matter to your project. If the BOM changes structurally, your project won't be influenced by that. Perhaps it's a more proper solution not to use a BOM here, but instead pick the dependencies and use your own version property here. Depends a little bit on how complex the BOM is.

So either use the BOM as a parent or dismiss the BOM at all, since you need more than your BOM gives you.

Daniel Heid
  • 199
  • 1
  • 5
2

The actual purpose about BOM import is precisely to avoid having to declare the exact version of the dependencies declared in the BOM. So, consider that you have a BOM witch declares a dependency like

<dependency>
    <groupId>com.google.inject</groupId>
    <artifactId>guice</artifactId>
    <version>${guice-version}</version>
</dependency>

(we asume your BOM also declares the property in it). So then, in your projects, you can declare the guice dependency without having to determine the version attribute as it is inherited from the BOM.

<dependency>
    <groupId>com.google.inject</groupId>
    <artifactId>guice</artifactId>
</dependency>

The benefit is that if you change your BOM version, this kind of dependencies will be updated accorndingly without having to do any change in the pom.xml of your project!

  • 1
    Yep that's true - but there might be an usecase where you want to use one more artifact of the dependency the BOM declares, that you know is released with the same version. Example: Spring-Boot declares a `flyway.version` that you would like to use for the flyway-maven-plugin though. Regular dependency resolution won't resolve the "sibling artifact" version. – icyerasor Aug 12 '22 at 14:59