<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
	<properties>
		<title>アプリケーションのビルド方法</title>
	</properties>
	<body>
		<section name="目次">
			<ul>
				<li><a href="#概要">概要</a></li>
				<li><a href="#javacのバグについて">javacのバグについて</a></li>
				<li><a href="#Antによるビルド">Antによるビルド</a></li>
				<li><a href="#Mavenによるビルド">Mavenによるビルド</a></li>
				<li><a href="#Gradleによるビルド">Gradleによるビルド</a></li>
			</ul>
		</section>
		<section name="概要">
			<p>
				Domaを利用するアプリケーションを、AntもしくはMavenによってビルドする方法を示します。
			</p>
			<p>
				2011年8月現在、JDK6のjavacにはaptに関するバグがあることが判明しています。
				ここでは、このバグの回避を考慮に入れて解説します。
			</p>
			<p>
				なお、このバグはJDK7のjavacでは解決されています。
			</p>
		</section>
		<section name="javacのバグについて">
			<p>
				バグは、Bug DatabaseにBug ID <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403465">6403465</a>として登録されています。
				このバグの内容は、一言で言うと、本来はコンパイルエラーでないものがエラーとして報告されるというものです。
			</p>
			<p>
				回避方法の1つは、誤って報告されるエラーメッセージを単に無視することです。
			</p>
			<p>
				このバグの現象は、aptにより生成されるJavaコードに依存するコードをjavacの対象にすると起こります（aptにより生成されるJavaコードと依存するコードが異なるパッケージの場合にのみ起きます）。
				たとえば、javacは、以下のコードに対し間違ったエラー報告をします（EmployeeDaoImplというクラスがaptにより生成されると前提します）。
			</p>
<source><![CDATA[package tutorial.service;

import tutorial.dao.EmployeeDao;
import tutorial.dao.EmployeeDaoImpl;
import tutorial.entity.Employee;

public class TutorialService {

    public Employee selectById(Integer id) {
        EmployeeDao dao = new EmployeeDaoImpl();
        return dao.selectById(id);
    }
}]]></source>
			<p>
				javacから出力される間違ったエラー報告とは次のようなものです。
			</p>
<source><![CDATA[tutorial\service\TutorialService.java:19: シンボルを見つけられません。
シンボル: クラス EmployeeDaoImpl
場所    : tutorial.dao の パッケージ
import tutorial.dao.EmployeeDaoImpl;
                   ^]]></source>
			<p>
				このメッセージが出力されても、実際にはコンパイルは成功しています。
			</p>
			<p>
			</p>
			<p>
				もう1つの回避方法は、aptにより生成されるJavaコードに直接依存するコードを書かないことです。
				この方法を利用する場合、aptにより生成されるJavaコードのクラスには実行時にリフレクションを使ってアクセスする必要があります。
				この場合、自前でファクトリクラスを作成するか、Seasar2やSpring Frameworkといった汎用的なDIコンテナを活用することを推奨します。
			</p>
		</section>
		<section name="Antによるビルド">
			<p>
				<a href="http://ant.apache.org/">Ant</a>でビルドを行うには、あらかじめAntをインストールしてください。
				Ant 1.7で動作を確認しています。
			</p>
			<p>
				Antでビルドを行う際のポイントを示します。
			</p>
			<ul>
				<li>クラスパスには、doma-x.x.x.jarを指定する</li>
				<li>コンパイル前にSQLファイルをクラスが出力されるディレクトリにコピーする</li>
				<li>javacの-sオプションを使い、aptで生成されるコードの出力先ディレクトリを指定する</li>
			</ul>
			<p>
				サンプルのビルドファイルを示します。このビルドファイルは、チュートリアルの配布ファイルに含まれるものです。
				チュートリアルは<a href="../downloads.html">ダウンロードページ</a>からダウンロードできます。
			</p>
<source><![CDATA[<project name="doma-tutorial" default="jar" basedir=".">

    <property name="dest" value="target/build"/>
    <property name="apt_generated" value="target/apt_generated"/>
    <property name="src" value="src/main/java"/>
    <property name="resources" value="src/main/resources"/>

    <path id="classpath">
        <fileset dir="lib" includes="*.jar"/>
    </path>

    <target name="jar" depends="clean,copy,compile">
        <jar jarfile="target/doma-tutorial.jar" basedir="${dest}" />
    </target>

    <target name="clean">
        <delete dir="target" failonerror="false"/>
        <mkdir dir="target"/>
        <mkdir dir="${dest}"/>
        <mkdir dir="${apt_generated}"/>
    </target>

    <target name="compile">
        <javac fork="yes" compiler="javac1.6" debug="on" encoding="UTF-8"
            classpathref="classpath" srcdir="${src}" destdir="${dest}">
            <compilerarg line="-s ${apt_generated}" />
        </javac>
    </target>

    <target name="copy">
        <copy todir="${dest}" filtering="true">
            <fileset dir="${resources}">
                <include name="META-INF/**" />
            </fileset>
        </copy>
    </target>
</project>]]></source>
			<p>
				javacタスク実行時にはjavacのバグによりエラーメッセージが誤って報告されますが、「BUILD SUCCESSFUL」というメッセージとともにAntの実行が終了すれば、ビルドは成功しています。
			</p>
			<p>
				Antを使ったWebアプリケーションのビルドについては、Doma JPetStoreの配布ファイルに含まれるbuild.xmlを参考にしてください。
				Doma JPetStoreは<a href="../downloads.html">ダウンロードページ</a>からダウンロードできます。
			</p>
		</section>
		<section name="Mavenによるビルド">
			<p>
				<a href="http://maven.apache.org/">Maven</a>でビルドを行うには、あらかじめMavenをインストールしてください。
				Maven 3.0.3で動作を確認しています。
			</p>
			<p>
				Mavenでビルドを行う際のポイントを示します。
			</p>
			<ul>
				<li>依存関係の設定でdomaへの依存を指定する</li>
				<li>maven-resources-pluginを使いSQLファイルのコピーを行う</li>
				<li>上記処理後、maven-processor-pluginでapt処理を行う</li>
				<li>上記処理後、maven-compiler-pluginを使いコンパイルを行う（ただし、aptの処理は行わない。つまり、compilerArgumentで-proc:noneを指定する）</li>
			</ul>
			<p>
				サンプルのpom.xmlの抜粋を示します。pom.xmlは、チュートリアルに含まれるものです。
				チュートリアルは<a href="../downloads.html">ダウンロードページ</a>からダウンロードできます。
			</p>
<source><![CDATA[<plugin>
    <groupId>org.bsc.maven</groupId>
    <artifactId>maven-processor-plugin</artifactId>
    <version>2.0.5</version>
    <executions>
        <execution>
            <id>process</id>
            <goals>
                <goal>process</goal>
            </goals>
            <phase>process-resources</phase>
            <configuration>
                <outputDirectory>${project.build.directory}/apt_generated</outputDirectory>
                <failOnError>false</failOnError>
            </configuration>
        </execution>
    </executions>
</plugin>]]></source>
			<p>
				failOnErrorにはfalseを指定してください。
				javacのバグにより報告されるエラーによって処理を中断しないようにするためです。
			</p>
			<p>
				この例では使用していませんが、aptにパラメータを渡す場合にはmaven-processor-pluginのcompilerArguments要素を使ってください。
			</p>
			<p>
				Mavenを使ったWebアプリケーションのビルドについては、Doma JPetStoreの配布ファイルに含まれるpom.xmlを参考にしてください。
				Doma JPetStoreは<a href="../downloads.html">ダウンロードページ</a>からダウンロードできます。
			</p>
		</section>
		<section name="Gradleによるビルド">
			<p>
				Gradle 1.6で動作確認しています。
			</p>
			<p>
				Gradleでビルドを行う際のポイントを示します。
			</p>
			<ul>
				<li>JavaクラスとSQLファイルの出力先ディレクトリを同じにする</li>
				<li>コンパイルより前にSQLファイルを出力先ディレクトリにコピーする</li>
				<li>依存関係の設定でdomaへの依存を指定する</li>
			</ul>
			<p>
				サンプルのbuild.gradleを示します。このファイルはチュートリアルに含まれています。
			</p>
<source><![CDATA[apply plugin: 'java'

sourceCompatibility = targetCompatibility = 1.6
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
// JavaクラスとSQLファイルの出力先ディレクトリを同じにする
processResources.destinationDir = compileJava.destinationDir
// コンパイルより前にSQLファイルを出力先ディレクトリにコピーするために依存関係を逆転する
compileJava.dependsOn processResources

def aptGeneratePath = 'build/apt_generated'
compileJava.options.compilerArgs = ['-s', aptGeneratePath]
new File(aptGeneratePath).mkdirs()

repositories {
  mavenLocal()
  mavenCentral()
  // domaのMavenリポジトリを指定する
  maven {url 'http://maven.seasar.org/maven2'}
}

dependencies {
  // domaへの依存を指定する
  compile 'org.seasar.doma:doma:1.31.0'
  compile 'com.h2database:h2:1.3.171'
  testCompile 'junit:junit:3.8.2'
}]]></source>
			<p>
				Java6でビルドする場合は、<a href="#javacのバグについて">javacのバグについて</a>も参照ください。
			</p>
			<p>
				Java7以上でビルドする場合は、<a href="#javacの警告について">javacの警告について</a>も参照ください。
			</p>
		</section>
	</body>
</document>