0

I have a POM that according to the Maven best practises should group the dependencies of a component/system to declare any dependencies required to use said component/system. (Only the grouping itself is a best practise ;))

Normaly this pom will just declare the components (in this example systemA) service (interface) module as compile scoped dependency and its according implementation module as runtime scoped dependencie like this:

<dependencies>
    <dependency>
        <groupId>ch.jeeguy.systemA</groupId>
        <artifactId>systemA-service</artifactId>
        <scope>compile</scope>
    </dependency>

    <dependency>
        <groupId>ch.jeeguy.systemA</groupId>
        <artifactId>systemA-implementations</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

(Of course the POM of the service module as well as the POM of the implementation-module will declare further dependencies to modules of systemA like for example a DTO-Module of systemA required with a scope compile etc.)

So if i now plan to build a new systemB that needs to interact with systemA or reuses certain parts of systemA i dont want systemB to have dependencies on internas of systemA such as its DTO-module but only the dependencie to the above POM. This is how i add the above POM as dependencie in systemB:

        <dependency>
            <groupId>ch.jeeguy.systemA</groupId>
            <artifactId>systemA</artifactId>
            <type>pom</type>
            <version>${systemA.version}</version>
        </dependency>

As faar as i understood everything correctly to this point my componentB will now get systemA's service module as a compile scoped depencency and the implementation module as runtime scoped dependency - Each of which define their own dependencies which will become transitive dependencies for systemB and behave like defined here (scope matrix): http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope.

My Question: If i apply a scope ... overriding the default commpile... say test to the POM-typed dependencie of systemA in systemB's POM like this:

        <dependency>
            <groupId>ch.jeeguy.systemA</groupId>
            <artifactId>systemA</artifactId>
            <type>pom</type>
            <scope>test</scope>
            <version>${systemA.version}</version>
        </dependency>

What exactly am i applying the test scope on now? Is it something of the selection below?

  • i apply the scope to the entire POM-dependencie - considered i applyied test the entire information defined in the POM of systemA wont be considered at all unless the context test is given (if systemB is compiled skipping tests whatever information is defined in the group-POM is not consulted). Once the context test is given it will result in systemB getting compile and runtime dependencies that in this context dont make any sence... . -> "Scope is applied on the POM itself"

  • i override the scope of any dependencies defined in the POM of systemA - which in this example results in systemB only depending on systemA's modules for its tests. The compile/runtime scopes of the two dependencies of systemA are in the context of systemB both set to test. (E.g. "i dont care you want me to use your service-module with scope compile, i want it to have scope test!") -> "Scope is applied to the dependencies inside the according POM and thus affects the behaviour of transitive dependencies"

Could you help me out of my confusion i put myself in trying to figure this out?

What i tryied so faar

Even thus i am new to Maven i dont fear to read the entire documentation as well as a book about Maven3 i ordered. I invested aprox. 80-100 hours into my Maven "skills" so faar. I also more or less "fully" understand the behaviour of at least the scope import when it comes to dependencyManagement information like described here: difference between scope "import" and "pom" type dependency yet i cannot manage to find a (official) source to my question. Leaving two possibillies in my eyes: I just overread the according part in the documentation OR (and this unfortunately is more likely) i already have a huge missunderstanding of the concepts of Maven. Especially in the case of the later one i would realy appreciate clarification :) Btw. i am currently trying to reverseengineer the behaviour by just applying the different scopes and analyze the build output ... but i am working with 15 systems and hundreds of modules...

Community
  • 1
  • 1
JBA
  • 2,769
  • 5
  • 24
  • 40
  • You are applying this scope to the jar that is created from systemA. http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html, and from the link scope test means that: This scope indicates that "the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases.". I think that you should uses scope provided. – BlueLettuce16 Nov 07 '14 at 12:55
  • @BlueLettuce16 Thank you very much for your reply. While i understand the behaviour of the scopes when it comes to archives such as `jar` (war, ear, etc.) the above "maven project" of systemA wont result in a `jar` but only a `pom` beeing populated to the repositories - This is exactly the point where i start to struggle. (Inside this project there are dependencies defined that point to for example the service module which itself would be packed as `jar`). – JBA Nov 07 '14 at 13:11
  • I think that is the solution for you. Instead of using systemA as a dependency of systemB you should define systemA to be the parent of systemB. Please read inheritence section on http://maven.apache.org/pom.html. – BlueLettuce16 Nov 07 '14 at 13:35
  • A first point: I am absolutly aware of the inheritence, actually while the best practise of grouped dependencies is described to be used to group common depencencies of systemA and systemB (say JUnit for example) we currently manage the dependencyManagement of such common dependencies over inheritence (e.g. company-, division-, etc. parent POMs beeing childs of a company super POM beeing a child of Mavens root POM). – JBA Nov 07 '14 at 13:39
  • Have you seen that: http://stackoverflow.com/questions/16894032/how-to-use-poms-as-a-dependency-in-maven? – BlueLettuce16 Nov 07 '14 at 13:42
  • @BlueLettuce16 Say systemA has a module `systemA-DTO` that defines DTOs which will be populated by systemA's module `systemA-service`. I now dont want systemB to have a dependency directly on systemA's module DTO but its POM that groups modules required to run systemA - because of the simple fact that now systemA can independendly rename its module `systemA-DTO` to `systemA-FactModel` without any required changes to systemB (the renamed dependency will be available transitive) – JBA Nov 07 '14 at 13:42
  • @BlueLettuce16 Yeah i have seen that and i am aware on the possibility to import `dependencyManagement` informations using `pomimport` i am however interested on the behaviour of the `scope` on `dependencies`-information only rather than `dependencyManagement`-information. – JBA Nov 07 '14 at 13:46
  • I also found that: http://jira.codehaus.org/browse/MNG-2975. Hope it helps. – BlueLettuce16 Nov 07 '14 at 13:52
  • @BlueLettuce16 Thank you very much for your efforts! The above is not a bug but a well defined behaviour of transitive dependencies described in that scope-matrix i posted a link in my question (beside `test` scoped dependencies `runtime` scoped transitive dependencies will also be omitted). – JBA Nov 07 '14 at 13:56
  • But in the end that is exactly the real purpose of my question - depending on the `scope` beeing applied i am currently not sure if the module `systemA-service` in the context of systemB is already transitive (in that case the `scope` would apply to the POM project itself) or transitivity starts on the dependencies of systemA-service (in that case the `scope` would override the `scope` defined in the grouping-POM) – JBA Nov 07 '14 at 13:58
  • @BlueLettuce16 Btw. if of interest regarding the bug above: While if you have tests that are required in another project you are able to include those as `test-jar` you may have some sort of testing-base (Customized Testrunners etc.) project which source belongs into `src/main/java` rather than `src/test/java` (tests of the testing-base code would reside in `src/test/java` and again be available as `test-jar) – JBA Nov 07 '14 at 14:01
  • Sorry that I couldn't help but I think that you are complicating things a little bit to much. You wouldn't have this problem if you had systemA-DTO-module as a jar and systemA-service-module as a jar and then systemA-service-module would have systemA-DTO-module as a dependency and systemB would have systemA-service-module as a dependency and this way the systemB does not depend on systemA-DTO-module. – BlueLettuce16 Nov 07 '14 at 14:05
  • @BlueLettuce16 Exactly this is what we have had! BUT for sake of architecture systemB had a dependencie to `systemA-service` that MUST BE `compile` scoped by guidelines. SystemB as well had to have a dependency to `systemB-serviceImpl` that MUST BE `runtime` scoped by guidelines. SystemB gets the DTOs transitivly since ever. Now the company architecture gremium wants to have scoping definitions like those beeing defined by the component (in this case systemA) itself rather than by the components that rely on them. Once you have so many guidelines things are always getting more complicated :( – JBA Nov 07 '14 at 14:15
  • @BlueLettuce16 Btw. You did help alot!! Because beside the core of my question (on the behaviour of the scopes applied to such groups) i guess the idear of such "port POMs" (as they call them) as a "Interface to the entire component" is only a question of meaning and preferences of architecture in general. (I personally would just have left it as you described it) – JBA Nov 07 '14 at 14:19

1 Answers1

0

I could consult our companys lead architect regarding this issue - providing the sourced answer here:

1.) Lets call this pom of systemA that only groups two dependencies (systemA-service, systemA-Impl) a "port pom".

Quick Answer: The scope defined in systemB applies to the port pom (of systemA) itself hence making any grouped dependencies in that pom become transitive and behave according to the matrix table under http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope for systemB.

Extended Answer: My key issue was a missunderstanding of the packaging type pom. While i considered this something "maven special" it will result in a maven artefact of type pom in the repositories and can be seen as a "normal" dependency such as a jar (it just isnt a jar effectivly providing implementations of any functionality but only maven based information on where to find further maven artefacts [or manage their versions by importing their dependencyManagement information using scope import]).

Comming back to my question - the questioned scope (marked green, big arrow below) as shown here:

enter image description here

The port pom that groups the dependencies to systemA's service/impl modules (which themselves would define further dependencies such as eclipselink etc. and may be grouped under a components parent) leads to a artifact ch.jeeguy.systemA:systemA:<version> beeing populated to the repositories (green box).

If systemB (yellow box) now adds a dependency to the port pom it acctually adds a dependency to the above (green box) artefact hence making the artefact itself becoming a direct dependency of systemB while any further dependencies (the grouped ones - orange boxes) become transitive dependencies from systemB's point of view.

Since we now know those are transitive dependencies we can answer the effect of the scope beeing applied: It behaves like transitive dependencies do behave according to Mavens documentations (see link under quick answer).

Regarding the scope i asked about (where the arrow points at) - this means:

  • If no scope is applied - default scope compile applies - in the above described scenario systemA-service would transitivly be available in scope compile while systemA-Impl would be transitivly available in scope runtime.

  • If another scope is applyied the behaviour is the one described in the scope matrix (e.g. the very left column is the scope where the arrow points at, the headercolumn represents the resulting scope of transitive dependencies).

  • If another scope is applyied the behaviour for transitive dependencies behaves according to the scope matrix (e.g. transitive dependencies of scope test and provided will be omitted).

  • Example 1: If scope provided is applied, transitive dependencies of scope compile or runtime will be available in scope provided as well (e.g. systemA-service will no longe be available in scope compile but only in scope provided.

  • Example 2: If scope runtime is applied, transitive dependencies of scope compile or runtime will be available in scope runtime as well.

Considered we have a new policy to only create new dependencies to the port pom of a system we had to prevent usage of the scope at that point in the policy too (The hole "enforce something using" maven approach is highly questionable but our main goal is to have a Maven structure as close to our component design as possible.

Sources

Side note 'best practise': In the comment section of my question you see the reason we are trying to apply that best practise in our context and i too can confirm it seems senceful from a "maven is just configuration" point of view. However considered applicationB would just need the DAO-module of systemA - using such port poms will result in applicationB getting various dependency artefacts (such as systemA-service, systemA-Impl and some of their transitive dependencies) it will never realy use for the sole purpose of following a companys maven guide. I have seen some EARs exploding from 50MBs to over 150MBs just because of the transitive dependencies that reach me in scope compile. So be aware about this aspect in this scenario and also note that you dont want to exclude the transitive dependencies in systemB because you dont want to have any other systemA-modules in systemB's POMs unless its the port pom module allowing to refactor any modules of systemA without any change to systemB [unless the port pom's itself is affected]).

JBA
  • 2,769
  • 5
  • 24
  • 40