GWTサンプルの分析2

2018年2月9日

ここでは、先のサンプルのEclipse上での実行がどのように行われるかを見ていく。

実行メカニズムの相違~Super Dev Mode

しかし、Eclipse上での実行メカニズムと、最終的な製品としての実行(デプロイされるwarファイル)としての実行メカニズムは全く異なることに注意すする。

GWTのソースからデプロイ用のwarファイルを作成するためには、非常に時間のかかるコンパイルを行わなければならない。Eclipseのような開発環境で、コードを修正するたびに待たされてはたまらないので、EclipseのGWTプラグインでは、Super Dev Modeという開発モードが提供されている。これを使用すると、ほぼストレス無くGWTの開発を行うことができる。

なぜSuperがついているかと言えば、以前にDev Modeというものがあったからだ。二つの違いは以下の通り。

Dev Mode

ブラウザ側(ChromeでもFirefoxでも)に対し、GWT用のプラグインが提供されており、そのプラグインと開発環境がやりとりを行ってJavaScriptをその都度送りこんでいく方式(と思われる)。しかし、これはずいぶん以前に提供が終了され、現在の最新バージョンのブラウザには対応していない。

現在は使用できないのだが、しかしこれにはかなりのメリットがあった。ブラウザ上でのJavaScriptの実行であるにもかかわらず、Eclipseのデバッガが使用できたのである。Eclipse上でブレークポイントを設定すると、ブラウザ上での実行がそこで停止するという芸当ができた。

ただ、後のSuper Dev Modeに比較すると、起動は遅かった。

Super Dev Mode

Dev Modeの開発が停止したのは、仕組み上かなりの無理があったのだろうと推測される(詳細はわからない)。その代わりに出てきたのがSuper Dev Modeというもので、現在はこの仕組みしか使用できない。

これは、ブラウザ側には一切の手を加えず、そのままChromeでもFirefoxでも使用できる。最近のブラウザのデバッグ機構を使用しているようだ。出現した当時はChromeでしか使用できなかったが、現在はFirefoxでも使用できる。未確認だが、他のブラウザでも可能と思われる。

Super Dev Modeでも、ブレークポイントを使うことができるが、しかし、それはブラウザ内で行うことになる。旧Dev ModeのようにEclipse内ではできない。これは、最近のブラウザのソースコードデバッグ機能を使用しているらしい。ブラウザは単にJavaScriptを実行するだけなのだが、Eclipse側から変換前のソースコードが自動で提供され、それを参照しながら実行することができる。

JavaScriptのみを実行するブラウザが、なぜ「変換前のソースコードでのデバッグ」をサポートしているかといえば、おそらくだが、たとえJavaScriptのプログラムであっても、リリース時には難読化されている場合があるがあるからと想像される。この場合にも、元のソースコード(つまりJavaScript)上で実行を追わなければデバッグが難しくなるからだろう。

ということで、サーバコードは普通にJavaプログラムとして実行されるので、そのデバッグはEclipseのデバッガを使用し、クライアント側ではブラウザのデバッグ機能を使うことになる。

下図は、本サンプルプログラムをChromeのデバッガで表示させているところである。特に何もしなくとも、JavaソースコードがChromeに送られて表示されている。

起動パラメータ

さて、このサンプルをEclipse上で動作させるには、以下のメニューを呼び出した。プロジェクトを右クリックしてRun As > GWT Development Mode with Jettyである。

これを行うと、Eclipse上にRun Configurationが作られ、そこに起動パラメータが自動で作成される。

このConfigurationを見てみると、起動パラメータとして以下が設定されている。

-remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -startupUrl Sample.html -logLevel INFO -codeServerPort 9997 -port 8888 -war C:\***\sample\war sample.Sample

パラメータの意味

このパラメータの詳細はCompiling and Debuggingにあるが、ここでは以下を覚えておけばよい。

-startupUrl

最初にブラウザに表示するURLを指定する。この例では、「http://127.0.0.1:8888/Sample.html」だが、パスのみでよい。また、この例では静的なhtmlファイルになっているが、本格的なサーブレットとして動作させる場合はそのパスにもなりうる。

-war

そこからwarリソースを取得するためのトップフォルダ。繰り返しだが、これはデプロイされたwarファイルを動作させているわけではなく、Super Dev Modeで動作させており、本来のwarの中の「コード」は必要無いのだが、しかしwarに入れるべきリソースは必要になる。それをここから取得する。

sample.Sample

対象とするモジュール。このデバッグセッションでデバッグするモジュールが複数の場合は連続して記述する、例えば、

... -war C:\***\sample\war sample.Sample test.Test foo.Bar

など。

開発モードでのキャッシュの制御

この例のような単純なサンプルでは問題が無いのだが、Super Dev Modeという開発モードでは、巨大なプログラムの実行がたびたびおかしくなることがある。
例えば、新たにsharedにクラスを作成し、それをクライアント・サーバ間でやりとりさせようとしても、「そんなクラスは見つからない」と言われてしまうことがある。

この原因は、開発環境の動作スピードを高めようとして、あらゆるものをキャッシュしているかららしい。これがためにストレスなくデバッグができるのだが、逆にコードを変更した場合(特にクライント・サーバの通信部分)には、キャッシュの状態が不整合になってしまうらしい。

※ちなみに、クライアントコードを変更した場合は単にブラウザをリロードすれば良い。それだけで新たなコードをロードしてくれる。しかし、サーバコード変更時は、Eclipse上で実行中のプログラム自体を再起動させなければならない。

ともあれ、いったんそのような状況に陥った場合には、キャッシュの不整合を疑ってみる必要がある。そして、いったんプログラムの実行を停止し、キャッシュを削除してしまった方がよい。

gwt-unitCache

その一つがgwt-unitCacheで、これはEclipseプロジェクトのトップに現れる。一度でも実行した後に、プロジェクトをrefreshしてみれば、以下のフォルダが存在することに気がつくはずだ。

これは(プログラム停止中であれば)いつでも削除してよい。再実行の際にキャッシュ構築のための時間がかかるだけである。

workDir

もう一つがworkDirである。Compiling and Debuggingによれば、これは「コンパイラが内部的に使用するワーク用のディレクトリで、デフォルトはシステムのテンポラリディレクトリ」である。

  • -workDir The compiler’s working directory for internal use (must be writeable; defaults to a system temp dir)

詳細はわからないのだが、おそらくここもキャッシュとして使用されると思われるし、また、この内容は巨大になる可能性があるので、システムのテンポラリディレクトリのままにしておかない方がよい。どこかの場所を決めておき、動作がおかしい場合にgwt-unitCacheと共に削除してしまう、定期的に削除する等の措置をとった方がよい。やり方としては簡単で、起動パラメータとしてこの値を設定してしまうことである。例えば、先の起動パラメータを以下のように変更する。

-workDir c:\gwtWorkDir -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -startupUrl Sample.html -logLevel INFO -codeServerPort 9997 -port 8888 -war C:\***\sample\war sample.Sample