Gwt-rpc-communication
GWT-RPC通信
GWTベースのアプリケーションは通常、クライアント側モジュールとサーバー側モジュールで構成されます。 クライアント側のコードはブラウザーで実行され、サーバー側のコードはWebサーバーで実行されます。 クライアント側のコードは、サーバー側のデータにアクセスするために、ネットワークを介してHTTP要求を作成する必要があります。
RPC、リモートプロシージャコールは、クライアントコードがサーバー側のメソッドを直接実行できるGWTで使用されるメカニズムです。
- GWT RPCはサーブレットベースです。
- GWT RPCは非同期であり、通信中にクライアントがブロックされることはありません。
- GWT RPC Javaオブジェクトを使用すると、クライアントとサーバー間で直接送信できます(GWTフレームワークによって自動的にシリアル化されます)。
- サーバー側サーブレットは service と呼ばれます。
- クライアント側コードからサーバー側サーブレットのメソッドを呼び出すリモートプロシージャコールは、*サービスの呼び出し*と呼ばれます。
GWT RPCコンポーネント
以下は、GWT RPC通信メカニズムで使用される3つのコンポーネントです。
- サーバーで実行されるリモートサービス(サーバー側サーブレット)。
- そのサービスを呼び出すクライアントコード。
- クライアントとサーバー間で渡されるJavaデータオブジェクト。
GWTクライアントとサーバーは、データを自動的にシリアル化および逆シリアル化するため、開発者はオブジェクトをシリアル化/逆シリアル化する必要がなく、データオブジェクトはHTTPを介して移動できます。
次の図は、RPCアーキテクチャを示しています。
RPCの使用を開始するには、GWTの規則に従う必要があります。
RPC通信ワークフロー
手順1-シリアル化可能なモデルクラスを作成する
クライアント側で、直列化可能なJavaモデルオブジェクトを定義します。
public class Message implements Serializable {
...
private String message;
public Message(){};
public void setMessage(String message) {
this.message = message;
}
...
}
ステップ2-サービスインターフェイスの作成
すべてのサービスメソッドをリストするRemoteServiceを拡張するクライアント側のサービスのインターフェイスを定義します。
アノテーション@RemoteServiceRelativePathを使用して、サービスをモジュールベースURLに関連するリモートサーブレットのデフォルトパスにマップします。
@RemoteServiceRelativePath("message")
public interface MessageService extends RemoteService {
Message getMessage(String input);
}
手順3-非同期サービスインターフェイスを作成する
GWTクライアントコードで使用されるクライアント側(上記のサービスと同じ場所)でサービスする非同期インターフェイスを定義します。
public interface MessageServiceAsync {
void getMessage(String input, AsyncCallback<Message> callback);
}
ステップ4-サービス実装サーブレットクラスを作成する
サーバー側でインターフェースを実装すると、そのクラスはRemoteServiceServletクラスを拡張する必要があります。
public class MessageServiceImpl extends RemoteServiceServlet
implements MessageService{
...
public Message getMessage(String input) {
String messageString = "Hello " + input + "!";
Message message = new Message();
message.setMessage(messageString);
return message;
}
}
手順5-Web.xmlを更新してサーブレット宣言を含める
Webアプリケーションデプロイメント記述子(web.xml)を編集して、MessageServiceImplサーブレット宣言を含めます。
<web-app>
...
<servlet>
<servlet-name>messageServiceImpl</servlet-name>
<servlet-class>com.finddevguides.server.MessageServiceImpl
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>messageServiceImpl</servlet-name>
<url-pattern>/helloworld/message</url-pattern>
</servlet-mapping>
</web-app>
手順6-アプリケーションコードでリモートプロシージャコールを行う
サービスプロキシクラスを作成します。
MessageServiceAsync messageService = GWT.create(MessageService.class);
AsyncCallback Handlerを作成して、サーバーがクライアントにメッセージを返すRPCコールバックを処理します
class MessageCallBack implements AsyncCallback<Message> {
@Override
public void onFailure(Throwable caught) {
Window.alert("Unable to obtain server response: "
+ caught.getMessage());
}
@Override
public void onSuccess(Message result) {
Window.alert(result.getMessage());
}
}
ユーザーがUIと対話するときにリモートサービスを呼び出す
public class HelloWorld implements EntryPoint {
...
public void onModuleLoad() {
...
buttonMessage.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
messageService.getMessage(txtName.getValue(),
new MessageCallBack());
}
});
...
}
}
RPC通信の完全な例
この例では、簡単な手順でGWTのRPC通信の例を示します。 次の手順に従って、_GWTで作成したGWTアプリケーションを更新します-アプリケーションの作成_の章-
Step | Description |
---|---|
1 | Create a project with a name HelloWorld under a package com.finddevguides as explained in the GWT - Create Application chapter. |
2 | Modify HelloWorld.gwt.xml, HelloWorld.css, HelloWorldl and HelloWorld.java as explained below. Keep rest of the files unchanged. |
3 | Compile and run the application to verify the result of the implemented logic. |
以下は、変更されたモジュール記述子 src/com.finddevguides/HelloWorld.gwt.xml の内容です。
<?xml version = "1.0" encoding = "UTF-8"?>
<module rename-to = 'helloworld'>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name = 'com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. -->
<inherits name = 'com.google.gwt.user.theme.clean.Clean'/>
<!-- Inherit the UiBinder module. -->
<inherits name = "com.google.gwt.uibinder.UiBinder"/>
<!-- Specify the app entry point class. -->
<entry-point class = 'com.finddevguides.client.HelloWorld'/>
<!-- Specify the paths for translatable code -->
<source path = 'client'/>
<source path = 'shared'/>
</module>
以下は、変更されたスタイルシートファイル war/HelloWorld.css の内容です。
body {
text-align: center;
font-family: verdana, sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
color: #777777;
margin: 40px 0px 70px;
text-align: center;
}
以下は、変更されたHTMLホストファイル war/HelloWorldl の内容です。
<html>
<head>
<title>Hello World</title>
<link rel = "stylesheet" href = "HelloWorld.css"/>
<script language = "javascript" src = "helloworld/helloworld.nocache.js">
</script>
</head>
<body>
<h1>RPC Communication Demonstration</h1>
<div id = "gwtContainer"></div>
</body>
</html>
*src/com.finddevguides/client* パッケージにMessage.javaファイルを作成し、次のコンテンツをその中に配置します
package com.finddevguides.client;
import java.io.Serializable;
public class Message implements Serializable {
private static final long serialVersionUID = 1L;
private String message;
public Message(){};
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
*src/com.finddevguides/client* パッケージにMessageService.javaファイルを作成し、次のコンテンツをその中に配置します
package com.finddevguides.client;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
@RemoteServiceRelativePath("message")
public interface MessageService extends RemoteService {
Message getMessage(String input);
}
*src/com.finddevguides/client* パッケージにMessageServiceAsync.javaファイルを作成し、次のコンテンツをその中に配置します
package com.finddevguides.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface MessageServiceAsync {
void getMessage(String input, AsyncCallback<Message> callback);
}
*src/com.finddevguides/server* パッケージにMessageServiceImpl.javaファイルを作成し、次のコンテンツをその中に配置します
package com.finddevguides.server;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.finddevguides.client.Message;
import com.finddevguides.client.MessageService;
public class MessageServiceImpl extends RemoteServiceServlet
implements MessageService{
private static final long serialVersionUID = 1L;
public Message getMessage(String input) {
String messageString = "Hello " + input + "!";
Message message = new Message();
message.setMessage(messageString);
return message;
}
}
変更されたWebアプリケーションデプロイメント記述子 war/WEB-INF/web.xml の内容を更新して、MessageServiceImplサーブレット宣言を含めます。
<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>HelloWorldl</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>messageServiceImpl</servlet-name>
<servlet-class>com.finddevguides.server.MessageServiceImpl
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>messageServiceImpl</servlet-name>
<url-pattern>/helloworld/message</url-pattern>
</servlet-mapping>
</web-app>
*src/com.finddevguides/client* パッケージのHelloWorld.javaの内容を次のように置き換えます
package com.finddevguides.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DecoratorPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
public class HelloWorld implements EntryPoint {
private MessageServiceAsync messageService =
GWT.create(MessageService.class);
private class MessageCallBack implements AsyncCallback<Message> {
@Override
public void onFailure(Throwable caught) {
/*server side error occured*/
Window.alert("Unable to obtain server response: " + caught.getMessage());
}
@Override
public void onSuccess(Message result) {
/*server returned result, show user the message*/
Window.alert(result.getMessage());
}
}
public void onModuleLoad() {
/*create UI */
final TextBox txtName = new TextBox();
txtName.setWidth("200");
txtName.addKeyUpHandler(new KeyUpHandler() {
@Override
public void onKeyUp(KeyUpEvent event) {
if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER){
/*make remote call to server to get the message*/
messageService.getMessage(txtName.getValue(),
new MessageCallBack());
}
}
});
Label lblName = new Label("Enter your name: ");
Button buttonMessage = new Button("Click Me!");
buttonMessage.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
/*make remote call to server to get the message*/
messageService.getMessage(txtName.getValue(),
new MessageCallBack());
}
});
HorizontalPanel hPanel = new HorizontalPanel();
hPanel.add(lblName);
hPanel.add(txtName);
hPanel.setCellWidth(lblName, "130");
VerticalPanel vPanel = new VerticalPanel();
vPanel.setSpacing(10);
vPanel.add(hPanel);
vPanel.add(buttonMessage);
vPanel.setCellHorizontalAlignment(buttonMessage,
HasHorizontalAlignment.ALIGN_RIGHT);
DecoratorPanel panel = new DecoratorPanel();
panel.add(vPanel);
//Add widgets to the root panel.
RootPanel.get("gwtContainer").add(panel);
}
}
すべての変更が完了したら、link:/gwt/gwt_create_application [GWT-アプリケーションの作成]の章で行ったように、アプリケーションをコンパイルして開発モードで実行します。 すべてがあなたのアプリケーションでうまくいけば、これは次の結果を生成します-