7

I have the following scenario, simplified:

projectX  ---> projectA ---> projectB

Where ---> means "depends on".

ProjectB is really simple. It doesn't declare any dependenci. In fact, the only relevant part is this:

<packaging>jar</packaging>

In pom.xml of projectA I have declared the dependency to projectB:

<packaging>jar</packaging>
<dependencies>
    <dependency>
        <groupId>com.mycompany</groupId>
        <artifactId>projectB</artifactId>
        <version>1.0.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

And in pom.xml of projectX I have:

<packaging>war</packaging>
<dependencies>
    <dependency>
        <groupId>com.mycompany</groupId>
        <artifactId>projectA</artifactId>
        <version>1.0.0</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

The problem is that projectX needs to use components (classes and such) that are defined in projectB. If I change the scope in projectA to use compile for projectB, everything will work, but then projectB will be included when generating the war in projectX, and I need to have this library out of the generated war because I'm providing projectB in other part of the project.

In the real scenario, I have several dependencies like projectB that affect projectA, so to reduce the size of the generated war, I would like to set them as provided, but then projectX cannot use the components defined in any of those libraries. Example of components: Spring, Hibernate, etc.

Question: Is there a way to achieve this in a clean way without re-declaring dependencies in lots of places?

A_Di-Matteo
  • 26,902
  • 7
  • 94
  • 128
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • 1
    Provided dependencies aren't transitive http://stackoverflow.com/questions/34904558/why-arent-provided-maven-dependencies-transitive/. It is built this way into Maven and it will likely never change. – Tunaki Apr 26 '16 at 21:11
  • @Tunaki that's the motivation for this question (: – Luiggi Mendoza Apr 26 '16 at 21:11
  • 1
    Yeah but that's the conclusion here: *It is wrong to use a dependency that you do not declare.* See my answer over there, there is a bug report for that. You'll have to declare it explicitely. – Tunaki Apr 26 '16 at 21:14
  • @Tunaki my question is: how to avoid redeclaring several dependencies in several projects over and over? And with several, I mean more than 10 dependencies. – Luiggi Mendoza Apr 26 '16 at 21:20
  • @LuiggiMendoza consider a common parent pom? – A_Di-Matteo Apr 26 '16 at 21:21
  • 2
    Or, consider making a BOM that you import in each of your project (if you can't make a parent POM like @A.DiMatteo suggested)? [Like here](http://stackoverflow.com/questions/14874966/how-to-use-bom-file-with-maven) and [doc here](https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html). That could solve your issue. – Tunaki Apr 26 '16 at 21:23
  • @Tunaki that last comment would fit very well as an answer. – Luiggi Mendoza Apr 26 '16 at 22:08
  • @Tunaki OK then please do so and I will delete mine, no issue for me – A_Di-Matteo Apr 27 '16 at 04:56
  • @A.DiMatteo keep yours, there's no issue on having several posts trying to answer a question. It's me who'll decide which one to accept. – Luiggi Mendoza Apr 27 '16 at 05:07
  • @LuiggiMendoza well it was maybe time to get the Disciplined badge because indeed I was not disciplined enough recently:) a feeling I had – A_Di-Matteo Apr 27 '16 at 05:18
  • Thing is, I'm not sure it really answers your question since you'll have to declare the dependency everywhere you'll need it anyway (which is what you don't want). The BOM will only factor out the version (that's its goal). I think the only answer to your question is what @A.DiMatteo answered :). – Tunaki Apr 27 '16 at 07:39

1 Answers1

6

The problem is that projectX needs to use components (classes and such) that are defined in projectB.

Then ProjetB should be a dependency of ProjectX indeed, in provided scope, again. Re-declaring the dependency would change how Maven would handle it as transitive dependency (that is, you can override its behavior by saying: I want this dependency in my project with this scope).

but then projectB will be included when generating the war in projectX, and I need to have this library out of the generated war

This will not happen by re-declaring it in provided scope. Alternatively, you could change the scope of ProjectB in ProjectA to compile and then configure the maven-war-plugin to exclude them, using inclusions/exclusions.
Before doing so though, you should double-check why semantically (or requirements-wise) ProjectB was set as provided in ProjectA and what would be its impact on other consumer projects.


Update
Both approaches above may suit your needs. Alternatively, as suggested in comments further options could be more sustainable and clear in the long run towards a better governance and maintenance (centralization):

  • Use a common parent pom where you could declare the list of shared dependencies, that is, dependencies that will be used by all children projects, defined (and maintained) once.
  • Use the dependencyManagement section in ProjectX to change how Maven dependencies mediation would handle transitive dependencies on ProjectA, without changing ProjectA or ProjectB (similar to option 1 at the top of this answer, with the difference that it will only be applied whenever the dependency comes into scope and ignored otherwise). To centralize this management, again, would be better to do so in a common parent (option above).
Community
  • 1
  • 1
A_Di-Matteo
  • 26,902
  • 7
  • 94
  • 128