何度やっても同じ

ただの日記

Java + facebook Graph API メモ

Graph API は restfb

Graph API の呼び出しはrestfb。きれいに設計されていてとても使いやすい。オブジェクトをGETしたいときは、オブジェクトの種類を問わずfetchObjectまたはfetchConnectionを使う。これはすべてのオブジェクトを一意なIDで管理していて型(?)におおらかなfacebook側の設計と親和性が高い。もちろん、生JSONとかMAPが返ってきてもイヤなので、型は引数で指定。

User user = facebook.fetchObject("me", User.class, 
        Parameter.with("fields", "id,name,location"));

使いたいフィールドが、restfbによって提供されているモデルオブジェクトに含まれていなければ、自分で拡張すればよい。たとえば、Userクラスにはpictureフィールドがない(プロフィール画像が取れない!)ので、そんな場合はこうやって…

ExtendedUser user = facebook.fetchObject("me", ExtendedUser.class, 
        Parameter.with("fields", "id,name,location,picture"));

ExtendedUserを自作する。facebookが返すpictureフィールドは値がオブジェクトなので、対応するクラスが必要。返ってくるデータの形式さえつかんでいれば、あとは機械的作業。

public class ExtendedUser extends User {

    private static final long serialVersionUID = 1L;

    @Facebook
    private Picture picture;
  
    public Picture getPicture() {
      return picture;
    }

    public void setPicture(UserPicture picture) {
      this.picture = picture;
    }
}

public static class Picture implements Serializable {

    private static final long serialVersionUID = 1L;

    @Facebook
    private Data data;

    public Data getData() {
        return data;
    }

    public void setData(Data data) {
        this.data = data;
    }

    public static class Data implements Serializable {

        private static final long serialVersionUID = 1L;

        @Facebook("is_silhouette")
        private boolean isSilhouette;

        @Facebook
        private String url;

        public boolean isSilhouette() {
            return isSilhouette;
        }

        public void setSilhouette(boolean isSilhouette) {
            this.isSilhouette = isSilhouette;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }
    }
}

ログイン処理は自分で書いてしまう

restfbはログイン処理してくれないので、ここは自分で書いてしまう。こんな感じで使えるFacebookLoginクラスを作った。あとで公開しとく。かも。

public class IndexController extends BaseController {

    @Override
    protected Navigation run() throws Exception {

        AccessToken accessToken = sessionScope("access_token");
        if (accessToken != null && !accessToken.isExpired()) {
            return forward("index.jsp");
        }

        FacebookLogin login =
            FacebookLogin.Builder
                .with(FacebookService.APP_ID, FacebookService.APP_SECRET)
                .setCallbackUrl("https://apps.facebook.com/xxx/")
                .setPermissions(Permission.values())
                .begin();

        String code = asString("code");
        if (StringUtil.isEmpty(code)) {
            AccessToken token = login.getAccessToken(code);
            sessionScope("access_token", token);
            return forward("index.jsp");
        }

        return html(login.getLoginDialogRedirectScript());
    }
}

それはそうと、写真へのタグ付けでひっかかった

写真へのタグ付けを行って成功すると、facebookから次のようなレスポンスが返ってくる。

true

trueって何だよ…。wktkしてJSONを期待しているrestfbがこれをくらうとパースエラー吐くので、restfbを直さないといけない。GitHubで公開されているプロジェクトは、pom.xmlが少し変(ソースフォルダの設定がないとか)な気がするけど、build.xmlもついてるしビルドはしやすい。