JAX-RS RESTful Web Service について二回に分けて記事を記した。
- JAX-RS - misima RESTful Web Service の実装 (サーバ実装及び curl/ブラウザ試験)
- misima RESTful Web Service Perl クライアント (REST::
Client モジュール)
今日は Apache Wink 1.4 ライブラリを用いた Java REST クライアント・プログラムを書いてみた。Eclipse 開発環境(Eclipse Java EE IDE for Web Developers. Version: Kepler Service Release 1. Build id: 20130919-
クラス設計
設計内容とその機能を担当する Java クラス・ソースは以下のとおり。
- 標準入力から変換対象テキストを読み,コマンドライン引数に指定した misima 変換オプションで,
misimaRESTful Web Service に接続し,旧字・旧仮名遣い変換を行い,結果を標準出力に書く。実行メイン。(misimaRESTfulConvert. java) - コマンドライン引数を解析し,エラーチェック並びに,サーバに送信する変換オプションの組み立てを行う。Commons CLI クラスライブラリを使用する。(misimaOptions.
java) - サーバに POST する変換対象テキストを標準入力から読み出して蓄積する。(misimaReader.
java) - 接続先の情報(ホスト,アプリケーションパス,ユーザコード)はプロパティファイルで与えられるようにする。プロパティファイルのない場合はデフォルトの接続先を使用する。(misimaProperties.
java)
Eclipse 開発準備作業
Apache Wink 1.4 と Apache Commons CLI 1.2 を使うので,バイナリパッケージをダウンロードして解凍しておく。
まず,Eclipse 上にプロジェクトを新規作成する。プロジェクト名は misimaRESTfulClient とする。
misimaRESTfulClient が参照する,ビルドに必要な外部ライブラリを追加する。
- wink-client-1.4.jar: Apache Wink Client API
- wink-common-1.4.jar: Apache Wink 共通
- geronimo-jaxrs_1.1_spec-1.0.jar: JAX-RS 標準 API
- slf4j-api-1.6.1.jar: slf4j ロガー API
- slf4j-simple-1.6.1.jar: slf4j 実装
- commons-cli-1.2.jar: Commons CLI コマンドライン解析

図 1. Referenced Libraries
Java プログラム
設計のところで触れた Java クラスのソースを,
misimaRESTfulConvert は RESTful Web Service にアクセスするクライアントの中核クラスである。Apache Wink RestClient インスタンスを生成し,
RestClient client = new RestClient();
Resource resource = client.resource(host + path);
resource.contentType("application/xml");
resource.accept("text/plain");
ClientResponse response = resource.post(pxml);
System.out.print(response.getEntity(String.class));
import org.apache.wink.client.ClientResponse;
import org.apache.wink.client.Resource;
import org.apache.wink.client.RestClient;
/**
* misimaRESTfulConvert.java - misima RESTful Web Service Client
* - コマンドライン引数を解析する
* - 変換対象の UTF-8 テキストを読む
* - 接続先プロパティを取得する
* - POST XML を組み立てる
* - misimaRESTful Web Service に接続して変換結果を取得する
* Copyright(c) 2014, isao yasuda, All Rights Reserved.
*/
public class misimaRESTfulConvert {
/** connect host */
private static String host = "http://yasuda.homeip.net:8080";
/** RESTful application path */
private static String path = "/misimaRest/misima/convert";
/** usercode */
private static String ucod = "noxinsomniae201402";
/** Property file */
private static String prop = ".misimaRESTful-properties";
/** Convert main */
public static void main(String[] args) {
/** コマンドライン引数解析 */
String opts = null;
try {
misimaOptions mopt = new misimaOptions(
"misimaRESTfulConvert", args);
if (mopt.parse()) {
opts = mopt.getmisimaOptions();
} else {
System.exit(-1);
}
}
catch (Exception e) {
System.err.print(e.getMessage());
System.exit(-1);
}
/** 変換対象テキスト取得 */
String target = null;
try {
misimaReader mr = new misimaReader();
target = mr.read();
}
catch (Exception e) {
System.err.println("input file error.");
System.exit(-1);
}
/** プロパティ取得 */
try {
misimaProperties mprop = new misimaProperties(prop);
String hostp = mprop.getValue("host");
if (hostp != null) host = hostp;
String pathp = mprop.getValue("path");
if (pathp != null) path = pathp;
String ucodp = mprop.getValue("ucode");
if (ucodp != null) ucod = ucodp;
}
catch (Exception e) {
System.err.println("Properties not found. Running by default.");
}
/** Building XML for POST */
String pxml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<misimaRESTful>" +
"<misimaParam>" + opts + " -q</misimaParam>" +
"<misimaTarget>" + target + "</misimaTarget>" +
"<misimaUsercode>" + ucod + "</misimaUsercode>" +
"</misimaRESTful>";
/** Connect misimaRESTful Web Service */
try {
RestClient client = new RestClient();
Resource resource = client.resource(host + path);
resource.contentType("application/xml");
resource.accept("text/plain");
ClientResponse response = resource.post(pxml);
System.out.print(response.getEntity(String.class));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
misimaOptions はコマンド引数を解析するクラスである。Apache Commons CLI API を使用している。
import org.apache.commons.cli.*;
/**
* misimaOptions.java - コマンドライン引数を解析する
* Copyright(c) 2014, isao yasuda, All Rights Reserved.
*/
public class misimaOptions
{
/** ユーザ指定引数 */
private String[] cargs = null;
/** 解析済みオプション文字列 */
private String opts = null;
/** オプション */
private Options options = null;
/** Program name */
private String progname = null;
/** Constructor */
public misimaOptions(String progname, String[] args) {
this.progname = progname;
this.cargs = args;
options = new Options();
OptionBuilder.withArgName("c|h|u|a");
OptionBuilder.hasOptionalArg();
OptionBuilder.withDescription("旧字変換 " +
"<c:UTF-8; h:数値参照; u:TeX \\UTF; a:TeX \\CID>");
options.addOption(OptionBuilder.create("s"));
options.addOption("k", false, "旧仮名遣い変換");
options.addOption("y", false, "用語用字変換");
options.addOption("i", false, "繰返し符号変換");
options.addOption("t", false, "単純補正変換");
options.addOption("n", false, "仮名反転変換");
options.addOption("h", false, "ヘルプ");
}
/** 解析 */
public boolean parse() {
CommandLineParser parser = new PosixParser();
StringBuffer margs = new StringBuffer();
try {
CommandLine cl = parser.parse(options, cargs);
// help
if (cl.hasOption("h")) {
showUsage(options);
return false;
}
// misima command line args generate
if (cl.hasOption("s")) {
String sopt = cl.getOptionValue("s");
if (sopt.equals("c") || sopt.equals("h") ||
sopt.equals("u") || sopt.equals("a")) {
} else {
System.err.println("Unrecognized argument: " + sopt);
showUsage(options);
return false;
}
margs.append("-s ");
margs.append(sopt + " ");
}
if (cl.hasOption("k")) margs.append("-k ");
if (cl.hasOption("y")) margs.append("-y ");
if (cl.hasOption("i")) margs.append("-i ");
if (cl.hasOption("t")) margs.append("-t ");
if (cl.hasOption("n")) margs.append("-n ");
opts = margs.toString();
} catch (ParseException e) {
System.err.println(e.getMessage());
showUsage(options);
return false;
}
return true;
}
/** 解析済みオプション取得 */
public String getmisimaOptions() {
return opts;
}
/** Usage message */
private void showUsage(Options options) {
HelpFormatter hf = new HelpFormatter();
hf.printHelp(progname, options, true);
}
}
misimaReader はテキストファイルストリームを入力し文字列変数に蓄積するクラスである。コンストラクタの引数に指定した入力ストリームからデータを読む。引数がない場合は標準入力を読む。misimaRESTful クライアントでは後者のインスタンスを使っている。
import java.io.*;
/**
* misimaReader.java - misima 変換対象テキスト入力
* 変換対象のテキストを UTF-8 として入力し,文字列に格納する
* Copyright(c) 2014, isao yasuda, All Rights Reserved.
*/
public class misimaReader
{
/** リーダ(UTF-8) */
BufferedReader it;
/** 入力文字バッファ */
CharArrayWriter ot;
/** 入力ストリーム */
InputStream is;
/** misimaReader を InputStream 指定で新たに作成する.
* @param inputs InputStream オブジェクト
*/
public misimaReader(InputStream inputs)
{
is = inputs;
}
/** misimaReader を標準入力指定で新たに作成する. */
public misimaReader()
{
is = System.in;
}
/**
* 入力テキストを文字列に格納する.
* @return 変換対象テキスト文字列
*/
public String read() throws IOException {
int c;
String tText = null;
it = new BufferedReader(new InputStreamReader(is, "UTF-8"));
ot = new CharArrayWriter();
while ((c = it.read()) != -1)
ot.write(c);
it.close();
tText = ot.toString();
ot.close();
return tText;
}
}
misimaProperties.
Runnable jar の生成
ビルドがうまく終わったら,runnable jar (実行可能 jar) ファイルを作成する。misimaRESTfulClient から参照するライブラリをすべて含めた実行可能形式で jar ファイルを生成しておけば,実行時のクラスパス設定がラクである。その Eclipse 操作手順は以下のとおり。
- プロジェクトの Properties から,
Run/ Debug Settings を選択する。 - New... ボタン - Java Application を選択し OK をクリックする。すると Edit launch configuration properties 画面が表示される。
- ここで Name:
を適宜指定する。プロジェクト名と同じでよい。 - Main タブで Project:
にプロジェクト名を, Main Class: に misimaRESTfulConvert を指定する。(図 2.) - プロジェクトの Export... から,
Java - Runnable JAR File を選択する。すると Runnable JAR File Specification 画面が表示される。 - Launch configuration:
に対し, Edit launch configuration properties 画面で作成した構成を選択する。 - Export destination:
に出力ファイル名 misimaRESTfulClient. jar を指定する。 - Library handling:
で Extract required libraries into generated JAR (必要なライブラリを展開して jar に格納) を選択する。 - Finish ボタンで jar ファイルが生成される。(図 3.)

図 2. Edit launch configuration properties 画面

図 3. Runnable JAR File Specification 画面
試験
以上でプログラムが出来上がった。試験用のテキストファイル test.
$ cat .misimaRESTful-properties # misimaRESTful Client プロパティファイル # 接続先ホスト host=http://yasuda.homeip.net:8080 # misimaRESTful Web Service パス path=/misimaRest/misima/convert # ユーザコード(暫定試行用) ucode=noxinsomniae201402 $ cat test.txt 森鴎外はこう言い,内田百間を団扇であおいだ。 僕は黙っていますよ。 $ java -jar misimaRESTfulClient.jar -h usage: misimaRESTfulConvert [-h] [-i] [-k] [-n] [-s <c|h|u|a>] [-t] [-y] -h ヘルプ -i 繰返し符号変換 -k 旧仮名遣い変換 -n 仮名反転変換 -s <c|h|u|a> 旧字変換 <c:UTF-8; h:数値参照; u:TeX \UTF; a:TeX \CID> -t 単純補正変換 -y 用語用字変換 $ java -cp misimaRESTfulClient.jar \ misimaRESTfulConvert -kyitn -s c < test.txt 森鷗外ハカウ言ヒ,內田百閒ヲ團扇デアフイダ。 僕ハ默ツテヰマスヨ。 $
企業ネットワークでは普通に設けられているプロキシ環境においても,以下のようにすれば,プロキシを越えて misima RESTful Web Service にアクセスできる。
java -Dhttp.proxyHost=プロキシ・ホスト名 \
-Dhttp.proxyPort=プロキシ・ポート番号 \
-Dhttp.proxyUser=プロキシ・ユーザ名 \
-Dhttp.proxyPassword=プロキシ・パスワード \
-cp misimaRESTfulClient.jar \
misimaRESTfulConvert -kyitq -s c < input.txt
参考文献
[ 2015/02/02 付記 ]
misima RESTful Web Service は 2014/12 より友人のためだけの限定公開といたしました。上記ユーザ認証コードでは動作しません。

