Dev Study
← 解説「Ant: 依存の扱いと、古いプロジェクトの読み方」に戻る

サンプルコードで身につける: Ant: 依存の扱いと、古いプロジェクトの読み方

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1ivy.xml と build.xml の全文: dependency 1行と <ivy:retrieve/>

7.0.9 を に取らせる最小の2ファイルです。5行目の dependency の org、name、rev は の 、artifactId、version で、 で実行に要るものだけに絞ります。10行目で ivy の名前空間を宣言し、12行目の が へコピーします。実際のビルドでは init の を ="resolve" にして、コンパイルの前に走らせます。

ivy.xml / build.xml(l3-ivy/webmvc、Ivy 2.6.0)設定ファイル
# ivy.xml
<ivy-module version="2.0">
<info organisation="jp.co.example" module="shop"/>
<dependencies>
<dependency org="org.springframework" name="spring-webmvc" rev="7.0.9" conf="default"/>
</dependencies>
</ivy-module>
 
# build.xml(resolve の target だけの最小版)
<project name="shop" default="resolve" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">
<target name="resolve" description="fetch spring-webmvc and everything it needs into lib/">
<ivy:retrieve/>
</target>
</project>

2lib/ に手で置く: Maven Central の URL と、build.xml での読み方

手で置く方式では、座標から URL を組み立てて取り、lib/ に置きます(隣の .sha1 と照合したのは、この記録にある と の2本です)。 側は <path> の中の < dir="${lib.dir}" includes="*"/> で lib/ 直下の 全部をにし、<war> の <lib> で に詰めます。spring-webmvc 1本に要った11本は、レッスン「 で の を作る」で人が を辿って書き出したものです。

download-log.txt と、E-2 の build.xml の該当部分コマンド出力
# Maven Central の URL は座標から決まる:
# https://repo.maven.apache.org/maven2/<groupId の . を / に>/<artifactId>/<version>/<artifactId>-<version>.jar
# curl で取り、隣の .sha1 と照合した記録
# downloaded 2026-10-03T00:19:46Z from Maven Central
https://repo.maven.apache.org/maven2/org/apache/commons/commons-lang3/3.21.0/commons-lang3-3.21.0.jar => 200 749083 bytes
sha1 remote: 7bad013a5acee0a078d75fc352a906baa57acb74
sha1 local : 7bad013a5acee0a078d75fc352a906baa57acb74
https://repo.maven.apache.org/maven2/org/junit/platform/junit-platform-console-standalone/6.1.3/junit-platform-console-standalone-6.1.3.jar => 200 2997949 bytes
sha1 remote: bb65bef57072d36433e8a863016163858c926113
sha1 local : bb65bef57072d36433e8a863016163858c926113
 
# 取ってきた JAR を lib/ に置き、build.xml ではこう読む(E-2 の WAR 版 build.xml から)
<path id="compile.classpath">
<fileset dir="${lib.dir}" includes="*.jar"/> ← lib/ 直下の *.jar 全部
<fileset dir="lib-compile" includes="*.jar"/> ← コンパイルにだけ使う servlet-api
</path>
<javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="compile.classpath" .../>
<war destfile="${dist.dir}/shop.war" webxml="${web.dir}/WEB-INF/web.xml">
...
<lib dir="${lib.dir}" includes="*.jar"/> ← WEB-INF/lib へ(lib-compile は入れない)
</war>
 
# spring-webmvc 7.0.9 を使うために人が POM を辿って置いた 11 本(レッスン「Ant で Spring の WAR を作る」)
lib/spring-webmvc-7.0.9.jar ← 自分で選んだ1本
lib/spring-web-7.0.9.jar ← webmvc の POM が要求
lib/spring-context-7.0.9.jar ← webmvc
lib/spring-beans-7.0.9.jar ← webmvc, web, context, aop
lib/spring-core-7.0.9.jar ← 全モジュール
lib/spring-aop-7.0.9.jar ← webmvc, context
lib/spring-expression-7.0.9.jar ← webmvc, context
lib/commons-logging-1.3.5.jar ← spring-core
lib/jspecify-1.0.0.jar ← spring-core
lib/micrometer-observation-1.16.7.jar ← spring-web, spring-context
lib/micrometer-commons-1.16.7.jar ← micrometer-observation
# 1本ずつ抜いたとき、ビルドで気づけたのは spring-web と spring-context の2本だけ

3Ivy で同じ11本を取る: found の行と lib/ の中身

に spring-webmvc 7.0.9 を1行書いて で走らせた記録です。found の行が POM を辿って見つけた12、evicted modules が jspecify 1.0.0 を 1.0.1 に寄せた判断、最後の 11 artifacts copied が lib/ に置いた本数です。ls -l のサイズは、人が置いた11本と1バイトまで一致しました(jspecify の版だけ違います)。

$ ant -lib /bt/l3-ivy/ivylib(webmvc)/ $ ls -l libコマンド出力
$ ant -lib /bt/l3-ivy/ivylib | grep -v "^\[ivy:retrieve\] \.\|downloading" # ivy-2.6.0.jar のディレクトリを -lib で渡す。進捗の点と downloading の行は grep で省いた
Buildfile: /bt/l3-ivy/webmvc/build.xml
 
resolve:
[ivy:retrieve] :: Apache Ivy 2.6.0 - 20260712075753 :: https://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: url = jar:file:/bt/l3-ivy/ivylib/ivy-2.6.0.jar!/org/apache/ivy/core/settings/ivysettings.xml
[ivy:retrieve] :: resolving dependencies :: jp.co.example#shop;working@5330a5c0e463
[ivy:retrieve] confs: [default]
[ivy:retrieve] found org.springframework#spring-webmvc;7.0.9 in public
[ivy:retrieve] found org.springframework#spring-aop;7.0.9 in public
[ivy:retrieve] found org.springframework#spring-beans;7.0.9 in public
[ivy:retrieve] found org.springframework#spring-core;7.0.9 in public
[ivy:retrieve] found commons-logging#commons-logging;1.3.5 in public
[ivy:retrieve] found org.jspecify#jspecify;1.0.0 in public
[ivy:retrieve] found org.springframework#spring-context;7.0.9 in public
[ivy:retrieve] found org.springframework#spring-expression;7.0.9 in public
[ivy:retrieve] found io.micrometer#micrometer-observation;1.16.7 in public
[ivy:retrieve] found org.jspecify#jspecify;1.0.1 in public
[ivy:retrieve] found io.micrometer#micrometer-commons;1.16.7 in public
[ivy:retrieve] found org.springframework#spring-web;7.0.9 in public
[ivy:retrieve] [SUCCESSFUL ] org.springframework#spring-webmvc;7.0.9!spring-webmvc.jar (167ms)
...
[ivy:retrieve] :: evicted modules:
[ivy:retrieve] org.jspecify#jspecify;1.0.0 by [org.jspecify#jspecify;1.0.1] in [default]
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 12 | 12 | 12 | 1 || 11 | 11 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: jp.co.example#shop
[ivy:retrieve] confs: [default]
[ivy:retrieve] 11 artifacts copied, 0 already retrieved (8459kB/27ms)
 
BUILD SUCCESSFUL
 
$ ls -l lib | sort -k9
-rw-r--r-- 1 root root 73737 Jan 31 2025 commons-logging-1.3.5.jar
-rw-r--r-- 1 root root 3064 Jul 29 22:41 jspecify-1.0.1.jar
-rw-r--r-- 1 root root 51745 Aug 20 08:02 micrometer-commons-1.16.7.jar
-rw-r--r-- 1 root root 83914 Aug 20 08:02 micrometer-observation-1.16.7.jar
-rw-r--r-- 1 root root 426204 Aug 20 09:37 spring-aop-7.0.9.jar
-rw-r--r-- 1 root root 928155 Aug 20 09:37 spring-beans-7.0.9.jar
-rw-r--r-- 1 root root 1399435 Aug 20 09:37 spring-context-7.0.9.jar
-rw-r--r-- 1 root root 2035755 Aug 20 09:37 spring-core-7.0.9.jar
-rw-r--r-- 1 root root 327140 Aug 20 09:37 spring-expression-7.0.9.jar
-rw-r--r-- 1 root root 2226342 Aug 20 09:37 spring-web-7.0.9.jar
-rw-r--r-- 1 root root 1107415 Aug 20 09:37 spring-webmvc-7.0.9.jar

4よくある失敗と誤解: -lib なし、conf なしで25本、2回目のキャッシュ

-lib を付けないと Ant は ivy の名前空間を知らず、failed to create or type で止まります。dependency に conf を書かないと、その POM のテスト用の依存と 、-javadoc.jar まで取ってきて、commons-lang3 1本の指定で lib/ が25本になりました。2回目は から解決し、ダウンロードも lib/ へのコピーも起きません。

$ ant resolve(-lib なし)/ conf なし / conf="default" / 2回目 / ~/.ivy2 の中コマンド出力
##### -lib を付けずに ant を打つ: Ant は ivy の名前空間を知らない
$ ant resolve
resolve:
 
BUILD FAILED
/bt/l3-ivy/hello/build.xml:8: Problem: failed to create task or type antlib:org.apache.ivy.ant:retrieve
Cause: The name is undefined.
...
Action: Check that the implementing library exists in one of:
-/opt/apache-ant-1.10.18/lib
-/root/.ant/lib
-a directory added on the command line with the -lib argument
[exit 1]
 
##### conf を書かない <dependency org="org.apache.commons" name="commons-lang3" rev="3.21.0"/>
$ ant -lib /bt/l3-ivy/ivylib
[ivy:retrieve] found org.apache.commons#commons-lang3;3.21.0 in public
[ivy:retrieve] found org.junit.jupiter#junit-jupiter;5.14.4 in public
[ivy:retrieve] found org.junit.jupiter#junit-jupiter-api;5.14.4 in public
...(found は全部で 23 行。mockito、easymock、jmh なども含む)
[ivy:retrieve] downloading https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.21.0/commons-lang3-3.21.0-sources.jar ...
[ivy:retrieve] downloading https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.21.0/commons-lang3-3.21.0-javadoc.jar ...
...
| default | 26 | 23 | 23 | 3 || 25 | 25 |
[ivy:retrieve] 25 artifacts copied, 0 already retrieved (25242kB/45ms)
$ find lib build dist -type f | sort
build/classes/com/example/app/Main.class
build/classes/com/example/greet/Greeter.class
dist/app.jar
lib/apiguardian-api-1.1.2.jar
lib/asm-9.8.jar
lib/byte-buddy-1.17.5.jar
lib/byte-buddy-agent-1.12.19.jar
lib/commons-lang3-3.21.0.jar
lib/commons-lang3-3.21.0-javadoc.jar
lib/commons-lang3-3.21.0-sources.jar
lib/commons-math3-3.6.1.jar
lib/commons-text-1.15.0.jar
lib/easymock-5.6.0.jar
lib/jmh-core-1.37.jar
...
lib/mockito-core-4.11.0.jar
lib/mockito-inline-4.11.0.jar
lib/objenesis-3.4.jar
lib/opentest4j-1.3.0.jar
# lib/ は 25 本(省略した行は junit-jupiter と junit-platform の 7 本と jmh-generator-annprocess、jopt-simple、junit-pioneer)
 
##### 同じものに conf="default" を付ける
$ ant -lib /bt/l3-ivy/ivylib resolve
[ivy:retrieve] found org.apache.commons#commons-lang3;3.21.0 in public
| default | 1 | 0 | 0 | 0 || 1 | 0 |
[ivy:retrieve] 1 artifacts copied, 0 already retrieved (731kB/3ms)
$ ls lib
commons-lang3-3.21.0.jar
 
##### 2回目(conf 無し版をもう一度): ダウンロードが無く、lib/ へのコピーも無い
$ ant -lib /bt/l3-ivy/ivylib resolve
[ivy:retrieve] :: resolution report :: resolve 148ms :: artifacts dl 6ms
| default | 26 | 0 | 0 | 3 || 25 | 0 |
[ivy:retrieve] 0 artifacts copied, 25 already retrieved (0kB/3ms)
 
$ find /root/.ivy2 -type f | sort | grep commons-lang3 # キャッシュの置き方
/root/.ivy2/cache/org.apache.commons/commons-lang3/ivy-3.21.0.xml ← POM を Ivy の形式に変換したもの
/root/.ivy2/cache/org.apache.commons/commons-lang3/ivy-3.21.0.xml.original ← 元の POM
/root/.ivy2/cache/org.apache.commons/commons-lang3/ivydata-3.21.0.properties
/root/.ivy2/cache/org.apache.commons/commons-lang3/jars/commons-lang3-3.21.0.jar
/root/.ivy2/cache/org.apache.commons/commons-lang3/javadocs/commons-lang3-3.21.0-javadoc.jar
/root/.ivy2/cache/org.apache.commons/commons-lang3/sources/commons-lang3-3.21.0-sources.jar

5古い Ant + Spring のプロジェクトを開いたときに見る順

職場の build.xml を読むときの手がかりを、今回の実物を根拠に表にしました。上から順に、、 の値、lib/ か ivy.xml か、、、出力先、 のファイルです。頻度の分からないもの( の同居など)は、そう書いています。

読む順と、それで分かること表
1. build.xml の <project default="…">
分かること: 引数なしで ant と打ったときに走る target
根拠 : 「Ant で Spring の WAR を作る」の build.xml は default="war"。
ant -p の最終行にも出る
 
2. <property name="src.dir" value="src"/> など
分かること: src、build、dist、lib、WebContent の実際の名前。
全部ここで決まる
根拠 : 公式サイトの原文 does not impose coding conventions or
directory layouts。既定で読むファイル名 build.xml も
-f で変えられる
 
3. <target> の description
分かること: ant -p に出る target の一覧。description のある target が
1つでもあれば、無い target は出ない
根拠 : マニュアル(deemed internal and will not be listed)と実測
 
4. lib/ に JAR が直接ある
分かること: 依存を人が置いて管理している。推移依存も人が辿る
根拠 : 「Ant で Spring の WAR を作る」の lib/ に 11 本。
Maven の作者の回想:
all the JARs that we were depending on were stored in CVS
 
5. ivy.xml がある
分かること: Ivy に取らせている。ivy の JAR を ant -lib か
~/.ant/lib に置いて動かす
根拠 : <ivy:retrieve/> が lib/ へコピーする。
無いと failed to create task or type
 
6. <path id="…"><fileset dir="lib"/></path>
分かること: クラスパスの定義。javac の classpathref と
war の <lib> から参照される
根拠 : lib/ 直下の *.jar 全部、の意味
 
7. WebContent/
分かること: Eclipse の Dynamic Web Project が以前の既定で付けていた
名前。WAR の中身の元になるフォルダ。Ant では、何を WAR に
入れるかは build.xml の <war> が決める
根拠 : Eclipse ヘルプ: The Web content folder represents
the contents of the WAR file。2021年1月の WTP の
コミット [417874] で既定は src/main/webapp に変わった
 
8. WebContent/WEB-INF/web.xml
分かること: Tomcat が WAR を展開したあとに読む、このアプリの設定。
Spring の ContextLoaderListener と DispatcherServlet
根拠 : レッスン「Ant で Spring の WAR を作る」
 
9. build/、dist/
分かること: ビルドの出力。名前は property 次第。clean の target が消す
根拠 : 「Ant で Spring の WAR を作る」では build/classes/ と
dist/shop.war。2回目の ant は見出しだけで何もしない
 
10. .project、.classpath
分かること: Eclipse がプロジェクトごとに作る記述ファイル。
Java プロジェクトなら .classpath も
根拠 : Eclipse ヘルプ: This file is always called ".project"。
同居の頻度は確かめていない

図やコードに出てくる用語(タップで説明)