Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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(OrganizationProxy 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.

like image 961
Riley Lark Avatar asked Feb 20 '11 18:02

Riley Lark


2 Answers

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.

like image 155
BobV Avatar answered Oct 14 '22 05:10

BobV


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.)

like image 42
Hilbrand Bouwkamp Avatar answered Oct 14 '22 05:10

Hilbrand Bouwkamp