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