Extend RequestFactory to Make Use of None Primitive Types

73 views
Skip to first unread message

hkropp

unread,
Nov 7, 2011, 8:40:41 AM11/7/11
to google-we...@googlegroups.com
Hi,

is there a way to extend the RequestFactory to support none primitive types? For example a way to write modules which tell the RequestFactory how to de-/serialize the specific none primitive type to a String and vis versa, so it can be use over HTTP?

kind regards

Patrick Julien

unread,
Nov 7, 2011, 9:03:00 AM11/7/11
to google-we...@googlegroups.com
RequestFactory is already over http.

If you're looking to shoot over a String, just use a String.  You can use, but don't recommend, DefaultProxyStore for this purpose which you can obtain from RequestFactory.

but again, RF is already over http

hkropp

unread,
Nov 7, 2011, 9:09:26 AM11/7/11
to google-we...@googlegroups.com

hkropp

unread,
Nov 8, 2011, 3:27:49 AM11/8/11
to google-we...@googlegroups.com
Maybe describing my current problem with RF helps make things clear.

I want to use MongoDB for the Employee example. Now MongoDB is using org.bson.ObjectId as the PK instead of the primitive type Long for its objects.

So the question is, can I make RF use ObjectId?

thx

Thomas Broyer

unread,
Nov 8, 2011, 4:13:44 AM11/8/11
to google-we...@googlegroups.com
Yes; and no.

RF can use any object as the entity ID (returned by the getId method on your entity or locator) on the server side.
You cannot use ObjectId on the client-side, but you could map it as a ValueProxy; the only issue is that ObjectId is immutable, so you won't be able to pass an "ObjectIdProxy" to a method (as RF would have to reconstruct it on the server-side, which assumes the object is mutable), be it a setter on a proxy or a service method; but a getter or a service-method return value should be an issue.
If you do want to "set" an ObjectId on the client-side, your best bet would be to either marshall your ObjectId to a String (and yes, this has to be done "manually" everywhere you need it), or use a builder-pattern around an ObjectId on the server-side (mapped on the client-side as a ValueProxy; and yes, that also means using that ObjectIdBuilder everywhere instead of ObjectId).

Something like:

abstract class AbstractObjectId {
   public abstract int getTime();
   public abstract int getMachine();
   public abstract int getInc();
   public abstract void setTime(int time);
   public abstract void setMachine(int machine);
   public abstract void setInc(int inc);

   public abstract ObjectId asObjectId();
}

@ProxyFor(value=AbstractObjectId.class, locator=ObjectIdLocator.class)
interface ObjectIdProxy extends ValueProxy {
   // getters and setters for time, machine and inc
}

public class ObjectIdLocator extends Locator<AbstractObjectId, Void> {
   public AbstractObjectId create(Class<? extends AbstractObjectId> clazz) {
      return new ObjectIdBuilder();
   }
   
   public AbstractObjectId find(Class<? extends AbstractObjectId> clazz, Void id) {
      throw new UnsupportedOperationException("should never be called for a ValueProxy");
   }
   // do the same as find() for all the other methods; only entities have ID and version.
}

class ObjectIdBuilder extends AbstractObjectId {
   private ObjectId objectId;
   private int time;
   private int machine;
   private int inc;

   // getters and setters, as usual

   public ObjectId asObjectId() {
      if (objectId == null) {
         objectId = new ObjectId(time, machine, inc);
      }
      return objectId;
   }
}

// use this on the server-side, to wrap an ObjectId so it can be sent to the client.
class ObjectIdWrapper extends AbstractObjectId {
   private final ObjectId objectId;
   public ObjectIdWrapper(ObjectId objectId) {
       this.objectId = objectId;
   }
   public int getTime() { return objectId.getTime(); }
   public void setTime(int time) { throw new UnsupportedOperationException(); }
   // similar for machine and inc

   public ObjectId asObjectId() { return objectId; }
}

Alternatively, you could use a single String property instead of the three 'int' ones.

This approach is completely untested though. It'd IMO be much easier to add a pair of String-based accessors to the ID and map those in your proxies (leaving ObjectId entirely on the server side).

hkropp

unread,
Nov 11, 2011, 4:10:57 AM11/11/11
to google-we...@googlegroups.com
Thanks for your detailed explanation. It helped me understand RF and GWT a little better.

I ended up with a EmplyeeGWT class, which extends the MongoDB model but returns the ObjectId as String and parse the returned String to ObjectId. This seems to work. One restriction to our problem is also, that the model gets generated. The thing that bugs me is that I have an extra model and also an extra service just for GWT. We are thinking about making GWT use the JERSEY Service over RPC, but than we cant use the Objects on the client side.
So far many thanks for the help.


Reply all
Reply to author
Forward
0 new messages