Google App EngineとFlex間(BlazeDS)でDatastoreのKeyを送受信

普通にやってもAMFでキーを渡せないみたいです。
キーの値がnullになってしまう。

BeanProxyってのを実装すればオブジェクト変換をごにょごにょできる事がわかったので

GAEのKey変換を作ってみました。

Java側でKeyを変換するKeyProxyクラス

slim3に依存してます。

public class KeyProxy extends BeanProxy {
    public Object createInstance(String className) {
        return new KeyStub();
    }

    public Object getValue(Object instance, String propertyName) {
        Key key = (Key) instance;
        if (propertyName.equals("keyStr")) {
            return KeyFactory.keyToString(key);
        } else if (propertyName.equals("name")) {
            return key.getName();
        } else if (propertyName.equals("id")) {
            return key.getId();
        } else if (propertyName.equals("kind")) {
            return key.getKind();
        }
        throw new IllegalArgumentException("ん? " + propertyName);
    }

    public void setValue(Object instance, String propertyName, Object value) {
        KeyStub es = (KeyStub) instance;
        if (propertyName.equals("keyStr")) {
            es.keyStr = StringUtils.toString(value);
        } else if (propertyName.equals("name")) {
            es.name = StringUtils.toString(value);
        } else if (propertyName.equals("id")) {
            if (!value.equals(Double.NaN)) {
                es.id = NumberUtils.toLong(value);
            }
        } else if (propertyName.equals("kind")) {
            es.kind = StringUtils.toString(value);
        } else {
            throw new IllegalArgumentException("ん? " + propertyName);
        }
    }

    public Object instanceComplete(Object instance) {
        KeyStub es = (KeyStub) instance;

        if (es.keyStr != null) {
            return KeyFactory.stringToKey(es.keyStr);
        } else if (es.name != null) {
            return Datastore.createKey(es.kind, es.name);
        } else if (es.id != null) {
            return Datastore.createKey(es.kind, es.id);
        }

        throw new IllegalArgumentException("ん? ");
    }

    public List getPropertyNames(Object instance) {
        return Arrays.asList("keyStr", "name", "id", "kind");
    }

    class KeyStub {
        // Key key;
        String keyStr;
        String name;
        Long id;
        String kind;
    }
}
KeyProxyをBlazeDSに登録するクラス

よくわからないけど、とりあえずMessageBrokerServletに追加すればOKでした。

public class MessageBrokerServlet2 extends MessageBrokerServlet {
    static {
        PropertyProxyRegistry.getRegistry().register(Key.class, new KeyProxy());
    }
}
Flex側のKeyクラス
[RemoteClass(alias="com.google.appengine.api.datastore.Key")]
public class Key
{
	public function Key()
	{
	}
	
	public var keyStr:String;
	public var name:String;
	public var id:Number;
	public var kind:String;
}

で、

FlexではModelクラスに↑のKeyクラスでkeyプロパティを定義してやれば普通にKeyを扱えるようになります。

注意

Flex側でKeyを生成したい場合は、keyのnameかidだけセットすればOKだけど、
今の実装ではEGは管理できないので、EGに属するKeyを生成したい場合はGAE側でキーを生成して、keyStrでやりとりする必要があります。
(GAEでキーを生成すれば後はKeyProxyが勝手にやってくれます)
とりあえずは、FlexでのEG作成は使わないから実装してませんが、うまくやればFlexからでもparentKeyを指定した生成も可能かと思います。

別に

↓の方法でも全然恥ずかしくないんだけど、
http://blog.livedoor.jp/teruriot/archives/65184994.html