Hi G-Men,

Here's our use-case: our domain model does not do lazy-loading (we're using 
Morphia with MongoDB, but if you're familiar with Objectify on AppEngine 
–I'm not, I've just read the docs–, it would look very similar; except that 
with Morphia we can opt-in to "managed relationships" and lazy-loading, we 
just chose not to do so), but we need to retrieve related entities on the 
client-side (using RequestFactory). We cannot (or "do not want to", if you 
prefer) put the accessors for the related entity within the domain class as 
we don't have a handle on the "entity manager" (we use DI all the way, I 
don't want to introduce a static factory similar to 
ObjectifyService.begin()).

A concrete example: we have "illustrations" and "files", a "file" can 
contain several "illustrations" through "legends" (the "legend" has the 
"file" as a "parent", and "links" to the "illustration", adding some data 
such as a title). Each one of these: illustration, file and legend are 
entities.
In Objectify, I think it'll map to something like:
public class Legend {
  @Id String id;
  @Parent Key<File> fileKey;
  Key<Illustration> illustrationKey;
}

Second example: a "contribution" is a link between a "file" and a "person", 
it adds the role of the contribution (was the person an author of the file? 
the architect of the building described by the file? etc.)

To finish drawing the whole picture, we have forms to edit legends and 
contributions: the ID of the legend/contribution is contained in the 
Place/history token, the illustration/person can only be known by retrieving 
the legend/contribution.
We don't want to do 2 requests (one for the legend/contribution, followed 
by, now that we have its ID, one for the illustration/person), but we cannot 
do a single one because we don't know the illustration/person's ID, and we 
do not have a getIllustration()/getPerson() on the Legend/Contribution 
domain objects.

We've solved it using a ServiceLayerDecorator that does "lazy loading" for 
us: when the property "illustration" is asked for a Legend, we look for the 
illustrationKey field, load the illustration and return it. That way, on the 
client-side, we just have to do a .with("illustration") to get the 
illustration associated with the legend.
As I said, we do not have a getIllustration() on the Legend domain class 
(but we do have one on the LegendProxy client type), and this makes the 
RequestFactoryInterfaceValidator bail.
We're working around it in two steps:
1. use @ProxyForName so the RequestFactoryGenerator compiles the client code 
without looking at the domain classes
2. copy the whole ResolverServiceLayer, removing anything related to 
RequestFactoryInterfaceGenerator; our copy then totally "overrides"/hides 
the original ResolverServiceLayer.
Not having our proxies validated against our domain model isn't much of an 
issue as we're generating one from the other.

The issue is that resolveClientType is not easy to implement, particularly 
for types that only go from server to client; so we have to do our own 
"bookmarking" in the resolveDomainMethod method.

Because this issue is likely to come in many projects using Objectify (and 
not only our project, using Morphia), I therefore suggest adding an 
annotation to selectively disable validation on methods. And by that I only 
mean disabling the check that a corresponding method exists in the domain 
class. You'd use it this way:

@ProxyFor(Legend.class)
public interface LegendProxy extends EntityProxy {
   // We do have String actually, but that wouldn't be very diferent with 
Key<?>
   String getIllustrationId();
   void setIllustrationId(String id);

   @SkipInterfaceValidation
   IllustrationProxy getIllustration();
   @SkipInterfaceValidation
   void setIllustratin(IllustrationProxy illustration);
}

Here, the RequestFactoryInterfaceValidator would validate the illustrationId 
accessors against the Legend class, would descend into the IllustrationProxy 
(in case it's not referenced directly by other methods where validation 
hasn't been disabled), but would not check whether there are corresponding 
getIllustration/setIllustration methods on the Legend class.

It would apply to both getters/setters on proxies, and request methods on 
contexts. We could imagine putting it on the class as a shortcut to applying 
it on each method.


I've already started working on a patch and it's fortunately a somewhat 
small change (add flag to RFMethod, do not poison() the validator if the 
flag is present, but perform all other checks otherwise).

What do you think?

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to