![]() ![]() ![]() ![]() Google Web ToolkitでSQL AnywhereのWebサービスを利用するこの記事のURLhttp://japan.internet.com/developer/20070417/26.html
著者:Rob Close
海外internet.com発の記事
はじめにSQL Anywhereはデータベースサーバとして有名ですが、それだけではありません。SQL Anywhereサーバに、データベースクエリの結果セットをWebページまたはWebサービスを介して提供できるHTTPサーバの機能があることはあまり知られていません。Google Web Toolkit(GWT)は、AJAXアプリケーションの作成を簡易化するJavaソフトウェア開発フレームワークです。開発者は、ブラウザ間の違いを意識せずに、使い慣れた環境でおなじみのツールを使ってJavaアプリケーションを作成することができます。GWTには、Javaクラスから各ブラウザ対応のJavaScriptとHTMLを生成するコンパイラが含まれています。 GWTは便利で使いやすく、SQL Anywhereにも対応しています。本稿では、SQL AnywhereのHTTPサーバ機能を利用するためのセットアップ方法と、GWTの使用方法、さらにSQL AnywhereにWebアプリケーションをデプロイする方法を説明します。また、SQL Anywhereサーバへの接続を監視するWebアプリケーションの作成手順も紹介します。SQL Anywhereでのセキュリティやエラー処理についての説明は省きます。 本稿は、SQL AnywhereやGWTの経験がない方でもお読みいただけますが、JavaとSQLの知識があることを前提としています。 ソフトウェアを入手するGWTのWebサイトからGWTをダウンロードしましょう。本稿の執筆時点で入手可能な最新バージョンはビルド1.1.10だったので、今回はこのバージョンを使いました。 SQL Anywhereはバージョン10を使いましたが、バージョン9でもかまいません。バージョン10.0.0ビルド2719以上、または9.0.2ビルド3385以上が必要です。それ以前のバージョンにはGWTの動作を妨げるバグがありました。アップデートはSQL Anywhereのデベロッパーサイトからダウンロードすることができます。EBFのリンクに従ってください。SQL Anywhereをお持ちでない場合は、SQL AnywhereのWebサイトから無料の評価版をダウンロードすることができます。 最後に、SunのJava 2 Runtime Environment 1.4.2以上も必要です。JREはSunのWebサイトからダウンロードすることができます。本稿では最新バージョンのJava 5を使いました。また、Javaソースを編集するためのエディタも必要です。 GWTを使ってアプリケーションを作成する本稿では、DBConsoleの接続部のような外観と振る舞いのWebアプリケーションを作成します。DBConsoleはSQL Anywhereを監視するアプリケーションで、SQL Anywhereに付属しています。 GWTには、シェルアプリケーションを自動的に生成するツールが用意されています。このツールは「applicationCreator」という名前で、インストールしたGWTの最上位のディレクトリに入っています。このディレクトリをパスに追加するか、ツールを実行するときにapplicationCreatorをパスに含める必要があります。まず、プロジェクト用のディレクトリを作成します。ここでは「w:x」を使っているので、この「w:x」を実際に使用するプロジェクトディレクトリに置き換えてください。applicationCreatorを実行するときは、クラスの修飾名を指定する必要があります。パッケージ名の後ろには必ず「.client」を付けます。ここでは、アプリケーションを「com.iAnywhere」というパッケージに入れました。アプリケーションの名前は「Console」です。 アプリケーションの作成 ![]() アプリケーションを作成すると、アプリケーションをビルドしてホストモードで実行するためのスクリプトも作成されます。 アプリケーションをビルドする デフォルトのコンパイルで生成されるJavaScriptは読みにくいので、読みやすくするために「Console-compile.cmd」を編集し、コマンドラインの アプリケーションをビルドするには、コマンドラインで「Console-compile.cmd」を実行します。 アプリケーションをホストモードで実行するホストモードでは、アプリケーションはGWTシェルで実行され、アプリケーションの実行環境となるブラウザが起動されます。ビルドした新規アプリケーションをホストモードで実行するには、コマンドラインで「Console-shell.cmd」を実行します。次の2つのダイアログが表示されます。 GWTシェル ![]() データベースを作成してSQL Anywhereサーバを起動する Webアプリケーションで使うサービスやストアドプロシージャ、またはWebアプリケーションで使用するデータを保管するためには、データベースが必要です。既存のSQL Anywhereデータベースを使うことも、新規にデータベースを作成することもできます。データベースを作成するには、コマンドラインで サーバを起動するには、コマンドラインに次のコードを入力します。 dbsrv10 -xs HTTP(port=80) console.db これで、データベースサーバが起動します。データベースアプリケーションがデータベースに接続するには、正しい認証情報を持っていることが必要です。これは、SQL Anywhereサーバの管理下にあるその他のデータベースに接続する場合も同様です。.xsオプションを指定すると、SQL AnywhereはWebプロトコルをリスンします。ここでは、ポート80のHTTP要求が対象となります。 SQL Anywhereは、特定の要求に応答するために作成されたWebサービスを必要とします。例えば、fooというWebサービスを作成した場合は、次のURLを指定してこのWebサービスにアクセスします。 HTTP://localhost/foo ただし、ページの生成中はうまくいきません。GWTは多くのファイルを生成します。こうしたファイルの中には、「Console-compile.cmd」でプロジェクトをリビルドするたびに名前が変わるものもあります。SQL Anywhereのデフォルトでは、要求されるファイルごとに異なるサービスを用意することが期待されますが、この問題には回避策があります。「root」というWebサービスを作成するのです。このrootサービスは、一致するサービスがないすべての要求を処理します。 rootサービスのソースは次のとおりです。 CREATE SERVICE "root" TYPE ’RAW’ AUTHORIZATION OFF USER "DBA" URL ON AS call RootPage(:url); このサービスは非常に単純です。認証を無効にし、すべての呼び出しにDBA権限を使います。さらに、呼び出しているURLを取得してRootPageストアドプロシージャに渡します。RootPageは要求をディスパッチする処理を行います。 RootPageは、GWTの出力生成先ディレクトリをURLの前に付加し、そのURLを使用してファイルを読み取り、要求側に返します。RootPageは各ファイルのファイル拡張子を認識し、適切なコンテンツタイプを設定します。ここでは「w:xwww」を使いました。「www」ディレクトリは、Console-compileが生成ファイルをデフォルトで書き込む場所です。このディレクトリは、実際にプロジェクトをビルドする場所に置き換えてください。 CREATE PROCEDURE "DBA"."RootPage"( url_part varchar(250) ) RESULT( HTML_doc XML ) BEGIN declare root_page long varchar; set root_page = xp_read_file( ’w:xwww’ + HTTP_decode( url_part ) ); IF COMPARE( ’.html’, LOWER( RIGHT( url_part, 5 ) ) ) = 0 OR COMPARE( ’.htm’, LOWER( RIGHT( url_part, 4 ) ) ) = 0 THEN CALL dbo.sa_set_http_header( ’Content-Type’, ’text/HTML’ ); ELSEIF COMPARE( ’.js’, LOWER( RIGHT( url_part, 3 ) ) ) = 0 THEN CALL dbo.sa_set_http_header( ’Content-Type’, ’text/javascript’ ); ELSEIF COMPARE( ’.css’, LOWER( RIGHT( url_part, 4 ) ) ) = 0 THEN CALL dbo.sa_set_http_header( ’Content-Type’, ’text/css’ ); ELSEIF COMPARE( ’.xml’, LOWER( RIGHT( url_part, 4 ) ) ) = 0 THEN CALL dbo.sa_set_http_header( ’Content-Type’, ’text/xml’ ); ELSEIF COMPARE( ’.gif’, LOWER( RIGHT( url_part, 4 ) ) ) = 0 THEN CALL dbo.sa_set_http_header( ’Content-Type’, ’image/gif’ ); ELSEIF COMPARE( ’.jpe’, LOWER( RIGHT( url_part, 4 ) ) ) = 0 OR COMPARE( ’.jpeg’, LOWER( RIGHT( url_part, 5 ) ) ) = 0 OR COMPARE( ’.jpg’, LOWER( RIGHT( url_part, 4 ) ) ) = 0 THEN CALL dbo.sa_set_http_header( ’Content-Type’, ’image/jpeg’ ); END IF; select "root_page"; END; Webサービスとストアドプロシージャの作成および維持にはDBISQLまたはSybase Centralを使用できます。DBISQLとSybase CentralはSQL Anywhereに付属のツールです。今回の例では、Sybase Centralの方が効率的であることが分かりました。 Windowsでは、DBISQLとSybase Centralは[スタート]メニューから起動できます。起動したら、作成した新規データベースに接続する必要があります。新規データベースのデフォルトのユーザーIDは「dba」で、デフォルトのパスワードは「sql」です。他に既に使用しているSQL Anywhereデータベースがある場合は、そのデータベースの名前も指定する必要があります。ここでは、「console」を使います。 WebアプリケーションをデプロイするこれでSQL AnywhereがWebサーバとして設定されました。このサーバはGWTがアプリケーションを生成するディレクトリを監視しているので、プロジェクトがコンパイルされるたびにアプリケーションがデプロイされます。アプリケーションを変更したのにブラウザで実行したときにその変更が反映されていない場合は、「www」ディレクトリの中味を削除してからアプリケーションを再度ビルドします。GWTでは、既存のファイルを上書きしないように配慮されています。 これをテストするには、アプリケーションをコンパイルした後、お気に入りのWebブラウザに移動して、生成したWebページのURLを入力します。 HTTP://localhost/com.iAnywhere.Console/Console.html これで、SQL Anywhereで管理できる作業アプリケーションが完成しました。 コンソールアプリケーションを作成する次に、SQL Anywhereに付属しているDBConsoleアプリケーションの接続ビューア部分と同じ働きをするブラウザベースのアプリケーションを作成してみます。 DBConsoleの接続ビューアでは、ユーザーはデータベース接続プロパティのリストから表示するものを選択し、データ更新のリフレッシュレートを設定し、その情報を表示することができます。DBConsoleはオプションダイアログを使って構成します。 同じことを行うためには、Webサービスとストアドプロシージャを設定し、表示する接続データを集める必要があります。また、接続プロパティのリストを作るためにもWebサービスとストアドプロシージャが必要です。さらに、サーバからの結果を表示するためにGWTプロジェクトを更新することも必要です。 まず、「Console.html」を編集します。編集するのは、デプロイ先のディレクトリ(デフォルトでは「www」)内のファイルではなく、「src」ディレクトリ内のファイルです。こうしないと、最初からすべてビルドし直したときに正しいHTMLファイルを取得することができません。新規アプリケーションのユーザーインターフェイスに必要なのは、GWTが自動的に生成するJavaScriptだけです。HTML要素は必要ありません。「Console.html」から次の要素を削除します。 GWTによってタイトルは自動的に「Wrapper HTML for Console」になりました。このタイトルを「Console」に変更します。GWTのグラフィカルコンポーネント(ボタンやメニューなど)は、スタイルシートを使ってカスタマイズできます。これらのコンポーネントの多くは、スタイルシートでカスタマイズしないと非常に地味です。GWTの資料には、各コンポーネントのスタイルシートプロパティのリストが含まれています。スタイルシートは非常に長いので、ここでは省略します。詳しい内容については、「Console.html」を参照してください。 どの接続プロパティをリストに表示したいと思うかは、ユーザーによって異なります。まず、ユーザーが表示データをカスタマイズできるように、接続プロパティのリストを取得する必要があります。 そのためのサービスを作成します。 CREATE SERVICE "get_connection_properties" TYPE ’XML’ AUTHORIZATION OFF USER "DBA" AS call getConnectionPropeties(); 次にストアドプロシージャを作成します。 CREATE PROCEDURE "DBA"."getConnectionPropeties"() RESULT ( property_name long varchar, property_description long varchar, property_is_numeric long varchar, property_is_cumulative long varchar ) begin select property_name( row_num ) as prop, property_description( row_num ), property_is_numeric( row_num ), property_is_cumulative( row_num ) from sa_rowgenerator(0,500) where connection_property( prop ) is not null order by prop end このリストをブラウザに表示するには、GWTが生成した 次に、接続プロパティのリストを作るための接続データを取得します。そのために、接続データを取得するためのサービスを作成します。 CREATE SERVICE "connections" TYPE ’RAW’ AUTHORIZATION OFF USER "DBA" AS call connections(:properties); ストアドプロシージャを作成します。 CREATE PROCEDURE "DBA"."connections"( IN properties LONG VARCHAR ) BEGIN DECLARE pos INT; DECLARE start_pos INT; DECLARE property LONG VARCHAR; DECLARE temp_table LONG VARCHAR; DECLARE insert_into LONG VARCHAR; DECLARE counter INT; DECLARE curr_cid INT; DECLARE cid INT; DECLARE return_value LONG VARCHAR; DECLARE table_heading LONG VARCHAR; DECLARE insert_html long varchar; DECLARE cols LONG VARCHAR; declare local temporary table t_html( ord INT, str LONG VARCHAR ) in SYSTEM not transactional; SET temp_table = ’declare local temporary table t_conn_webconsole(’; SET insert_into = ’insert into t_conn_webconsole values (’; SET table_heading = ’<TR class="header">’; SET cols = ’’; SET insert_html = ’INSERT INTO t_html SELECT 1, ’’<TR>’’ ||’; SET pos = 1; SET start_pos = 0; SET counter = 0; WHILE pos > 0 LOOP SET pos = LOCATE( properties, ’,’, start_pos ); IF pos = 0 THEN SET property = SUBSTR( properties, start_pos, LENGTH( properties ) - start_pos ); ELSE SET property = SUBSTR( properties, start_pos, pos - start_pos ); END IF; IF counter > 0 THEN SET temp_table = temp_table || ’, ’; SET insert_into = insert_into || ’, ’; SET cols = cols || ’ || ’; SET insert_html = insert_html || ’ || ’; END IF; SET temp_table = temp_table || ’ "’ || property || ’" varchar(255)’; SET cols = cols || ’ "’ || property || ’"’; SET insert_into = insert_into || ’ connection_property( ’’’ || property || ’’’ , cid )’; SET table_heading = table_heading || ’<TH>’ || property_description( property ) || ’</TH>’; SET insert_html = insert_html || ’’’<TD>’’ ||"’ || property || ’" || ’’</TD>’’’; SET start_pos = pos + 1; SET counter = counter + 1; END LOOP; SET temp_table = temp_table || ’ ) in SYSTEM not transactional;’; SET insert_into = insert_into || ’);’; SET table_heading = table_heading || ’</TR>’; SET insert_html = insert_html || ’ || ’’</TR>’ ’ FROM t_conn_webconsole’; EXECUTE IMMEDIATE temp_table; set curr_cid = connection_property( ’number’ ); set cid = next_connection( NULL, NULL ); loop_label: loop if cid is NULL then leave loop_label end if; if cid <> curr_cid then EXECUTE IMMEDIATE insert_into; end if; set cid = next_connection( cid, NULL ); end loop loop_label; INSERT INTO t_html VALUES ( 0, ’<HTML><BODY><TABLE BORDER=1 CELLSPACING=1 CELLPADDING=0 COLS=’ || counter || ’>’ || table_heading ); EXECUTE IMMEDIATE insert_html; INSERT INTO t_html VALUES ( 99999, ’</TABLE></BODY></HTML>’ ); SELECT str FROM t_html ORDER BY ord; END このアプリケーションでは定期的にデータを更新します。データの収集の管理にはタイマーを使います。アプリケーションがブラウザのドキュメントにロードされたときにタイマーを始動し、アンロードされたときにタイマーを停止します。今回使用したコードを次に示します。 public void onLoad() { _timer = new Timer() { public void run() { boolean success = HTTPRequest.asyncGet( _hostName + "connections?properties="+_connectionProperties, new ResponseTextHandler() { public void onCompletion( String responseText ) { _content.setHTML( responseText ); } }); if( !success ) { _timer.cancel(); // Report problem to user. Window.alert( "Error getting connection data." ); } } }; _timer.scheduleRepeating( _refreshRate ); } public void onDetach() { _timer.cancel(); } Webアプリケーションを起動するたびに、表示するプロパティのリストをユーザーが設定し直すのでは不便です。クッキーを使用すれば、この設定を保存することができます。GWTには、クッキーの値を設定および取得するための静的なメソッドを含む 完成したWebアプリケーションは次のようになります。 複数のブラウザをターゲットとするJavaScriptアプリケーションを作成した経験がある人ならば、すべてのブラウザで同じ動作を期待どおりに実現するのが大変であることはよくご存知でしょう。この問題を解決するために、GWTは複数の代表的なブラウザ用のスクリプトを生成します。生成されたコードは、ロード時にブラウザに合ったスクリプトを読み込みます。このGWTの素晴らしい働きのおかげで、Javaプログラマは複数のブラウザ用のWebアプリケーションを簡単にデプロイできるようになりました。 手順さえ理解すれば、GWTをSQL Anywhereで利用するのは難しいことではありません。このサンプルアプリケーションは未完成ですが、アプリケーションを作成する際の出発点としては役に立つでしょう。 参考資料著者紹介Rob Close(Rob Close)
SQL Anywhereエンジニアリングチームのシニア開発者。SQL Anywhere向け管理ツールを担当するチームのJavaリーダー的存在。SQL Anywhereの次期バージョンや技術記事の投稿に関わっていないときは、カナダ、オンタリオ州南部で養蜂の仕事をしている。
|