问题
I would like to use the same code to sort and manipulate objects in client and server sides.
But I am facing a problem since in client we need a proxy interface representing the class of the server.
Is there a way to use the same interface in both?, I know RF has a mechanism to copy bean attributes from the server instance to the client instance when it is sent through the wire.
回答1:
As Thomas says in his answer, the only way in current GWT to have shared code in client and sever is implementing the same interface in both sides and using it in your shared code.
Since RF copies attributes from the server to the client as you say in your query, in theory we could use the same interface (the proxy one) in both sides (simpler code), setting the @ValueFor value pointing to itself.
Lets see an example:
// 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";};
}
As information, we use this approach in our product, so as we can sell 2 backend solutions (one is based on GAE and other on couchdb).
The code above works for client code which does not create new values, but if you want to create them, it is enough to define a value locator:
// 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();
}
...
}
Unfortunately, RF does not deal with interfaces in the server side see issues: 7509 and 5762.
But, as you can read in the issues comments, there is already a fix for this (pending for review). Hopefully it would be included in a next release of GWT.
In the meanwhile, you can use this approach, just copying the file ResolverServiceLayer.java
in your src folder and applying this patch to it.
回答2:
One way to use the same API is to use interfaces that both your proxies extend and your domain objects implement.
// 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
}
You can then use a Comparator<Foo>
or Comparator<Bar>
in both client and server side.
I generally only implement traits (aspects, facets, call them the way you like) that way though (HasId
, HasLabel
, HasPosition
, etc.), not complete domain objects' APIs. I can then use HasId
to get the key of any object to put them in a map or compare for equality, HasLabel
for displays (custom Cell
s on the client-side, error messages on the server-side that are sent to the client, etc.), HasPosition
for sorting, etc.
回答3:
The point of RequestFactory is that it does not do use the same type. Each request context describes a set of operations to perform when the call gets to the server (create and find things, then apply setters, then run service methods). As calls are described as just proxies to the real thing on the server, you need a 'fake' model object like a EntityProxy
or ValueProxy
to ensure that the only calls that can be made are getters and setters - and that sometimes, setters are not allows (when an object has been read from the server but before it has been edited).
If your models are simple, i.e. not holding other objects, but only string, date, and primitives, you can have both the entity and the proxy implement the same interface. However, if the model holds sub-objects, then this is more difficult - the only way possible is to leave out those getters and setters. Otherwise, you can't override those methods in the proxy type to specify the proxy version of that nested object.
Consider using RPC isntead if you actually want to reuse the same types on the client and server.
来源:https://stackoverflow.com/questions/15849602/gwt-rf-how-to-share-the-same-code-in-client-and-server