GWT RequestFactory: How can I get a persistent id from stableId()?
I use Long
ids in my entities, not only to store them in the datastore, but to reference other entities. Now, I'm using RequestFactory to create() objects on the client and persist them, but I need a way to figure out what id the server has generated.
Here's one way I've figured out that requires two trips:
final OrganizationProxy proxy = context.create(OrganizationProxy.class);
context.persist().using(proxy).fire(new Receiver<Void>(){
public void onSuccess(Void response)
{
requestFactory.find(proxy.stableId()).fire(new Receiver<OrganizationProxy>()
{
public void onSuccess(Organi开发者_C百科zationProxy response)
{
//hey, now response has the server-generated id in it, along with any other values the server populated
}
});
}
});
But it seems like there must be a way to get the persistent id without the second trip. It seems like requestFactory.find() would need the persistent id to work at all in the first place.
How can I get at the persistent id without a second request to the server?
=======Update=======
It finally occurred to me (after tbroyer told me ;)) that I could return the Long
id from the persist() method in the RequestContext. This doesn't retrieve the persistent id from the EntityProxyId
, but it does get me the persistent id of a new object in a single request.
I'll leave this question open - I am still interested in getting the persistent id out of an EntityProxyId.
You can get a String representation of an EntityProxyId by calling RequestFactory.getHistoryToken()
. This can be converted back to an EntityProxyId
by calling RequestFactory.getProxyId()
.
In RequestFactory parlance, the id of a newly-created entity is "ephemeral." An ephemeral id is only valid within the instance of the RequestFactory
that created the RequestContext
used to create the EntityProxy
. When the RequestContext
is fired and all method invocations have been processed by the server, the SimpleRequestProcessor
will check the payload's ephemeral objects and if they have been persisted, the resulting payload will update the client's state with the value returned from the getId()
method.
The object identity and equality of an EntityProxyId
won`t change when it switches from the ephemeral to persistent state, but its associated history token will change:
OrganizationProxy proxy = context.create(OrganizationProxy.class);
final EntityProxyId<?> id = proxy.stable();
String ephemeralString = factory.getHistoryToken(id);
context.persist().using(proxy).fire(new Receiver<Void>() {
public void onSuccess(Void response) {
String persistedString = factory.getHistoryToken(id);
assert !ephemeralString.equals(persistedString);
assert factory.getProxyId(ephemeral) == factory.getProxyId(persistedString);
MyRequestFactory otherFactory = GWT.create(MyRequestFactory.class);
assert factory.getProxyId(ephemeral) != otherFactory.getProxyId(ephemeral);
// Throws IllegalArgumentException
otherFactory.find(otherFactory.getProxyId(ephemeral));
}
});
In the above demo, once you have persistedString
, you can stash the value in a cookie or some other client-side persistence mechanism and re-create the id later to be used with a call to RequestFactory.find()
. The second and third assertions demonstrate the "scope" of an ephemeral id. The ephemeral and persisted forms can be used interchangeably with the RequestFactory
that created the object. If an ephemeral id is used with a newly-created instance of a RequestFactory
(which would happen if an ephemeral id were bookmarked as a History
token), you'll get an EntityProxyId
, but it can't really be used for any useful purpose.
The class implementing an EntityProxyId
is SimpleEntityProxyId
. This class has a method getServerId()
, which will return the id. So by checking with instanceof
you can then call the method. (Actually RequestFactory.getHistoryToken()
doesn't even check, but simply casts to this class).
Now the bad news: it's encoded and the base class for SimpleEntityProxyId
, which is SimpleProxyId
and contains the method getServerId()
, specifically states:
The encodedAddress is totally opaque to the client. It's probably a base64-encoded string, but it could be digits of pi. Any code that does anything other than send the contents of this field back to the server is wrong.
(Where the field encodedAddress
contains the server id.)
I just declared the getId() method in my Proxy interface and it seems to work. Is there any problem with this approach?
精彩评论