これは、Java EE Advent Calendar 2015 - Qiitaの2日目(12月2日)の記事だよ。
昨日は、キクタロー(@kikutaro_)さんのJava EEでMicroserviceを実現するKumuluzEE #javaee #Qiita ね。
明日は、Kohei Nozaki(@lbtc_xxx)さんが書くみたい。
今日は、Gradleを使って、
GlassFish上で動くWebアプリをNetBeansで開発するときのプロジェクトを作ってみようと思いま〜す。
Webアプリは、CDIとJPA使う想定で、ユニットテストも出来るようにしたいかも。
でも、中身はなしでっ。
開発する環境を用意するのを中心にやることにするのだ。
あと、ユニットテストでCDIとかJPAを使う具体的な方法は別の記事を参照ってことで、
環境の前提はこんな感じでいくね。
1.Windows 8.1(まだ10にしてない)
2.JDK 1.8(手元で使ってるのはupdate66)
3.NetBeans 8.1(JavaEE開発用)
4.GlassFish 4.1(ドメインとデータソースの設定済み)(GlassFish 4.1.1でもほとんどおなじ)
流れは、こんな感じで。
1.GlassFishのサーバーとドメインをNetBeansに設定
2.NetBeansのGradle Supportモジュールをインストール
3.Gradleのプロジェクトを作ってビルドファイルをかきかきφ(。。
4.簡単な拡張とか
と言うことで。
☆☆☆1.GlassFishのサーバーとドメインをNetBeansに設定☆☆☆
ドメインの作成、DBのライブラリの設定、データソースの設定は終わってる前提だから、
NetBeansに登録して使えるようにするところから。
サーバーの追加でGlassFishを選んで……、
ここではGlassFish 4.1って名前にするね。この名前は後で使うよ。
GlassFishのインストール先と、ドメインを指定して完了〜。
☆☆☆2.NetBeansのGradle Supportモジュールをインストール☆☆☆
いれるのは、これね、これ。
https://github.com/kelemen/netbeans-gradle-project
NetBeansのメニューバーから、ツール→プラグインと選んで、
プラグインの検索とインストール、更新が出来るダイアログを開くよ。
Gradleって検索すると『Gradle Support』って言うが見つかるからそれ。
もう1個のはよく知らない。とりあえず今回はいらないのでどっちでも。
何が出来るようになるんだろうね。
インストールしようとすると
『GroovyおよびGrails』も一緒に入れないとなのでまとめて入れちゃう。
GradleがGroovyで動くからだね。
NetBeansの再起動を要求されるから再起動すればGradleを使う準備は完了!
☆☆☆3.Gradleのプロジェクトを作ってビルドファイルをかきかきφ(。。☆☆☆
さぁ、新規プロジェクトを作るよ。
今回は、Single Gradle Projectで。
複雑なプロジェクト構成を組む場合は、Gradle Root Projectね。
Java用のbuild.gradleファイルが出来ているはず。
でもこのファイルは、Webアプリ用じゃないから、
ばっさりと書き換えちゃう。こんな感じに。
// GradleでGlassFishにアクセスするためのプラグイン用意してみたからそれ使うのだ。
// http://memory.empressia.jp/article/167469186.html
buildscript {
repositories {
maven { url "http://www.empressia.jp/maven/"; }
}
dependencies {
classpath group: "jp.empressia", name: "jp.empressia.gradle.plugin.glassfish", version: "0.2.2";
}
}
// warをパッケージする。
apply plugin: "war";
// GlassFish用のタスクを追加する。
apply plugin: "glassfish";
// NetBeansのGlassFish設定を読み込める様にする。
apply plugin: "glassfish.netbeans";
// Java8で。
sourceCompatibility = 1.8;
targetCompatibility = 1.8;
// Mavenな感じと同じようにclassesの中にリソースが配置されるようにする。
sourceSets {
main.output.resourcesDir = main.output.classesDir;
test.output.resourcesDir = test.output.classesDir;
}
// アプリの依存性解決用のリポジトリにMavenセントラル使うよ。
repositories {
mavenCentral();
}
// 依存関係。必要なの追加で。
dependencies {
providedCompile(group:"javax", name:"javaee-web-api", version:"7.0");
}
// NetBeans GlassFishプラグインの設定。NetBeansに登録したGlassFishサーバーを使う設定をしているよ。
// 記事の前半で設定したサーバーの名前を設定するのだ。
// glassfish.netbeans.serverName = "GlassFish Server 4.1";って書いてもokだからね。
glassfish {
netbeans {
serverName = "GlassFish Server 4.1";
}
}
// JavaはUTF-8でいいよね。
tasks.withType(JavaCompile) {
options.encoding = "UTF-8";
}
// リソースは、classes側に移動するようにしたからデプロイでリソースを個別に動かす必要はないからスルーする設定。
tasks.deployResources {
exclude "**/*"
}
これで基本的な設定は終わり〜。
開始ボタン、ビルドボタン、とか普通に動くはず。
ブラウザは自動では開かないから、自分で開くっ。一度開けばいいし、良いよね。
あと、ログ見たいときは、サービスのサーバーからドメイン・サーバー・ログの表示を選べばでてくるよ。
これも一度だけ選べばずっと出てるかな。
あ、メインメニューのツール→オプションの設定に、Compile on saveがあるから、使ってみるといいかも。
プロジェクトのプロパティ設定でApply Code Changesを『${project}:deploy』がおすすめかな。
☆☆☆4.簡単な拡張とか☆☆☆
☆ユニットテストでCDIとJPAを使う設定
CDIを実際に動かすには、コンテナ作るか用意しないとだと思うけど、
基本的な設定はこんな感じ?
dependenies {
// testRuntimeでも良いのもあるかも。
testCompile(group:"junit", name:"junit", version:"4.12");
testCompile(group:"org.hamcrest", name:"hamcrest-library", version:"1.3");
testCompile(group:"org.jboss.weld.se", name:"weld-se", version:"2.2.2.Final");
testCompile(group:"org.eclipse.persistence", name:"eclipselink", version:"2.5.2-RC1");
testCompile(group:"javax.transaction", name:"javax.transaction-api", version:"1.2");
}
tasks.test {
doFirst {
// test側のbeans.xmlに書かれた内容をユニットテストの時に読み込まれるようにbeans.xmlをmainのclassesにコピーする。
// 要らなければスルーで。
copy { from "${sourceSets.test.resources.srcDirs.find({true})}/META-INF/beans.xml" into "${sourceSets.main.output.resourcesDir}/META-INF/" }
// コネクションはテスト側にあっても取れるけど、Entityはmain側にないと読み込めないから、persistence.xmlをmainのclassesにコピーする。
// あと、persistence.xmlの競合を避けるために、テスト側からpersistence.xmlを削除する。
copy { from "${sourceSets.test.resources.srcDirs.find({true})}/META-INF/persistence.xml" into "${sourceSets.main.output.resourcesDir}/META-INF/" }
delete "${sourceSets.test.output.resourcesDir}/META-INF/persistence.xml"
}
// JPAをJavaAgentで使う〜。
jvmArgs "-javaagent:${configurations.testCompile.files.find({ file -> file.name.equals('eclipselink-2.5.2-RC1.jar') })}"
}
// ビルドする場合は、testをはじめる前にパッケージ(とデプロイ)をしないと、テスト直前でリソースを書き換えているのが問題になっちゃうから、依存関係を追加しておく。
if(this.gradle.startParameter.taskNames.contains("build")) {
// tasks.test.dependsOn(tasks.assemble);っていう方法も。
tasks.test.dependsOn(tasks.war);
tasks.test.dependsOn(tasks.deploy);
}
余談だけど、CDIってなんかパッケージの外から設定上書きできないのかなぁ?
Alternativeとか、外から切り替えたいんだけど、できないよね。
そのうちできるようになるのかなぁ……?それとも、そういうものじゃないのかな……?
☆LESSを使う設定
LESS便利だよね。と言うか、CSSが不便すぎて……。
パスを直接ビルドファイルに書くのいやだし、NetBeansからパスを読み込むのを用意してみたよ。
ビルドスクリプトに追加で。
buildscript {
repositories {
maven { url "http://www.empressia.jp/maven/"; }
}
dependencies {
classpath group: "jp.empressia", name: "jp.empressia.gradle.plugin.netbeans.configuration", version: "0.0.6";
}
}
apply plugin: "netbeans.configuration";
// タスクを追加するよ。
// タスクの定義で『<<』で作ってる例あるけど、タスクの定義に『<<』は追加したらだめだよね。
// タスクの定義ちゃんとしてインクリメンタルビルドしないとね。
task processLess(type: Copy) {
from webAppDir
into webAppDir
include "**/*.less"
eachFile { file ->
exec {
commandLine "${netbeans.configuration.lessPath}", "--compress", "${webAppDir}/${file.path}", "${webAppDir}/${file.path.substring(0, file.path.length() - '.less'.length())}.min.css"
}
file.exclude();
}
}
// タスクの依存関係はこんな感じ?
// コンパイル系の作業の中にLESSコンパイルもいれるよ。
tasks.classes.dependsOn(tasks.processLess);
他にも、netbeans.configuration.***Pathっていう形でいろいろ取れるようにしてあるよ。
- sassPath
- gruntPath
- gulpPath
- karmaPath
- expressPath
- nodePath
- npmPath
バージョンとか指定したい場合は
netbeans {
configuration {
version = "8.1";
}
}
とか
netbeans {
configuration {
appDataDirectoryPath = "C:/Users/[UserName]/AppData/Roaming/NetBeans";
version = "8.1";
}
}
とか
netbeans {
configuration {
directoryPath = "C:/Users/[UserName]/AppData/Roaming/NetBeans/8.1/config";
}
}
とかで指定できるよ。
☆JavadocとMavenでのアップロードは……。
まぁ、いいよね。
今回は、スルーで。
☆最終的なbuild.gradle
こんな感じになるかな?
buildscript {
repositories {
maven { url "http://www.empressia.jp/maven/"; }
}
dependencies {
classpath group: "jp.empressia", name: "jp.empressia.gradle.plugin.glassfish", version: "0.2.2";
classpath group: "jp.empressia", name: "jp.empressia.gradle.plugin.netbeans.configuration", version: "0.0.6";
}
}
apply plugin: "war";
apply plugin: "glassfish";
apply plugin: "glassfish.netbeans";
apply plugin: "netbeans.configuration";
sourceCompatibility = 1.8;
targetCompatibility = 1.8;
sourceSets {
main.output.resourcesDir = main.output.classesDir;
test.output.resourcesDir = test.output.classesDir;
}
repositories {
mavenCentral();
}
dependencies {
providedCompile(group:"javax", name:"javaee-web-api", version:"7.0");
testCompile(group:"junit", name:"junit", version:"4.12");
testCompile(group:"org.hamcrest", name:"hamcrest-library", version:"1.3");
testCompile(group:"org.jboss.weld.se", name:"weld-se", version:"2.2.2.Final");
testCompile(group:"org.eclipse.persistence", name:"eclipselink", version:"2.5.2-RC1");
testCompile(group:"javax.transaction", name:"javax.transaction-api", version:"1.2");
}
glassfish {
netbeans {
serverName = "GlassFish Server 4.1";
}
}
tasks.withType(JavaCompile) {
options.encoding = "UTF-8";
}
task processLess(type: Copy) {
from webAppDir
into webAppDir
include "**/*.less"
eachFile { file ->
exec {
commandLine "${netbeans.configuration.lessPath}", "--compress", "${webAppDir}/${file.path}", "${webAppDir}/${file.path.substring(0, file.path.length() - '.less'.length())}.min.css"
}
file.exclude();
}
}
tasks.classes.dependsOn(tasks.processLess);
tasks.deployResources {
exclude "**/*"
}
tasks.test {
doFirst {
copy { from "${sourceSets.test.resources.srcDirs.find({true})}/META-INF/beans.xml" into "${sourceSets.main.output.resourcesDir}/META-INF/" }
copy { from "${sourceSets.test.resources.srcDirs.find({true})}/META-INF/persistence.xml" into "${sourceSets.main.output.resourcesDir}/META-INF/" }
delete "${sourceSets.test.output.resourcesDir}/META-INF/persistence.xml"
}
jvmArgs "-javaagent:${configurations.testCompile.files.find({ file -> file.name.equals('eclipselink-2.5.2-RC1.jar') })}"
}
if(this.gradle.startParameter.taskNames.contains("build")) {
tasks.test.dependsOn(tasks.war);
tasks.test.dependsOn(tasks.deploy);
}
これで、割と自然にGradle+NetBeans+GlassFishでWebアプリ作れるんじゃないかなぁって。
そうそう、NetBeansのGradleプラグイン作ってる人に聞いたんだけど、
非同期構成意識して作っているからプロジェクトの構成が古いのと違っていて、
古いNetBeansのNode追加するプラグインがGradleのプロジェクトには追加されないんだよね(Ver.1.3.7.2)。
対応してもらったバージョン作ってもらったから、良ければ直接ダウンロードして使ってみてね。
https://github.com/kelemen/netbeans-gradle-project
NetBeans81ブランチで試してたんだけど、今は、masterにも取り込まれたみたいだよ。
かなり、メールの応答が速かったから、とっても助かったのだ(゜▽、゜感謝だね