読者です 読者をやめる 読者になる 読者になる

JSONIC + Slim3 + GAE/JでRESTサービスを構築する方法 Part3

Java Slim3 GAE/J JSON 連載

これまでの記事はこちら。

2012-01-08 追記
Messagesクラスに@Modelアノテーションを付け忘れていたので追加。

今回は、検索機能や登録機能の実装について説明。ただ、長くなりそうなので、まずは最低限の雛形部分の作成までにしようと思います。

最初はControllerクラスの作成。これがWebサービスAPIになります。
src/main/javaの下に、com.example.controllerパッケージを作成し、そこにGreetingControllerクラスを作成します。GreetingControllerクラスには、find/create/update/deleteメソッドを定義します。

package com.example.controller;

import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.example.model.Messages;

/**
 * @author jupitris
 * 
 */
public class GreetingController {

    /** logger. */
    private static Logger logger = LoggerFactory.getLogger(GreetingController.class);

    /**
     * Returns the list of <code>Messages</code> which is found by condition.
     * 
     * @param param
     *            the condition for finding data.
     * @return the list of <code>Messages</code>
     */
    public List<Messages> find(Map<String, Object> param) {
        logger.debug("find was called.");
        return null;
    }

    /**
     * Create a message to data store.
     * 
     * @param messages
     *            the <code>Messages</code> which create to data store.
     */
    public void create(Messages messages) {
        logger.debug("create was called.");
    }

    /**
     * Update a message to data store.
     * 
     * @param messages
     *            the <code>Messages</code> which update to data store.
     */
    public void update(Messages messages) {
        logger.debug("update was called.");
    }

    /**
     * Delete a message from data store.
     * 
     * @param messages
     *            the <code>Messages</code> which delete from data store.
     */
    public void delete(Messages messages) {
        logger.debug("delete was called.");
    }
}

続いてcom.example.modelパッケージを作って、その下にMessagesクラスを作成します。

package com.example.model;

import java.io.Serializable;
import java.util.Date;

import org.slim3.datastore.Attribute;
import org.slim3.datastore.CreationDate;
import org.slim3.datastore.CreationUser;
import org.slim3.datastore.Model;
import org.slim3.datastore.ModificationDate;
import org.slim3.datastore.ModificationUser;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.users.User;

/**
 * @author jupitris
 * 
 */
@Model
public class Messages implements Serializable {

    /**
     * serialVersionUID.
     */
    private static final long serialVersionUID = 8376675962650956754L;

    /** primary key. */
    @Attribute(primaryKey = true)
    private Key key;

    /** the field realizes the optimistic lock. */
    @Attribute(version = true)
    private Long version = 0L;

    /** message. */
    private String message;

    /** created by. */
    @Attribute(listener = CreationUser.class)
    private User createdBy;

    /** created at. */
    @Attribute(listener = CreationDate.class)
    private Date createdAt;

    /** updated by. */
    @Attribute(listener = ModificationUser.class)
    private User updatedBy;

    /** updated at. */
    @Attribute(listener = ModificationDate.class)
    private Date updatedAt;

    /**
     * @return the key
     */
    public Key getKey() {
        return key;
    }

    /**
     * @param key
     *            the key to set
     */
    public void setKey(Key key) {
        this.key = key;
    }

    /**
     * @return the version
     */
    public Long getVersion() {
        return version;
    }

    /**
     * @param version
     *            the version to set
     */
    public void setVersion(Long version) {
        this.version = version;
    }

    /**
     * @return the message
     */
    public String getMessage() {
        return message;
    }

    /**
     * @param message
     *            the message to set
     */
    public void setMessage(String message) {
        this.message = message;
    }

    /**
     * @return the createdBy
     */
    public User getCreatedBy() {
        return createdBy;
    }

    /**
     * @param createdBy
     *            the createdBy to set
     */
    public void setCreatedBy(User createdBy) {
        this.createdBy = createdBy;
    }

    /**
     * @return the createdAt
     */
    public Date getCreatedAt() {
        return createdAt;
    }

    /**
     * @param createdAt
     *            the createdAt to set
     */
    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }

    /**
     * @return the updatedBy
     */
    public User getUpdatedBy() {
        return updatedBy;
    }

    /**
     * @param updatedBy
     *            the updatedBy to set
     */
    public void setUpdatedBy(User updatedBy) {
        this.updatedBy = updatedBy;
    }

    /**
     * @return the updatedAt
     */
    public Date getUpdatedAt() {
        return updatedAt;
    }

    /**
     * @param updatedAt
     *            the updatedAt to set
     */
    public void setUpdatedAt(Date updatedAt) {
        this.updatedAt = updatedAt;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((key == null) ? 0 : key.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        Messages other = (Messages) obj;
        if (key == null) {
            if (other.key != null) {
                return false;
            }
        } else if (!key.equals(other.key)) {
            return false;
        }
        return true;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return String
                .format("Messages [key=%s, version=%s, message=%s, createdBy=%s, createdAt=%s, updatedBy=%s, updatedAt=%s]",
                        key, version, message, createdBy, createdAt, updatedBy, updatedAt);
    }
}

これで、コンソールから

$ mvn gae:run

を実行すれば、Webサービスを起動することができます。
動作の確認には、Google Code Archive - Long-term storage for Google Code Project Hosting.で提供されているRESTClientを使うと便利です。GETとかPUTとかを切り替えながらリクエストを送信することが、容易にできます。
GET/POST/PUT/DELETEのいずれかのHTTP Methodを指定して、http://localhost:8080/restapp/greeting.jsonにアクセスすると、対応するControllerの各メソッドが呼び出されます。それぞれのHTTP Methodに対応するControllerクラスのメソッドは、下記の通り。

  • GET:find
  • POST:create
  • PUT:update
  • DELETE:delete

なお、今回作成したControllerクラスで定義したメソッドですが、JSONICのRESTサーブレットの仕様に則っています。詳細は、WebサービスAPI (JSONIC 1.3)にて。

次回は、ビジネスロジック周りを実装して、BigTableへのアクセスを行えるようにします。