同じコードを使用して、クライアント側とサーバー側でオブジェクトをソートおよび操作したいと考えています。
しかし、クライアントではサーバーのクラスを表すプロキシ インターフェイスが必要なため、問題に直面しています。
両方で同じインターフェイスを使用する方法はありますか? RF には、Bean 属性がネットワーク経由で送信されるときに、サーバー インスタンスからクライアント インスタンスに Bean 属性をコピーするメカニズムがあることがわかっています。
同じコードを使用して、クライアント側とサーバー側でオブジェクトをソートおよび操作したいと考えています。
しかし、クライアントではサーバーのクラスを表すプロキシ インターフェイスが必要なため、問題に直面しています。
両方で同じインターフェイスを使用する方法はありますか? RF には、Bean 属性がネットワーク経由で送信されるときに、サーバー インスタンスからクライアント インスタンスに Bean 属性をコピーするメカニズムがあることがわかっています。
同じ API を使用する 1 つの方法は、プロキシが拡張し、ドメイン オブジェクトが実装するインターフェイスを使用することです。
// common interfaces
interface Foo { … }
interface Bar<T extends Foo> {
int getX();
void setX(int x);
// setters need to use generics
List<T> getFoos();
void setFoos(List<T> foos);
// with only a getter, things get easier:
Bar getParent();
}
// domain objects
class RealFoo implements Foo { … }
class RealBar implements Bar<RealFoo> {
int x;
List<RealFoo> foos;
RealBar parent;
@Override
public RealBar getParent() { return parent; }
// other getters and setters
}
// proxy interfaces
@ProxyFor(RealFoo.class)
interface FooProxy extends Foo { … }
@ProxyFor(RealBar.class)
interface BarProxy extends Bar<FooProxy> {
@Override
BarProxy getParent();
// other getters and setters
}
その後、クライアント側とサーバー側の両方でComparator<Foo>
orを使用できます。Comparator<Bar>
私は一般的に、完全なドメイン オブジェクトの API ではなく、特性(アスペクト、ファセット、好きなように呼び出す) のみをそのように実装します ( HasId
、HasLabel
、など)。HasPosition
次にHasId
、任意のオブジェクトのキーを取得して、それらをマップに配置したり、同等性を比較したり、表示したりできHasLabel
ます (クライアント側のカスタムCell
s、クライアントに送信されるサーバー側のエラー メッセージなど)。 、HasPosition
仕分け用など
RequestFactory のポイントは、同じ型を使用しないことです。各リクエスト コンテキストは、呼び出しがサーバーに到達したときに実行する一連の操作を記述します (作成および検索、セッターの適用、サービス メソッドの実行)。呼び出しはサーバー上の本物への単なるプロキシとして記述されるため、実行できる呼び出しがゲッターとセッターのみであることを保証するために、 EntityProxy
orのような「偽の」モデル オブジェクトが必要です。ValueProxy
オブジェクトがサーバーから読み取られたが、編集される前の場合)。
モデルが単純な場合、つまり、他のオブジェクトを保持せず、文字列、日付、およびプリミティブのみを保持する場合、エンティティとプロキシの両方に同じインターフェイスを実装させることができます。ただし、モデルがサブオブジェクトを保持している場合、これはより困難です。可能な唯一の方法は、それらのゲッターとセッターを除外することです。そうしないと、プロキシ タイプでこれらのメソッドをオーバーライドして、ネストされたオブジェクトのプロキシ バージョンを指定することはできません。
クライアントとサーバーで同じ型を実際に再利用したい場合は、RPC の代わりに使用することを検討してください。
トーマスが答えで言っているように、現在の GWT でクライアントとサーバーでコードを共有する唯一の方法は、両側で同じインターフェースを実装し、それを共有コードで使用することです。
クエリで言うように、RF はサーバーからクライアントに属性をコピーするため、理論的には、@ValueFor 値をそれ自体を指すように設定して、両側で同じインターフェイス (プロキシ インターフェイス) を使用できます (より単純なコード)。
例を見てみましょう:
// Shared interface in client and server sides
@ProxyFor(Foo.class)
interface Foo extends ValueProxy {
String getBar();
}
// Server side implementation
class FooImpl implements Foo {
String getBar(){return "bar";};
}
情報として、2 つのバックエンド ソリューション (1 つは GAE ベース、もう 1 つは couchdb ベース) を販売できるように、製品でこのアプローチを使用しています。
上記のコードは、新しい値を作成しないクライアント コードに対して機能しますが、それらを作成する場合は、値ロケーターを定義するだけで十分です。
// Say RF which locator to use to create classes in server side
@ProxyFor(value = Foo.class, locator ALocator.class)
interface Foo extends ValueProxy {
}
public class ALocator extends Locator<Foo, String> {
public Foo create(Class<? extends Foo> clazz) {
return new FooImpl();
}
...
}
残念ながら、RF はサーバー側のインターフェースを処理しません: 問題 7509および5762を参照してください。
しかし、問題のコメントを読むことができるように、これに対する修正は既にあります(レビュー待ち)。GWT の次のリリースに含まれることを願っています。
それまでの間、このアプローチを使用して、ファイルResolverServiceLayer.java
を src フォルダーにコピーし、このパッチを適用するだけです。