How to subtract ivy dependency sets

2019-02-25 07:06发布

问题:

My goal is to demarcate project transitive dependencies into several not crossing sets:

  • system (jars already present in j2ee container; listed manually with explicit fixed versions)
  • provided (jars to be copied to j2ee container; listed manually)
  • ear (jars to be packed inside ear/lib, the rest)

My current solution listed below has some shortcomings:

  • have to exclude system and provided libraries from ear conf one by one
  • new third-party transitive deps that weren't already explicitly excluded could accidentally get to ear
  • sometimes have to add explicit override duplicating library name and version

Is there some approach possible to eliminate these shortcomings?

It would be nice to be able somehow define one conf as a result of dependency sets subtraction of the others (with graceful conflict resolution): ear = runtime - system - provided.

Maybe <conf name="ear" extends="runtime,!system,!provided"/> notation could be supported when IVY-982 gets fixed.

Looking for an actual solution to apply.

Even willing to consider switching to gradle if it has a solution.

<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">

    <info organisation="example.com" module="parent"/>

    <configurations defaultconfmapping="compile->@;runtime->@;system->master;provided->runtime;ear->runtime;test->test(default)">
        <conf name="compile"/>
        <conf name="runtime" extends="compile"/>
        <conf name="ear" extends="runtime" description="Libs to be packed inside ear"/>
        <conf name="provided" description="Libs to copy to j2ee container"/>
        <conf name="system" description="Libs already present in j2ee container"/>
        <conf name="test" extends="ear,provided,system" description="Simulate container environment. Used by unit tests to catch dependency compatibility problems."/>
    </configurations>

    <dependencies>
        <dependency org="log4j" name="log4j" rev="1.2.15" force="true" conf="system"/>
        <dependency org="commons-collections" name="commons-collections" rev="3.1" force="true" conf="system"/>
        <dependency org="commons-lang" name="commons-lang" rev="2.2" force="true" conf="system"/>

        <dependency org="org.apache.velocity" name="velocity" rev="1.7" force="true" conf="provided"/>
        <dependency org="org.slf4j" name="slf4j-api" rev="1.5.6" force="true" conf="provided"/>
        <dependency org="org.slf4j" name="slf4j-log4j12" rev="1.5.6" force="true" conf="provided"/>
        <!-- ... -->

        <dependency name="module1" rev="latest.integration" conf="runtime,ear,provided,test"/>
        <dependency name="module2" rev="latest.integration" conf="runtime,ear,provided,test"/>
        <!-- ... -->

        <exclude org="commons-collections" conf="ear,provided"/>
        <exclude org="commons-lang" conf="ear,provided"/>
        <exclude org="org.apache.velocity" conf="ear"/>
        <!-- TODO: negation not working: https://issues.apache.org/jira/browse/IVY-982 -->
        <!--<exclude org="org.slf4j" conf="*, !provided"/>-->
        <exclude org="org.slf4j" conf="ear,test"/>
        <!-- ... -->

        <override org="org.slf4j" rev="1.5.6"/>
        <override org="commons-collections" module="commons-collections" rev="3.1"/>
        <override org="commons-lang" module="commons-lang" rev="2.2"/>
        <!-- ... -->
    </dependencies>

</ivy-module>

Sample project sources to experiment with can be found in IVY-1443 attachment.

回答1:

While provided dependencies exclusion is possible with Maven and Gradle, it seems that currently there is no way to easily achieve it with ivy.

Update

In some cases the task can be worked around with intermediate induced module and negative regexp mask:

    <dependency org="com.company" name="root.module" conf="ear" rev="latest.integration">
        <exclude org="^(?!com.company).*$" matcher="regexp"/>
    </dependency>

But we've already moved to Gradle as Ivy seems to be losing momentum.