自己紹介(1/2)
- 株式会社OpenWeb Technology代表
- Google API Expert (HTML5) / html5-developers-jp管理人
- 著書に「HTML5&API入門」があります。
白石俊平@OpenWeb Technology
アノテーションを指定するだけで、RESTfulなサービスを構築可能。
@Path("/items")
class Items {
@GET
@Produces("application/json")
public Response get() {
...
}
}
Jersey(JAX-RSの参照実装)には、RESTクライアントライブラリもついてきてお得。
// リソースの生成
WebResource r = httpClient.resource("http://api.twitter.com/1/statuses/update.json");
// OAuthフィルタを設定
OAuthParameters params = new OAuthParameters().signatureMethod(
HMAC_SHA1.NAME).consumerKey(CONSUMER_KEY).token(accessToken);
OAuthSecrets secrets = new OAuthSecrets().consumerSecret(
CONSUMER_SECRET).tokenSecret(accessSecret);
OAuthClientFilter filter = new OAuthClientFilter(httpClient
.getProviders(), params, secrets);
r.addFilter(filter);
Form form = new Form();
form.add("status", "Twitterに送るメッセージ。");
// POSTリクエスト実行。
ClientResponse response = r.type(MediaType.APPLICATION_FORM_URLENCODED)
.post(ClientResponse.class, form);
Google謹製DIコンテナ。
アノテーションによる指定でほとんどのDI設定を行うので、設定作業が最小限。
class Item {
@Inject
UserService userService;
...
}
GuiceyFruitを使えば、javax.annotationパッケージと統合できる。
カスタムスコープやProvider Injectionと組み合わせれば、JavaEE6 / CDIっぽいプログラミングが可能
class Item {
@Inject
UserService userService;
// Provider injection
@Inject
Provider<HttpServletRequest> request;
// DI後に呼び出される
@PostConstruct
public void init() {
// コンテキストに応じた適切なオブジェクトが返る
HttpServletRequet req = request.get();
...
}
...
}
基本は、JavaBeanのプロパティ値の検証を行うためのフレームワーク。
値の制約をアノテーションで指定可能。
class Person {
@NotNull @Pattern("\\w{1,20}")
String name;
@Min(0) @Max(120)
int age;
}
制約をまとめて、一つのアノテーションにすることが可能。
@Constraint(validatedBy = PersonValidator.class)
@NotNull @Pattern("\\w{1,20}")
annotation PersonName {
}
class Person {
@PersonName
String name;
@PersonAge
int age;
}
制約アノテーションと、パラメータバリデーション(まだ非標準)の組み合わせは強力!
以下の例ではJAX-RSと組み合わせて、リクエストパラメータのバリデーションも自動化している。
@Path("/persons")
class Persons {
@POST
void post(
@PersonName String name,
@PersonAge int age) {
...
}
}
Chrome Extensionなので、ずっとバックグラウンドでpingをうち続けられる。
Retry-Afterヘッダを用いて、pingの間隔をサーバがコントロール可能。
class PingServlet extends HttpServlet{
public void doGet(HttpServletRequest req, HttpServletResponse resp) {
int retry = ...;
resp.setIntHeader("Retry-After", retry);
}
}
function ping() {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.status != 4)
return;
var retryAfter = parseInt(request.getResponseHeader("Retry-After"));
setTimeout(ping, retryAfter);
}
request.open("GET", "/ping");
request.send();
}
ping();
「OpenID4Java」というライブラリをベースに、OpenID対応コードを書いていましたが・・・
AppEngine本体がOpenIDに対応してしまったせいで、全部捨てるハメに。。
AppEngineでのOpenID認証の利用方法
String loginUrl =
userService.createLoginURL("/callback", "www.davincipad.net",
openId, null);
response.sendRedirect(loginUrl);
Userをパラメータとしたクエリは禁止!
Emailでの比較になってしまう(バグ?もう直ってる?)が、OpenIDプロバイダによっては、メールアドレスを返さない。
User loggedIn = userService.getCurrentUser();
AccountMeta meta = AccountMeta.get();
Account account =
Datastore.query(meta).filter(meta.user.equal(loggedIn));
guestbook-example-appengine-full-text-searchを参考に、全文検索機能を実装しました。
もとはJDO向けのサンプルだったので、ロジックをパクってSlim3上で実現しました。
public class FTSUtils {
// CJKに対応したアナライザ
private static CJKAnalyzer analyzer = new CJKAnalyzer(Version.LUCENE_30);
public static Set toTokens(String text) {
Set results = new HashSet();
// トークンに分割
TokenStream tokens = analyzer.tokenStream(null, new StringReader(text));
while (tokens.incrementToken()) {
TermAttribute term = tokens.getAttribute(TermAttribute.class);
results.add(term.term());
}
return results;
}
}
// 全文検索のインデックスを保存するためのモデル
TextItemIndexModel index = new TextItemIndexModel(this);
// バラしたトークンをセットして保存
Set<String> terms = FTSUtils.toTokens(getTextData());
index.setTerms(terms);
Datastore.put(index);
Set tokens = FTSUtils.toTokens(query);
Set tokens = FTSUtils.toTokens(query);
TextItemIndexModelMeta meta = TextItemIndexModelMeta.get();
List indexKeys =
Datastore.query(meta).filter(
meta.terms.in(tokens)).asKeyList();