I have a project, which is being used by other project as an Ivy dependency. Its dependencies.xml
contains lots of dependencies, basically in 3 categories:
The third dependencies category is critcal to me. If I don't include servlet-api.jar
in the javac
classpath I can't compile the project. But if I include that package in the war classpath I fall into a bad practice, because server runtimes (mainly Tomcat, but also Websphere) contain their own servlet-api.jar
.
And for JDBC connectors, I am only required to include them into Ant classpath for running unit tests from Bamboo, as I want to repeat the same tests with multiple databases.
Here is my current dependency.xml fragment:
<configurations>
<conf name="test" visibility="public" extends="compile" />
<conf name="compile" visibility="public" extends="runtime" />
<conf name="runtime" visibility="public" />
<conf name="provided" visibility="public" />
<conf name="junit" visibility="public" />
</configurations>
<!-- Build -->
<dependency org="javax.servlet" name="javax.servlet-api" rev="3.0.1" transitive="false" conf="provided->*" />
<dependency org="javax.servlet.jsp" name="javax.servlet.jsp-api" rev="2.3.1" transitive="false" conf="provided->*" />
<dependency org="javax.el" name="javax.el-api" rev="3.0.0" transitive="false" conf="provided->*" />
<dependency org="mysql" name="mysql-connector-java" rev="5.1.38" transitive="false" conf="provided->*" />
<dependency org="ojdbc" name="ojdbc" rev="14" transitive="false" conf="provided->*" />
<dependency org="org.hsqldb" name="hsqldb" rev="2.3.3" transitive="false" conf="provided->*" />
<dependency org="org.postgresql" name="postgresql" rev="9.4.1207" transitive="false" conf="provided->*" />
<dependency org="com.microsoft" name="sqljdbc" rev="4.1" transitive="false" conf="provided->*" />
<dependency org="org.adrianwalker" name="multiline-string" rev="0.1.2" transitive="false" conf="provided->*" />
<!-- Spring -->
<dependency org="org.springframework" name="spring-core" rev="4.2.4.RELEASE" transitive="false" conf="runtime->*"/>
<dependency org="org.springframework" name="spring-aop" rev="4.2.4.RELEASE" transitive="false" conf="runtime->*"/>
<dependency org="org.springframework" name="spring-beans" rev="4.2.4.RELEASE" transitive="false" conf="runtime->*"/>
<dependency org="org.springframework" name="spring-context" rev="4.2.4.RELEASE" transitive="false" conf="runtime->*"/>
<dependency org="org.springframework" name="spring-context-support" rev="4.2.4.RELEASE" transitive="false" conf="runtime->*"/>
<dependency org="org.springframework" name="spring-expression" rev="4.2.4.RELEASE" transitive="false" conf="runtime->*"/>
<dependency org="org.springframework" name="spring-jdbc" rev="4.2.4.RELEASE" transitive="false" conf="runtime->*"/>
<dependency org="org.springframework" name="spring-orm" rev="4.2.4.RELEASE" transitive="false" conf="runtime->*"/>
<dependency org="org.springframework" name="spring-tx" rev="4.2.4.RELEASE" transitive="false" conf="runtime->*"/>
<dependency org="org.springframework" name="spring-web" rev="4.2.4.RELEASE" transitive="false" conf="runtime->*"/>
<dependency org="org.springframework" name="spring-webmvc" rev="4.2.4.RELEASE" transitive="false" conf="runtime->*"/>
<dependency org="org.springframework" name="spring-test" rev="4.2.4.RELEASE" transitive="false" conf="test->*"/>
<dependency org="org.springframework.plugin" name="spring-plugin-core" rev="1.2.0.RELEASE" transitive="false" conf="runtime->*"/>
<dependency org="org.springframework.plugin" name="spring-plugin-metadata" rev="1.2.0.RELEASE" transitive="false" conf="runtime->*"/>
In the above example, com.adrianwalker#multiline-string
is required only for annotation parsing and no more
In my main-project
, I ended up retrieving dependencies with the following task
<target name="ivy-retrieve">
<ivy:configure override="true" file="${ivy.install.dir}/ivy-settings.xml" />
<ivy:retrieve sync="true" conf="runtime,junit" type="jar,bundle" pattern="${project.local.lib}/[artifact]-[revision].[ext]" />
<eclipse.refreshLocal depth="infinite" resource="/" if:set="eclipse.running" />
</target>
This will populate my WEB-INF/lib
directory correctly with all the dependencies I need (including spring-test
) but without the JDBC connectors that are already manually copied to Tomcat classpath
Ok...
The problem comes when I embed the main-project
into a derived-project
<dependency org="com.example" name="main-project" rev="${current.version}" transitive="true" conf="runtime->*"/>
And
<target name="ivy-retrieve-eclipse">
<ivy:configure override="true" file="${ivy.install.dir}/ivy-settings.xml" />
<ivy:retrieve sync="true" conf="runtime,junit" type="jar,bundle" pattern="${project.local.lib}/[artifact]-[revision].[ext]" />
<eclipse.refreshLocal depth="infinite" resource="/" if:set="eclipse.running" />
</target>
The result is that I still get all the dependencies downloaded.
I just need to tell Ivy to download all dependencies that are runtime
and junit
for my derived-project
, including those runtime
and junit
dependencies included in main-project
's ivy file.
How can I do that? What did I mess up?
There were two problems in the previous setup:
conf="runtime->*"
on the child project dependency, which will just remap runtime
to all
configurationsAbout point 2, I had the below on parent project
<configurations>
<conf name="test" visibility="public" extends="compile" />
<conf name="compile" visibility="public" extends="runtime" />
<conf name="runtime" visibility="public" />
<conf name="provided" visibility="public" />
<conf name="junit" visibility="public" />
</configurations>
And the below on child project
<configurations>
<conf name="test" visibility="public" extends="compile" />
<conf name="compile" visibility="public" extends="runtime" />
<conf name="runtime" visibility="public" />
<conf name="provided" visibility="public" extends="compile" />
<conf name="junit" visibility="public" extends="provided, test" />
</configurations>
So I had to first align child project to parent.
The second step, although possibly to be avoided, was to remap the dependency of parent project multiple times for each configuration neeeded. Maybe I could optimize on this one, but at least I don't get the jdbc jars downloaded any more into runtime classpath
So child dependency became
<dependencies>
<dependency org="com.acme" name="parent-project" rev="${phoenix.version}" transitive="true" conf="runtime->runtime"/>
<dependency org="com.acme" name="parent-project" rev="${phoenix.version}" transitive="true" conf="compile->compile"/>
<dependency org="com.acme" name="parent-project" rev="${phoenix.version}" transitive="true" conf="provided->provided"/>
<dependency org="com.acme" name="parent-project" rev="${phoenix.version}" transitive="true" conf="junit->junit"/>
<dependency org="com.acme" name="parent-project" rev="${phoenix.version}" transitive="true" conf="test->test"/>
</dependencies>