GroovyServ - Technical Part
-
Upload
yasuharu-nakano -
Category
Technology
-
view
2.081 -
download
0
Transcript of GroovyServ - Technical Part
![Page 1: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/1.jpg)
高速起動Groovy
Side-B: Technical Part
![Page 2: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/2.jpg)
目次基本編全体のクラス構成や、基本的な処理の流れのようなもの
がんばりどころ思ったほど単純じゃないのですね
ビルドこうやってビルドしてます
ぷちハック別マシン上のgroovyserverプロセスをつついてみよう
![Page 3: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/3.jpg)
期待される効能実装面に色々やってるのを見て「へぇ~」と思う
自分でソースからビルドできるようになる
バグ対処も自分でできるようになる
報告&パッチください
ハック!ハック!ハック!
![Page 4: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/4.jpg)
基本編
![Page 5: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/5.jpg)
全体のクラス図based on: Ver 0.4-SNAPSHOT(7/24)
![Page 6: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/6.jpg)
![Page 7: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/7.jpg)
!"#$%&'()*スクリプト実行までの流れ
based on: Ver 0.4-SNAPSHOT(7/24)
高速学習GroovyServ
高速学習GroovyServ
![Page 8: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/8.jpg)
$ groovyserver
![Page 9: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/9.jpg)
GroovyServerのmain()が起動される
![Page 10: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/10.jpg)
ServerSocketを作ってListenループ開始(デフォルトでは1961番ポート)
![Page 11: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/11.jpg)
$ groovyclient -e “println(‘Hello, GroovyServ!’)”
groovyclient
groovyserver1961(default)
![Page 12: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/12.jpg)
RequestWorkerを生成して、start()する
![Page 13: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/13.jpg)
ClientConnection#openSession()を呼び出して、リクエストのヘッダ情報をパースした、InvocationRequestを取得する
![Page 14: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/14.jpg)
groovyclientからのGroovyスクリプトを実行するためのスレッドを起動する
![Page 15: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/15.jpg)
Groovyスクリプトを実行する
![Page 16: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/16.jpg)
+,-./012345
67389:3467;5
<=6#+,4
スクリプト実行までの流れbased on: Ver 0.4-SNAPSHOT(7/24)
高速学習GroovyServ
高速学習GroovyServ
![Page 17: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/17.jpg)
$ groovyserver
![Page 18: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/18.jpg)
GroovyServerのmain()が起動される
![Page 19: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/19.jpg)
System.in/out/errの標準入出力を自前のクラスに差し替える!リクエストごとに独立したソケットとの接続性を実現するため。後述。
![Page 20: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/20.jpg)
ユーザ認証用のクッキーを生成して、~/.groovy/groovyserv/cookie に保存しておく
![Page 21: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/21.jpg)
ServerSocketを作ってListenループ開始(デフォルトでは1961番ポート)
![Page 22: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/22.jpg)
$ groovyclient -e “println(‘Hello, GroovyServ!’)”
groovyclient
groovyserver1961(default)
./groovy/groovyserv/cookie内に出力されているトークンがリクエストヘッダのCookieに設定される
Cookie: 425ba835cb32688b1
![Page 23: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/23.jpg)
クライアントSocketがLoopback Addressのものであれば、RequestWorkerを生成する
![Page 24: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/24.jpg)
RequestWorkerのコンストラクタで、クライアントごとのソケットやストリー
ム周りの色々をとりまとめたClientConnectionを生成する
CientConnectionのコンストラクタの最後で、自分自身をThreadGroupをキーにSingletonなリポジトリに登録する
![Page 25: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/25.jpg)
RequestWorkerをstart()する
![Page 26: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/26.jpg)
このとき、リクエストのヘッダ情報としてクライアントから渡されたクッキーのトークンが、サーバ側で持っているCookieと一致するかどうかチェックする
ClientConnection#openSession()を呼び出して、リクエストのヘッダ情報をパースした、InvocationRequestを取得する
![Page 27: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/27.jpg)
groovyclient上の標準入力をソケット経由でサーバ側で受け取ってSystem.inに転送し続けるスレッドを起動する
![Page 28: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/28.jpg)
groovyclientからのGroovyスクリプトを実行するためのスレッドを起動する
![Page 29: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/29.jpg)
groovyclientが実行されたカレントディレクトリ(CWD)を以下のようにJVMに反映する1. システムプロパティ“user.dir”にセット2. JNAを利用してJVMプロセス自体のCWDを変更3. CWDをクラスパスに追加
![Page 30: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/30.jpg)
GroovyMainという本家のクラスをちょっとだけ変更したGroovyMain2を使って、Groovyスクリプトを実行する
![Page 31: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/31.jpg)
がんばりどころ
>?@A4BCDE3:2
![Page 32: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/32.jpg)
クライアント-サーバ間通信の実態
見知らぬ人からのリクエストは処理しない
クラスパスの扱い
カレントディレクトリ(CWD)の扱い
クライアントから透過的にサーバを起動
クライアント側でCTRL+Cをするとサーバ処理が中断
スレッド/コネクション管理
![Page 33: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/33.jpg)
クライアント-サーバ間通信の実態
見知らぬ人からのリクエストは処理しない
クラスパスの扱い
カレントディレクトリ(CWD)の扱い
クライアントから透過的にサーバを起動
クライアント側でCTRL+Cをするとサーバ処理が中断
スレッド/コネクション管理
![Page 34: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/34.jpg)
クライアント-サーバ間通信の実態
スクリプトがSystem.out(err)を使って、標準出力をクライアントに送る
スクリプトがSystem.inを使って、クライアントからの標準入力を取得する
HTTPにちょっとだけ似た感じのオレオレ通信プロトコルを利用
![Page 35: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/35.jpg)
groovyclientClientConnectionRepository
現在のThreadGroupに対するClientConnectionを返す
ClientConnection
OutputStream
!script"
println “Hello, GroovyServ!”
System.out
(StreamResponse
OutputStream)
プロトコルに基づいて変換したデータをSocketの
OutputStream#write()
に書き出す
スクリプトがSystem.out(err)
を使って、標準出力をクライアントに送るの図
Hello, GroovyServ!
if Channelヘッダ==”err”" 標準エラー出力へ!
if Channelヘッダ==”out”" 標準出力へ!
![Page 36: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/36.jpg)
ClientConnectionRepository
現在のThreadGroupに対するClientConnectionを返す
ClientConnection
PipedOutputStream
PipedInputStream
groovyclient StreamRequestHandler
!script"
System.in.eachLine { ... }
接続されたパイプ
Socket.inputStream.read()して、プロトコルに基づいてパースしたボディ部をpipedOutputStream.write()に書き出す
System.in
(StreamRequestInputStream)ClientConnection内の
PipedInputStreamに処理を委譲
スクリプトがSystem.inを使って、クライアントからの標準入力
を取得するの図
![Page 37: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/37.jpg)
なんでこんな面倒なことしてるの?[要請] クライアントからの切断要求(Size:-1)に随時反応させたい
[案A] StreamRequestInputStreamから、直接Socket#getInputStream()にディスパッチする方式
System.inアクセス時にはじめてクライアントからの入力が評価される
余計なパイプが挟まらないのでシンプル
[案B] StreamRequestInputStreamからPipedInputStream()にディスパッチする。パイプには別スレッドを使って逐次クライアントからの入力をコピーする
常にクライアント入力を監視できるため、切断要求に即時応答できる
(Piped~)
![Page 38: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/38.jpg)
Request
InvocationRequest
初回にクライアントから送られるGroovyスクリプト自体を含む実行リクエスト
StreamRequest
クライアントへの標準入力を、サーバに送信するための、ストリーム型リクエスト
Response
StreamResponse
サーバ上のスクリプト実行結果としての標準出力と標準エラー出力を、クライアントに送信するための、ストリーム型レスポンス
オレオレ通信プロトコル
![Page 39: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/39.jpg)
InvocationRequest'Cwd:' <cwd> LF
'Arg:' <argn> LF
'Arg:' <arg1> LF
'Arg:' <arg2> LF
'Cp:' <classpath> LF
'Cookie:' <cookie> LF
LF
where:
<cwd> is current working directory.
<arg1><arg2>.. are commandline arguments(optional).
<classpath>.. is the value of environment variable
CLASSPATH(optional).
<cookie> is authentication value which certify client is
the user who invoked the server.
LF is line feed (0x0a, '\n').
![Page 40: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/40.jpg)
StreamRequest
'Size:' <size> LF
LF
<data from STDIN>
where:
<size> is the size of data to send to server. <size>==-1
means client exited.
<data from STDIN> is byte sequence from standard input.
![Page 41: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/41.jpg)
StreamResponse
'Status:' <status> LF
'Channel:' <id> LF
'Size:' <size> LF
LF
<data for STDERR/STDOUT>
where:
<status> is exit status of invoked groovy script.
<id> is 'out' or 'err', where 'out' means standard output
of the program. 'err' means standard error of the program.
<size> is the size of chunk.
<data from STDERR/STDOUT> is byte sequence from standard
output/error.
![Page 42: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/42.jpg)
クライアント-サーバ間通信の実態
見知らぬ人からのリクエストは処理しない
クラスパスの扱い
カレントディレクトリ(CWD)の扱い
クライアントから透過的にサーバを起動
クライアント側でCTRL+Cをするとサーバ処理が中断
スレッド/コネクション管理
![Page 43: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/43.jpg)
Cookie / Loopback onlyセキュリティ対策のために以下の2つの機構が導入されている
Only from Loopback address
「見知らぬ別のマシンからつついちゃだめ」単純に、InetAddress#isLoopbackAddress()で判定
Cookie
「Loopback address経由でも、起動したサーバと同じかそれ以上のアクセス権限がないユーザからのリクエストはNG」HTTPのCookieとは全く関係ないサーバ起動時にランダム文字列をクッキーとして、~/.groovy/groovyserv/cookieに保存クライアントからのリクエストごとに、ファイルから読み取ったクッキーをCookieヘッダに付けて送りつけるサーバ側でリクエストパース時にクッキートークンが一致しなければ、Authentication failed
![Page 44: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/44.jpg)
クライアント-サーバ間通信の実態
見知らぬ人からのリクエストは処理しない
クラスパスの扱い
カレントディレクトリ(CWD)の扱い
クライアントから透過的にサーバを起動
クライアント側でCTRL+Cをするとサーバ処理が中断
スレッド/コネクション管理
![Page 45: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/45.jpg)
クライアントでCLASSPATH環境変数が指定されている場合
InvocationRequestのCpヘッダにそのままの文字列を設定してサーバに送信する
GroovyMain2に渡す前に、システムプロパティ“groovy.classpath”に設定しておくと、後はGroovyMain2で良きに計らってくれる
ただし、現状の実装では、他のリクエストや実行中スレッドがあるかもしれない中、安全にgroovy.classpathから使い終わったクラスパスを取り除くことができないため、追加されていく一方になる。
後始末するにはサーバを再起動するしかない(groovyserver -r、等)
クライアントで-cpオプションが指定された場合
InvocationRequestのArgヘッダ、つまり、コマンドライン引数の一部としてそのままサーバに送信する
そのままGroovyMain2にコマンドライン引数として渡すと、良きに計らってくれる
CLASSPATH
![Page 46: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/46.jpg)
クライアント-サーバ間通信の実態
見知らぬ人からのリクエストは処理しない
クラスパスの扱い
カレントディレクトリ(CWD)の扱い
クライアントから透過的にサーバを起動
クライアント側でCTRL+Cをするとサーバ処理が中断
スレッド/コネクション管理
![Page 47: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/47.jpg)
カレントディレクトリという概念が裏側に隠蔽されているJavaですが、きちんと対処しないと困る場面があります
GroovyServでは、サーバ起動時のCWDと、クライアント実行時のCWDが異なるため、何も対処をしないと・・・
CWD(Current Working Directory)
$ cd /tmp
$ groovyserver -r
$ cd /home/kobo
$ cat > hoge.txt
HOGE!!
^C
$ groovyclient -e ‘println(new File(“hoge.txt”).text)’
Caught: java.io.FileNotFoundException: hoge.txt (No such file or directory)
...SNIP...
![Page 48: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/48.jpg)
よって、以下の対処が必要
システムプロパティ“user.dir”にセット
File#getAbsolutePath()に影響する
“"user.dir", which is initialized during jvm
startup, should be used as an informative/readonly
system property”(posted 2008-08-18)・・・だと・・・?!http://bugs.sun.com/bugdatabase/view_bug.do;:YfiG?bug_id=4117557
JNAを利用してJVMプロセス自体のCWDを変更
“user.dir”による絶対パス補完がなぜか漏れているFileInputStreamを含む多数のクラスのため
あと、CWDをクラスパスに追加しておく
Groovyでは、実行されたスクリプトと同じディレクトリにあるスクリプトは、クラスパスに入ってるものとして扱われるため
![Page 49: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/49.jpg)
import com.sun.jna.Library
import com.sun.jna.Native
import com.sun.jna.Platform
interface CLibrary extends Library {
String libname = (Platform.isWindows() ? "msvcrt" : "c")
CLibrary INSTANCE = Native.loadLibrary(libname, CLibrary.class)
int chdir(String dir)
int _chdir(String dir)
}
と、依存ライブラリを追加しておいて#でOK!便利!
<dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>3.2.2</version> </dependency>
JNAでcwdを変更するには、POMファイルで
![Page 50: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/50.jpg)
クライアント-サーバ間通信の実態
見知らぬ人からのリクエストは処理しない
クラスパスの扱い
カレントディレクトリ(CWD)の扱い
クライアントから透過的にサーバを起動
クライアント側でCTRL+Cをするとサーバ処理が中断
スレッド/コネクション管理
![Page 51: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/51.jpg)
「ポートをつついてサーバが生きてないなら、単純にgroovyserverシェルスクリプトを実行してるだけ」「え?」「え?」
Windowsの場合はgroovyserver.bat
PIDが簡単に扱えるLinux/MacOSXの場合は、PIDファイルを使って多重起動防止とかしてます。killも再起動もできます。
Windowsの場合は、起動してみて多重だったらAddress already in useエラーで落ちます
BATでPIDを使ってプロセス制御する方法知ってたら教えてください
透過的なサーバ起動
![Page 52: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/52.jpg)
クライアント-サーバ間通信の実態
見知らぬ人からのリクエストは処理しない
クラスパスの扱い
カレントディレクトリ(CWD)の扱い
クライアントから透過的にサーバを起動
クライアント側でCTRL+Cをするとサーバ処理が中断
スレッド/コネクション管理
![Page 53: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/53.jpg)
groovyclientで、サーバからのレスポンスを待っているときにCTRL+Cを実行すると・・・
“Size: -1”というヘッダを含むリクエストが飛ぶ
サーバ側のStreamRequestHandlerスレッドでこのリクエストを見つけると、サーバ側の処理を中断する
それほど大した話でもないですね
CTRL+C対応
![Page 54: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/54.jpg)
クライアント-サーバ間通信の実態
見知らぬ人からのリクエストは処理しない
クラスパスの扱い
カレントディレクトリ(CWD)の扱い
クライアントから透過的にサーバを起動
クライアント側でCTRL+Cをするとサーバ処理が中断
スレッド/コネクション管理
![Page 55: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/55.jpg)
正直まだまだ実装があまいですjava.util.concurrentパッケージを利用リクエストごとに2つの必須スレッドソケット越しの標準入力の監視・転送を行うスレッド(StreamRequestHandler)Groovyスクリプトを実行するスレッド(GroovyInvokeHandler)スクリプト内部で、スレッドが生成されるユースケースも対応しないといけない
スレッド/コネクション管理
![Page 56: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/56.jpg)
コネクションがクローズされた場合クライアント側からサーバ側からNWトラブルで
Groovyスクリプトの実行が終わったらサブスレッドがない場合サブスレッドがまだ生きている場合
クライアント側でCTRL+Cされて中断されたら・・・・・・どの場合にどの順序で何を後始末していくのか、スレッドをどうやって待ち受けるか、色々ややこしくて、まだナイスな状態になってない鋭意検討&実装中!!!
![Page 57: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/57.jpg)
書かなかったけど、がんばったその他のこと
System.exit()の取り扱い
スクリプトで実行されてもJVMを落とさないよ!
![Page 58: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/58.jpg)
ビルド
![Page 59: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/59.jpg)
Maven + GMaven
Maven + GMaven
GMavenはドキュメントが全然メンテナンスされてない。正直微妙
今ならGradleの方がよさげ(本家もGradleに移行中)
0.4-SNAPSHOTからgroovyファイルはコンパイルせずにそのまま実行ファイルとして提供するようにした
groovycでコンパイルすると、何故かJDKのAPIのprivateなコンストラクタの数の違いによって、IncompatibleClassChange
Errorが出たりしたので
![Page 60: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/60.jpg)
IntegrationTestメインでGroovyServは、クライアントとサーバ間の相互作用が一番のポイント
なので、ビルドで生成されたgroovyclient実行ファイルをそのまま使って、結合/システムテスト的なテストをメインに実行している
maven-failsafe-pluginというプラグインを使うと“mvn integration-test”で結合テストが実行できるようになる
詳しくは http://maven.apache.org/plugins/maven-failsafe-plugin/index.html
現状ではときどきスレッド系のテストでmvnが固まってしまう
サブスレッドが絡んだときの終了処理でバグがあるためと思われる
対応策を検討中
![Page 61: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/61.jpg)
How to Build
Maven2でビルド $ cd groovyserv-<Version>
$ mvn clean verify
バイナリパッケージ: target/groovyserv-<Version>-<OS>-<arch>-bin.zip
Integration-Test用の環境(パスを通せば実行することも可能。試行錯誤時に便利) target/groovyserv-<Version>-<OS>-<arch>.dir/groovyserv-<Version>-<OS>-<arch>
テストで失敗する場合:
EncodeITがエラーになるなど、文字化け系が怪しければ、文字エンコードをUTF-8に設定する $ export _JAVA_OPTIONS=-Dfile.encoding=UTF-8
テスト環境だけの問題であればすべてのテストをスキップする方法もある $ mvn -Dmaven.test.skip=true clean package
Windows上でビルドするためにはCygwinとgccが必要
![Page 62: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/62.jpg)
ぷちハック>?:')DFFFF
![Page 63: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/63.jpg)
Remote GroovyServ
セキュリティ対策のために導入されている以下をあえてOFFにしてみます
Only Loopback adress
Cookie
ただし、ハック版サーバを実行したまま放置した場合の被害等については責任を負いかねます
![Page 64: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/64.jpg)
修正ポイントは3カ所groovyserver
Loopback AddressチェックをコメントアウトCookieチェックをコメントアウト
grovyclient
接続先ホストを“localhost”=>接続したいサーバに変更する
サーバ用マシンAでビルドするgroovyserverを起動する
クライアント用マシンBにソース一式をおくるgroovyclientを実行してみると・・・・・
![Page 65: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/65.jpg)
まとめ
![Page 66: GroovyServ - Technical Part](https://reader035.fdocuments.us/reader035/viewer/2022062513/554f8646b4c905d25b8b4cc7/html5/thumbnails/66.jpg)
とまあ、GroovyServの中身はこんな感じです正直、完成度の低い部分はまだまだ残ってます自分のユースケースの範囲だと検出できない問題も多いので、是非みなさん使ってください!!ソースはGitHubで公開してます。clone/forkはご自由に!バグのパッチは大歓迎新機能や改善提案は採用できるかは別として、基本的にWelcomeです
GroovyServトップページhttp://kobo.github.com/groovyserv
GitHub
http://github.com/kobo/groovyserv