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 より友人のためだけの限定公開といたしました。上記ユーザ認証コードでは動作しません。