他のウェブサービスからデータを取得する
今回は、サイボウズ・ラボ株式会社が運営している、「Pathtraq」(パストラック)が提供する「キーワード・URL検索API」にGoogle App Engine上のプログラムからアクセスし、指定したURLに含まれる、人気ページの一覧をJSON形式で受信するプログラムを作成します。プログラムでは、JSONを見やすくするために、GWTを利用してブラウザでツリー形式に展開して表示します。
まず、「src/com/daisukeyamashita/test/urlfetch/UrlFetchTest.gwt.xml」の<module>タグの直後(4行目)に<inherits name='com.google.gwt.json.JSON' />を挿入してください。
次に、「war/UrlFetchTest.html」の下から3行目にある</table>タグ直前に以下の3行を挿入してください。
<tr> <td colspan="2" id="search"></td> </tr>
この2つの準備ができたら、以下の2つのソースコードを書き直してください。
package com.daisukeyamashita.test.urlfetch.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import com.daisukeyamashita.test.urlfetch.client.GreetingService;
import java.net.URL;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
/**
* The server side implementation of the RPC service.
*/
@SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {
public String greetServer(String url) {
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try {
URL urlPathtraq = new URL("http://api.pathtraq.com/pages?api=json&url=" + url); // (1)
reader = new BufferedReader(new InputStreamReader(urlPathtraq.openStream())); // (2)
String line;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
package com.daisukeyamashita.test.urlfetch.client;
import java.util.Set;
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.json.client.JSONArray;
import com.google.gwt.json.client.JSONException;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class UrlFetchTest implements EntryPoint {
/**
* Create a remote service proxy to talk to the server-side Greeting
* service.
*/
private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
private final Tree jsonTree = new Tree();
/**
* This is the entry point method.
*/
public void onModuleLoad() {
final Button sendButton = new Button("Send");
final TextBox nameField = new TextBox();
nameField.setText("http://www.google.co.jp");
// We can add style names to widgets
sendButton.addStyleName("sendButton");
// Add the nameField and sendButton to the RootPanel
// Use RootPanel.get() to get the entire body element
RootPanel.get("nameFieldContainer").add(nameField);
RootPanel.get("sendButtonContainer").add(sendButton);
RootPanel.get("search").add(jsonTree);
// Focus the cursor on the name field when the app loads
nameField.setFocus(true);
nameField.selectAll();
// Create a handler for the sendButton and nameField
class MyHandler implements ClickHandler, KeyUpHandler {
/**
* Fired when the user clicks on the sendButton.
*/
public void onClick(ClickEvent event) {
sendNameToServer();
}
/**
* Fired when the user types in the nameField.
*/
public void onKeyUp(KeyUpEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
sendNameToServer();
}
}
/**
* Send the name from the nameField to the server and wait for a
* response.
*/
private void sendNameToServer() {
sendButton.setEnabled(false);
String textToServer = nameField.getText();
greetingService.greetServer(textToServer, new AsyncCallback<String>() {
public void onFailure(Throwable caught) {
sendButton.setEnabled(true);
}
public void onSuccess(String result) {
try {
JSONValue jsonValue = JSONParser.parse(result);
displayJSONObject(jsonValue);
} catch (JSONException e) {
e.printStackTrace();
}
sendButton.setEnabled(true);
}
});
}
}
// Add a handler to send the name to the server
MyHandler handler = new MyHandler();
sendButton.addClickHandler(handler);
nameField.addKeyUpHandler(handler);
}
private void displayJSONObject(JSONValue jsonValue) {
jsonTree.removeItems();
jsonTree.setVisible(true);
TreeItem treeItem = jsonTree.addItem("JSON Response");
addChildren(treeItem, jsonValue);
treeItem.setStyleName("JSON-JSONResponseObject");
treeItem.setState(true);
}
private void addChildren(TreeItem treeItem, JSONValue jsonValue) {
JSONArray jsonArray;
JSONObject jsonObject;
JSONString jsonString;
if ((jsonArray = jsonValue.isArray()) != null) {
for (int i = 0; i < jsonArray.size(); ++i) {
TreeItem child = treeItem.addItem(getChildText("[" + Integer.toString(i) + "]"));
addChildren(child, jsonArray.get(i));
}
} else if ((jsonObject = jsonValue.isObject()) != null) {
Set<String> keys = jsonObject.keySet();
for (String key : keys) {
TreeItem child = treeItem.addItem(getChildText(key));
addChildren(child, jsonObject.get(key));
}
} else if ((jsonString = jsonValue.isString()) != null) {
treeItem.addItem(jsonString.stringValue());
} else {
treeItem.addItem(getChildText(jsonValue.toString()));
}
}
private String getChildText(String text) {
return "<span style='white-space:normal'>" + text + "</span>";
}
}
