Sep 21st, 2011, 03:20 AM
SDG: Best Practice - Managing multiple domain model instances
I'm looking for a best practice approach for the following problem:
We have a domain model with several relationships between the entities. Many of them are implemented with @GraphProperty annotated properties. We store such a domain model in a neo4j database where every entity is unique (identified by a UUID). We also use GraphRepository for entity lifecycle and lookup operations. What we now have is a synchronization mechanism with domain model descriptions (we get a JSON with a domain model description inside which we call 'remote domain model'). Now, a converter converts the JSON domain model description into the application's domain model entities.
The synchronization mechanism now compares the remote domain model with the one that already exists inside the application (the so called 'local domain model') to synchronize the local domain model with the content of the remote domain model. As we use interfaces for the entities, the same interfaces for the local domain model and the remote domain model are getting used.
There are several methods on the entities which use the power of neo4j's traversal descriptions. Currently, the remote domain model entities are implemented with in memory instances where all these methods aren't implemented wich use a traversal description.
It would be nice now, if we also can use neo4j for the remote domain model. The Problem is, that the GraphRepository lookup methods such as 'findByName' returns two objects, the remote and the local one.
For me, there are several solutions for this problem.
1. Use two independent databases. The problem: Synchronization may occur in parallel, so we must have many neo4j db instances (initialization takes time) only for a few method calls.
2. Mark entities as 'remote' or 'local'. The problem: A 'remote' marked must be identifiable by a 'synchronization' id to separate all possible remote entities which may exists in parallel for every currently running synchronization.
3. There exists a 'synchronization' entity node where all remote entities are related to. This would be one of my prefered solution. The problem: Lookup methods such as findByXX doen't work as described above.
It seems, that there needs also to be an index for every synchronization entity, but I can't find a way to do that in SDG. What would be the SDG's best practice approach for solving this problem. I think this is a common problem which occurs everywhere where graph traversial makes sense outside of application's persisted domain model.
Sep 22nd, 2011, 03:46 AM
I need to understand some things first:
Does this application run with neo4j-embedded + a server which then exposes endpoints that return your domain level JSON description?
Or is it just a single engine that uses JSON to transfer data between different layers?
Or is it a Neo4j-Server + custom extension written with SDG and a web-app in front of that that also runs SDG (or a different domain model)?
In general low level graph primitives as well as domain objects are too fine-grained for remote synchronization (and are affected by latency and bandwith). I'd rather look at your use-cases and provide endpoints for those - specific endpoints for reading data in one go that is needed in the main application.
And second endpoints that take commands with change-sets, i.e. operations that have been applied to entities in the application.
Calculating diffs is much more cumbersome and difficult (esp. if you take object-relationships into account) than having a clean use-case based command approach.
One could abstract both by having a means to describe fetch-plans for sub-graphs on the "read"-endpoints that provide the data that is needed to create the "App-domain (which might be differently structured per use-case from the graph-content). For recording changes as commands which then will be applied to the graph-entities in the server it is also possible to create appropriate mechanisms using the SDG infrastructure.
Let's continue that discussion to work out what you really need,
Sep 23rd, 2011, 03:48 AM
Thanks for your reply.
I wouldn't use SDG to synchronize. Synchronization is getting made inside the application. Let me generalize the problem: Let's assume we have a domain model, stored in a neo4j database and managed by SDG inside the persistence layer. Such entities are 'the entities users work with'. Now we want, for our synchronization approach with third party applications, to use the same domain class interfaces to represent the incoming data. For now, we have an in-memory representation of such interfaces. Because these are the same interfaces, we want to use the same methods. So now it would be nice if we can throw the in memory representation away and use neo4j as in this case, we can reuse the traversal descriptions.
Sep 24th, 2011, 03:33 AM
That also means that you let your domain objects leave the persistence layer and also be used in the application layer (which handles the data form the 3rd party apps).
You mean by just annotating interfaces? With the appropriate getters / setters?
Couldn't you just use the SDG entities there? Why keep the separation in SDG entities and interfaces + in memory-representation (probably hashmap).
I'm currently working on supporting the Spring Data Commons Mapping Abstractions in SDG this should make it easier to map non-aj entities to the SDG graph.
Unfortunately it's is not implemented right now that you can use aspects on top of just your interfaces. That has been requested just once so far and should be doable.
It would mean to allow the annotations also be placed on methods (getters) and have an aspect that handles this case.
Until then you could just use java.lang.reflect.Proxy and an invocation-handler to store/retrieve the data from a node.
Could be an interesting approach. Please let's continue to work out a a way that is suitable for your problem.