技術記事については、Qiitaにも稀に投稿しています。

さくらVPS上のGlassFishに自作のRESTなAPIをデプロイする

java_white

三部作で執筆した「NetBeansとJavaEEで、ポケモンの日英仏独韓の名前を返すRESTなAPIを開発」シリーズの続編的な内容を実践してみました。

シリーズ本編(?)では、タイトル通り、RESTなAPIを開発するに留まっており、実際にサーバ上で動かすところまではしていなかったわけですが、このAPIを使ってフロントエンドのあれこれも勉強してみたい、ということでまずは稼働させるところまでやってみよう、と。

API開発の本編は以下から

APIの稼働(デプロイ)環境

前提として、本サーバはさくらのVPS上に構築するものとします。

Server OS CentOS release 6.3 (Final)
App Server GlassFish4.1
DB MySQL Ver 14.14 Distrib 5.5.27, for Linux (x86_64) using readline 5.1
Java java version "1.7.0_21"

GlassFishの準備

GlassFishの入手

wgetコマンドで入手しましょう。執筆時点での最新は4.1です。

$ wget http://download.java.net/glassfish/4.1/release/glassfish-4.1.zip

--2016-06-27 22:02:08--  http://download.java.net/glassfish/4.1/release/glassfish-4.1.zip
download.java.net をDNSに問いあわせています... 23.32.241.32, 23.32.241.25
download.java.net|23.32.241.32|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 107743725 (103M) [application/zip]
`glassfish-4.1.zip' に保存中

100%[=================================================================================>] 107,743,725  669K/s 時間 81s

2016-06-27 22:03:30 (1.27 MB/s) - `glassfish-4.1.zip' へ保存完了 [107743725/107743725]

解凍と配備

zipなので解凍して、/usr/local/配下に配備します。

$ unzip glassfish-4.1.zip
$ sudo mv glassfish4 /usr/local/

デフォルトのポートの確認(と変更)

変更については任意ですが、一応確認の方法だけ記しておくとします。

$ vim /usr/local/glassfish4/glassfish/domains/domain1/config/domain.xml

<network-listeners>
  <network-listener port="8080" protocol="http-listener-1" transport="tcp" name="http-listener-1" thread-pool="http-thread-pool"></network-listener>
  <network-listener port="8181" protocol="http-listener-2" transport="tcp" name="http-listener-2" thread-pool="http-thread-pool"></network-listener>
  <network-listener port="4848" protocol="admin-listener" transport="tcp" name="admin-listener" thread-pool="admin-thread-pool"></network-listener>
</network-listeners>

GlassFishの起動と停止

ほんとは/etc/init.d/配下にスクリプト作って、サービス登録しておくとよさげだけど、それはまた今度ってことで基本コマンド。

起動

$ /usr/local/glassfish4/glassfish/bin/asadmin start-domain

Waiting for domain1 to start ...............................................
Successfully started the domain : domain1
domain  Location: /usr/local/glassfish4/glassfish/domains/domain1
Log File: /usr/local/glassfish4/glassfish/domains/domain1/logs/server.log
Admin Port: 4848
Command start-domain executed successfully.

停止

/usr/local/glassfish4/glassfish/bin/asadmin stop-domain

GlassFishの各種設定

管理パスワード変更

この後、GlassFishの管理コンソールを開くのですが、そこにログインするためのパスワードを設定しておきます。なお、最初の二つはNULLで問題ありません。(user nameは'admin'となります)

$ /usr/local/glassfish4/glassfish/bin/asadmin change-admin-password

Enter admin user name [default: admin]> (空)
Enter the admin password> (空)
Enter the new admin password>
Enter the new admin password again>
Command change-admin-password executed successfully.

再起動

設定反映のため、一度リスタートします。

$ /usr/local/glassfish4/glassfish/bin/asadmin restart-domain

Successfully restarted the domain
Command restart-domain executed successfully.

管理画面に入るための各種設定

先ほど設定したuser nameとpasswordでログインします。

$ /usr/local/glassfish4/glassfish/bin/asadmin login

Enter admin user name [Enter to accept default]> admin
Enter admin password>
Login information relevant to admin user name [admin] for host [kt-kiyoshi.com] and admin port [4848] stored at [/home/kodamat/.gfclient/pass] successfully.
Make sure that this file remains protected. Information stored in this file will be used by administration commands to manage associated domain.
Command login executed successfully.

こちらはSSLをenableにしている、といった具合でしょうか。(いまいちよく分かっていない)

$ /usr/local/glassfish4/glassfish/bin/asadmin enable-secure-admin

You must restart all running servers for the change in secure admin to take effect.
Command enable-secure-admin executed successfully.

Linuxのファイアウォール

本来であれば、ここまでやれば、ポート番号4848でGlassFishの管理コンソールにアクセス(&ログイン)できるはずなのだけど、今回はiptableの設定をしておきます。(というか、してなくて繋がらなかった)

4848番ポートを解放(設定)

とりあえず、管理コンソール用の4848番ポートを開放してあげます。ちなみに、8080番はTomcat用に開けていたので問題なしです。

$ sudo vi /etc/sysconfig/iptables

# glassfish
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 4848 -j ACCEPT

iptablesの再起動

$ sudo /etc/rc.d/init.d/iptables restart

iptables: ファイアウォールルールを消去中:                  [  OK  ]
iptables: チェインをポリシー ACCEPT へ設定中filter         [  OK  ]
iptables: モジュールを取り外し中:                          [  OK  ]
iptables: ファイアウォールルールを適用中:                  [  OK  ]

サーバ上にDBを作成

今回はローカルで開発した時と同様なDBをサーバ上にも作成します。別途データも入れます。(こちらに記載しているものと同様のデータです)

mysql> CREATE DATABASE _pkmn_db;
Query OK, 1 row affected (0.14 sec)

mysql> use _pkmn_db
Database changed

mysql> CREATE TABLE `pkmn_base` (
    ->   `number` int(5) NOT NULL,
    ->   `jp_name` varchar(10) NOT NULL COMMENT '日本語名',
    ->   `en_name` varchar(10) DEFAULT NULL COMMENT '英語名',
    ->   `ge_name` varchar(10) DEFAULT NULL COMMENT 'ドイツ語名',
    ->   `fr_name` varchar(10) DEFAULT NULL COMMENT 'フランス語名',
    ->   `kr_name` varchar(10) DEFAULT NULL COMMENT '韓国語名',
    ->   `created_datetime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '作成日時',
    ->   `updated_datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新日時'
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.65 sec)

実は知らなかったのだけど、MySQLでは「CURRENT_TIMESTAMP」を持つカラムを同一テーブル内には作れないらしいです。なので、作成日時のほうは0000-00-00 00:00:00がデフォルト。

以下はデータの挿入コマンド。外部ファイルとしてINSERT文を用意して取り込んでいます。

$ mysql -p _pkmn_db < pkmn_base_insert.sql

Enter password:

MySQL用のJDBCドライバーを用意

ローカルで使ったものと同様のJDBCドライバーでOKです。(ローカルでは5.1.38でしたが、執筆時点では5.1.39が最新になってました)

$ pwd;ls -l mysql*

/usr/local/glassfish4/glassfish/lib
-rw-r--r-- 1 kodamat kodamat 983914  6月 27 23:05 2016 mysql-connector-java-5.1.39-bin.jar

GlassFishにDBとのConnection Poolを作成(設定)

http://{Server}:4848で管理コンソールにアクセス

最初は以下のようなSSL証明書エラーの警告が出るかと思います。が、これは承認します。

ssl_cert

すると、以下のようなログインフォームが表示されます。ここに先ほど設定したuser nameとpasswordを入力すると管理コンソールにログインすることができます。

glassfish_admin

glassfish_console

JDBC Connection Poolの作成

いわゆるDBの接続情報です。左のメニューのJDBC -> JDBC Connection Poolを開き、【New...】を押下し、必要事項を埋めます。今回は以下のような感じとなりました。

Pool Name PkmnPool(任意)
Resource Type javax.sql.DataSource
Database Driver Vender MySQL
Introspect チェック無し

【Next】を押下し、Step2に進みます。Additional Propertiesは以下のようにDBの接続情報を記入します。当然ですが、userとpasswordは伏せ字でなく実際のものを入れます。

db_pool

MySQLのドライバーへのPATHを設定

左のメニューのConfiguration -> default-config -> JVM Setting -> Path Settingの【Native Library Path Suffix】にドライバーのフルパスを入力します。

/usr/local/glassfish4/glassfish/lib/mysql-connector-java-5.1.39-bin.jar

接続確認

先ほど作成したConnection Poolの設定に戻り、【Ping】を押し、以下のようにPing Succeededとなれば接続成功です。

jdbc_ping

JDBC Resourceの作成

最後に左のメニューのJDBC Resourcesから【New...】で、JDBC Resourceを作成します。

JNDI Name jdbc/_pkmn_db
Pool Name PkmnPool
Description (任意)
Status Enabled

ここまでできたら、サーバ上のdomain.xmlを確認してみます。

$ view /usr/local/glassfish4/glassfish/domains/domain1/config/domain.xml

    <jdbc-connection-pool datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" res-type="javax.sql.DataSource" name="PkmnPool">
      <property name="portNumber" value="3306"></property>
      <property name="databaseName" value="_pkmn_db"></property>
      <property name="datasourceName" value="PkmnPool"></property>
      <property name="serverName" value="kt-kiyoshi.com"></property>
      <property name="user" value="xxxxxxxx"></property>
      <property name="password" value="xxxxxxxx"></property>
    </jdbc-connection-pool>
    <jdbc-resource pool-name="PkmnPool" jndi-name="jdbc/_pkmn_db"></jdbc-resource>

GlassFishにアプリケーションをデプロイ

warファイルの配備

ローカルでビルドしたwarファイルをサーバ上へscpなりftpなりで転送して、GlassFishの/domains/domain1/applications/配下に置きます。なお、今回は試しにversion1.0のSNAPSHOTのまま置いてみます。

$ cd /usr/local/glassfish4/glassfish/domains/domain1/applications/
$ cp ~/pkmnAPI-1.0-SNAPSHOT.war .

あとは、asadmin deploy XXXX.warでアプリケーションがGlassFishにデプロイされます。

デプロイ(deploy)

$ /usr/local/glassfish4/glassfish/bin/asadmin deploy pkmnAPI-1.0-SNAPSHOT.war

Application deployed with name pkmnAPI-1.0-SNAPSHOT.
Command deploy executed successfully.

再起動(restart-domain)

$ /usr/local/glassfish4/glassfish/bin/asadmin restart-domain

Successfully restarted the domain
Command restart-domain executed successfully.

確認

warファイルは無くなり、代わりに同名のディレクトリなどが作成されています。

$ pwd;ls -l

/usr/local/glassfish4/glassfish/domains/domain1/applications
合計 8
drwxrwxr-x 3 kodamat kodamat 4096  6月 28 06:39 2016 __internal
drwxrwxr-x 5 kodamat kodamat 4096  6月 28 06:39 2016 pkmnAPI-1.0-SNAPSHOT

APIをブラウザから叩くには、https://kt-kiyoshi.com:8080/pkmnAPI-1.0-SNAPSHOT/rest/pkmn/getAllにアクセスすればOKです。
(※上記のAPIは現在は停止しています。だって、URLにSNAPSHOTとかかっこ悪いし...)

ちなみに、返ってきた結果を整形したものがこちらです。

[
  {
    "en_name": "Bulbasaur",
    "fr_name": "Bulbizarre",
    "ge_name": "Bisasam",
    "jp_name": "フシギダネ",
    "kr_name": "이상해씨",
    "number": 1
  },
  {
    "en_name": "Ivysaur",
    "fr_name": "Herbizarre",
    "ge_name": "Bisaknosp",
    "jp_name": "フシギソウ",
    "kr_name": "이상해풀",
    "number": 2
  },
・・・
・・・
・・・
  {
    "en_name": "Hoopa",
    "fr_name": "Hoopa",
    "ge_name": "Hoopa",
    "jp_name": "フーパ",
    "kr_name": "후파",
    "number": 720
  },
  {
    "en_name": "Volcanion",
    "fr_name": "Volcanion",
    "ge_name": "Volcanion",
    "jp_name": "ボルケニオン",
    "kr_name": "볼케니온",
    "number": 721
  }
]

とりあえずローカルで動作させた時同様のJSON形式で返ってきているのでOKですね。実際にこれを使うなら

  • -1.0-SNAPSHOTを外す
  • JSONP形式で返す

この辺はやりたいと思うのですが、それはまた次回以降としたいと思います。どろん。