What's?
Nablarchに関する確認をしていると、「WebアプリケーションをTomcatで動かして確認する」という場面がまあまああります。
これを「Tomcatをダウンロードして展開して…」などとやっているとなかなか面倒なので、Codehause Cargo Maven 3 Pluginを使って簡単に動かせるようにしてみます。
Codehause Cargo Maven 3 Plugin
Codehause CargoのWebサイトはこちら。
Codehause Cargoは、Java EE、Jakarta EEのアプリケーションサーバを統一された方法で操作できるラッパーです。
アプリケーションサーバの起動や停止、アプリケーションのデプロイなどができます。
GlassFish、Jetty、Tomcat、WebLogic、WebSphere、WildFlyなどたくさんのアプリケーションサーバに対応しています。
一方で、アプリケーションサーバ自体がこのようなツールを提供している場合はそちらを使った方がよい気もしますが、あいにくTomcatにはありません。
Mavenプラグインもあるので、こちらを使って今回はNablarchのブランクプロジェクトを動かしてみます。
環境
今回の環境はこちらです。
$ java --version
openjdk 21.0.11 2026-04-21 LTS
OpenJDK Runtime Environment (Red_Hat-21.0.11.0.10-1) (build 21.0.11+10-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-21.0.11.0.10-1) (build 21.0.11+10-LTS, mixed mode, sharing)
$ mvn --version
Apache Maven 3.9.16 (2bdd9fddda4b155ebf8000e807eb73fd829a51d5)
Maven home: /home/user/.local/share/mise/installs/maven/3
Java version: 21.0.11, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-21-openjdk
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "6.12.0-211.26.1.el10_2.x86_64", arch: "amd64", family: "unix"
Nablarchのブランクプロジェクトを作成する
まずはNablarchのブランクプロジェクトを作成しましょう。
対象のブランクプロジェクトは、ウェブアプリケーション用とします。
作成。
$ mvn archetype:generate \
-DinteractiveMode=false \
-DarchetypeGroupId=com.nablarch.archetype \
-DarchetypeArtifactId=nablarch-web-archetype \
-DarchetypeVersion=6u3 \
-DgroupId=com.example \
-DartifactId=hello-nablarch-web \
-Dversion=0.0.1 \
-Dpackage=com.example
プロジェクト内へ移動。
$ cd hello-nablarch-web
今回はJava 21を使うので、java.versionプロパティを変更します。
<!-- ソース及びclassファイルが準拠するJavaのバージョン-->
<java.version>17</java.version>
<!-- ソース及びclassファイルが準拠するJavaのバージョン-->
<java.version>21</java.version>
Codehause Cargo Maven 3 Pluginを導入する
Codehause Cargo Maven 3 Pluginを導入していきます。
対象はTomcat 10.xですね。
デプロイした時にわかりやすいようにfinalNameをROOTとします。
<build>
<resources>
<build>
<finalName>ROOT</finalName>
<resources>
ただ、コンテナ以外のブランクプロジェクトの場合は、そのままだとROOT-dev.warのような名前になってしまうためちょっと都合が悪いです。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>${webxml.path}</webXml>
<classifier>${env.classifier}</classifier>
<archive>
<manifestEntries>
<Target-Environment>${env.name}</Target-Environment>
</manifestEntries>
</archive>
</configuration>
</plugin>
今回はclassifierをコメントアウトします。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>${webxml.path}</webXml>
<!-- <classifier>${env.classifier}</classifier> -->
<archive>
<manifestEntries>
<Target-Environment>${env.name}</Target-Environment>
</manifestEntries>
</archive>
</configuration>
</plugin>
また実行時のuser.dirはmvnコマンドを実行したディレクトリではなくなってしまうので、相対パスで書かれたH2 Databaseの場所を
# JDBC接続URL(DataSourceを直接使用する際の項目)
# (TODO: 開発環境用の接続先に変更する。H2の接続URLは、データファイルの所在とユーザ名で決定される。変更する際は、理解したうえで変更すること)
nablarch.db.url=jdbc:h2:./h2/db/SAMPLE
絶対パスに変更しておきます。
# JDBC接続URL(DataSourceを直接使用する際の項目)
# (TODO: 開発環境用の接続先に変更する。H2の接続URLは、データファイルの所在とユーザ名で決定される。変更する際は、理解したうえで変更すること)
nablarch.db.url=jdbc:h2:/path/to/hello-nablarch-web/h2/db/SAMPLE
あとはCodehause Cargo Maven 3 Pluginを追加します。
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven3-plugin</artifactId>
<version>1.10.27</version>
<configuration>
<container>
<containerId>tomcat10x</containerId>
<zipUrlInstaller>
<url>https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/10.1.56/tomcat-10.1.56.tar.gz</url>
</zipUrlInstaller>
<timeout>0</timeout>
</container>
</configuration>
</plugin>
確認する
では、確認していきましょう。
gsp-dba-maven-pluginをJava 11以上で実行するための準備。
$ mkdir .mvn
$ echo '--add-opens java.base/java.lang=ALL-UNNAMED' > .mvn/jvm.config
実効。
$ mvn -P gsp clean generate-resources
パッケージングして、Tomcatを起動。
$ mvn package cargo:run -DskipTests
確認。
$ curl localhost:8080
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Webアプリケーション疎通確認</title>
</head>
<body>
<h1>Congratulations!</h1>
アプリケーションのデプロイに成功しました。
以下の疎通確認結果を確認してください。
<h2>各機能の疎通確認結果</h2>
<h3>ディスパッチ機能</h3>
ディスパッチ機能は正常に動作しています。
<h3>セッションストア</h3>
リロードする度に、以下のカウンタがカウントアップされていれば成功です。
<p>
カウンタ:0
</p>
<h3>コード管理機能</h3>
セレクトメニューが表示されていれば成功です。
<script type="text/javascript">
<!--
function nablarch_submit(event, element) {
if (element == null) {
element = event.currentTarget;
if (element == null) {
element = event.target;
}
}
var isAnchor = element.tagName.match(/a/i);
var form = nablarch_findForm(element, isAnchor);
if (form == null) {
return false;
}
var formName = form.attributes['name'].nodeValue;
if (nablarch_submission_info.endMark[formName] == null) {
return false;
}
if ((typeof form.onsubmit) == "function") {
if (!nablarch_invokeOnsubmit(form, event)) {
return false;
}
}
var submitName = element.name;
var formData = nablarch_submission_info[formName];
var submissionData = formData[submitName];
if (!submissionData.allowDoubleSubmission) {
element.onclick = nablarch_stopSubmission;
if (!isAnchor) {
element.disabled = true;
}
}
form["nablarch_submit"].value = submitName;
if (submissionData.submissionAction == "POPUP"
|| submissionData.submissionAction == "DOWNLOAD") {
nablarch_submitToNewForm(submitName, form, submissionData)
} else {
nablarch_submitOnWindow(submitName, form, submissionData);
}
return false;
}
function nablarch_submitOnWindow(submitName, form, submissionData) {
form.action = submissionData.action;
form.submit();
}
var nablarch_opened_windows = {};
function nablarch_submitToNewForm(submitName, form, submissionData) {
var target = submissionData.popupWindowName;
if (target == null) {
target = "nablarch__target_" + (+new Date());
}
if (submissionData.submissionAction == "POPUP") {
var windowOption = submissionData.popupOption;
var openedWindow = window.open("about:blank", target, windowOption != null ? windowOption : "");
nablarch_opened_windows[target] = openedWindow;
}
var tempForm = document.createElement("form");
var changeParamNames = submissionData.changeParamNames;
for (var i = 0; i < form.elements.length; i++) {
var element = form.elements[i];
if (element.type.match(/^submit$|^button$/i)) {
continue;
}
var paramName = changeParamNames[element.name];
if (paramName != null) {
nablarch_addHiddenTagFromElement(tempForm, paramName, element);
} else {
nablarch_addHiddenTagFromElement(tempForm, element.name, element);
}
}
if (submissionData.submissionAction == "POPUP") {
tempForm.target = target;
}
tempForm.action = submissionData.action;
tempForm.method = "post";
var body = document.getElementsByTagName("body")[0];
body.appendChild(tempForm);
tempForm.submit();
body.removeChild(tempForm);
}
function nablarch_findForm(element, isAnchor) {
if (isAnchor) {
var parent = element.parentNode;
while (parent != null && !parent.tagName.match(/^form$|^body$/i)) {
parent = parent.parentNode;
}
if (parent == null || !parent.tagName.match(/form/i)) {
return null;
}
return parent;
} else {
return element.form;
}
}
function nablarch_invokeOnsubmit(form, event) {
var onSubmitFunc = form.onsubmit;
var ret = onSubmitFunc.call(form, event);
return !( (ret != undefined && ret != null) && ret == false );
}
function nablarch_addHiddenTagFromElement(form, name, element) {
if (element.disabled) {
return;
}
if (element.tagName.match(/select/i)) {
for (var i = 0; i < element.options.length; i++) {
var option = element.options[i];
if (option.selected) {
nablarch_addHiddenTag(form, name, option.value);
}
}
} else if (element.type.match(/^checkbox$|^radio$/i)) {
if (element.checked) {
nablarch_addHiddenTag(form, name, element.value);
}
} else {
nablarch_addHiddenTag(form, name, element.value);
}
}
function nablarch_addHiddenTag(form, name, value) {
var input = document.createElement("input");
input.type = "hidden";
input.name = name;
input.value = value;
form.appendChild(input);
}
function nablarch_stopSubmission() {
if ((typeof nablarch_handleDoubleSubmission) == "function") {
nablarch_handleDoubleSubmission(this);
}
return false;
}
var nablarch_submission_info = {};
nablarch_submission_info.endMark = {};
-->
</script>
<form name="dummyForm" method="post">
<select name="sample.codeSelectValues" multiple="multiple">
<option value="0">アンロック</option>
<option value="1">ロック</option></select>
<input type="hidden" name="nablarch_hidden" value="csrf-token=480a5592-bc0e-453f-9bb3-431816c1d8c4" />
<input type="hidden" name="nablarch_submit" value="" />
<script type="text/javascript">
<!--
nablarch_submission_info.dummyForm = {
};
-->
</script>
</form>
<script type="text/javascript">
<!--
nablarch_submission_info.endMark.dummyForm = true;
-->
</script>
<h3>データベースアクセス機能</h3>
データベースアクセス機能は正常に動作しています。
<h3>メッセージ管理機能</h3>
<p>
「」内にメッセージが表示されていれば成功です。
</p>
メッセージID=errors.doubleSubmission のメッセージは
<p>
「画面遷移が不正です。」
</p>
です。
<h3>リソースマッピング</h3>
<p>
画像が表示されていれば成功です。
</p>
<img src="/images/nablarch-logo.jpg;jsessionid=ABD608718DBC817CB62B31A7010259D5" alt="logo" />
<hr/>
確認完了後は、疎通確認用のリソースを削除してください。
</body>
</html>
OKですね。
こんな感じでさらっと使えるようになるので、なかなか便利だと思います。
なお、実行時のuser.dirはこのような値になっています。
$ jcmd [PID] VM.system_properties | grep user.dir
user.dir=/path/to/hello-nablarch-web/target/cargo/configurations/tomcat10x