Yes, this ability to share entity code between client and server is a big advantage we're trying to achieve with Errai. Glad to hear it's (nearly) working out for your project.
About your issue with lazy loading and Errai marshalling not playing well together, I acknowledge that this is a weak area, and it's one that we want to address in Errai 2.1. I have a few comments and suggestions:
1. I don't think there's any safe & predictable way of magically detaching entities and ignoring their lazily initialized data. After all, JPA2 even allows individual fields to be lazy-loaded. I think the best (least demand on the programmer; most declarative approach) we could do is provide an annotation you can apply to entity fields which makes them invisible to Errai Marshalling: something like @DoNotMarshal or @ErraiTransient. Before handing over an entity graph to Errai, you would be responsible for ensuring that each property of every object in the graph is either populated or marked "do not marshal this."
Does this sound like a happy medium for your use case?
2. I am currently working (in the 2.1 branch) on a client-side JPA2 implementation for Errai. Presently, it uses localStorage in the browser for storing and retrieving entity instances. Presently, retrieval can only be done by entity ID or by named queries. If you can think of a use case for this in your app (eg. offline support or caching hot data for speeding up page reloads) then I'd really appreciate some feedback on this feature.
3. Building on point #2, we will soon be starting work on a data synchronization facility that builds on both client-side and server-side JPA. The basic plan is that you would choose one or more named queries, fill in the query parameters, then tell the data synchronization API "keep the results of this data set in sync between the server and the client(s)." The datasync system would use Errai's push messaging system to publish changes in the data set between client(s) and server. Offline support will exist, and there will be a user-provided callback for managing conflicts in case the same data was updated independently in multiple places.
We think this "syncable dataset" idea has a lot of promise, but since we're still in the design phase, it's unfortunately not going to help you in your present predicament.
Thanks a lot for your quick and detailed answer, Jonathan!
@1: These annotation suggestions are definitely reasonable, but they won't solve our issues. At the moment, we distinghuish between one-to-many relationships as follows
- If the collection is empty, and lazyly fetched respectively, we convert it to an empty collection. So the collection is returned but empty.
- If the collection has items, we start the detaching process for each item.
We can influence the state of the fields by configuring our queries (fetch join). So, we do not simply ignore certain fields per default, but treat them according to their state. However, @DoNotMarshal is useful because we may have fields that never should go to the client.
@2: In a less generic way, that's exactly what we are doing at the moment. We have tables of entities that show some basic properties of them. If you click on a row, it re-fetches the entity by ID and shows it in an editor with all n-ary relationships.
@3: That sounds very promising indeed. I'm looking forward to any future releases .