Hi Lorenzo, Certainly, this would work from a technical perspective. However, it is absolutely not right for the problem. For a variety of reasons, Domain and Element need to have a completely unowned relationship. I'll explain some of my high-level situation:
The Domain will be administered by a DomainAdministrator. This will be either me, or someone personally known to me. For security reasons, the DomainAdministrator has *no access* to the Elements that "belong" to the Domain. The DomainAdministrator will also assign authenticated users to what we can, for now, call the ElementAdministrator role. An ElementAdministrator has access to administer Elements within the context of assigned Domains. There may be thousands of Elements within a single Domain. At no time should all the Elements within a Domain ever be selected in a single operation. There would be no point! Also, the security model I've designed will fragment Elements further such that a User who is a member of the Domain will have access to only some of the Elements in that Domain. In fact, one of the primary reasons I'm building the Element the way I am is that Elements will be part of the fine-grained security model itself. If a particular piece of data is selected in the system, I need to check the user's profile's security elements against the security elements baked into the data. This would necessitate a datastore check, possibly in the middle of a transaction. If I have to manually twig the transaction on or off because of entity groups, I'm defeating years of conventional wisdom on "separation of concerns". I've designed my architecture the way I always have -- I want to be able to bring on junior developers who don't have to make decisions on low-level things like transactions and security. To separate this concern, I'm using the extremely nice @Transactional annotation within spring. If any service that inherits from my base entity service interface is called on its "update()" method, for instance, I want the whole thing to be transactional. It deeply pains me that I could easily build this kind of a separated-concern solution ten years ago with clunky hand-built libraries for a Weblogic production environment, but I can't do it in 2010 with Google App Engine. The fundamental problem with the concept of the entity group as a restriction on transactional operations is that it mandates a hierarchy on all operations. To be part of the entity group and thence any operation in the transaction, it says, there must be a hard- and-fast "owned" relationship between the entities. This looks very nice on paper, but the problem is that if you're modelling the real world, real world entities do not have nice hierarchical relationships. For a very nice explanation of why this is a very serious problem in solution design, see Christopher Alexander's classic "A City Is Not A Tree" (it's available online for free). I've hacked around this for now, with a ten pound sledge hammer and a rusty hacksaw. Using spring interceptors, I've built in an "extra- transactional check" layer around my services, outside the aegis of the transactional advisor. This is highly unsatisfactory because now my developers are going to have to keep track of what is, and what isn't part of the transaction. The concern is no longer neatly separated. This is de-evolution. I absolutely love what leap forward Google App Engine represents in terms of building applications. OTOH, the restrictions of entity groups on transaction is a very real obstacle to building "serious" business applications! Thanks, - Bill On Jul 26, 3:22 am, "l.denardo" <[email protected]> wrote: > As far as I know there are two possible solutions: > > *Review the architecture inserting Elements as a list property of your > domain, something like > > @PersistenceCapable > class Domain{ > private ArrayList<Element> elements; > > } > > This works correctly and you get the benefit to have a cascasing > delete on elements when you delete the Domain they're part of. > This does not seem to have significant drawbacks, as documentation > says somewhere Elements are fetched from datastore only if you access > the list, and not if you just read the Domain without actually going > thru the list. > Elements are also queriable without reading the actual Domain they're > in. > The only thing this architecture seems to impede is finding the domain > an element belongs to, given the element, without having complex > iterations. > > * Check if domain exists outside the transaction. > If your domains are not deleted during an Element insert this should > work. > > I've gone the first path for my application and benefits in terms of > code complexity and maintenance have been worth the effort, anyway it > depends on your business logic if that can be right. > > Regards > Lorenzo > > On Jul 24, 4:04 pm, Bill <[email protected]> wrote: > > > > > Hello, > > > I'm quite frustrated with entity groups. They seem to make the > > concept of a transaction largely pointless. > > > The specific problem I face at this moment is this. Since the > > datastore has no concept of foreign key constraints, I need to do > > bounds checking. Here's the case: > > > There exists a Domain type, and an Element type. An Element requires > > a reference to a pre-existing Domain in order to function, per my > > business rules. Domains exist independently of Elements, and are > > administered separately. I would characterize their relationship as > > "Element has a reference to a required Domain's primary key" rather > > than "Element is a child of Domain". > > > When creating an Element, I need to check that the reference to the > > assigned Domain is not bogus. I do this in my service layer, which is > > also where I want to determine transactionality. > > > The algorithm goes like this: > > > * start transaction. Per my current architecture I cannot start this > > transaction any later without creating an entirely new non- > > transactional business delegate layer that feels like absolute > > overkill. > > * retrieve Domain by key. If no such Domain is found, throw an error > > * insert Element > > * commit > > > Unfortunately, this causes the dreaded "can't operate on multiple > > entity groups in a single transaction" exception. I'm absolutely > > hornswaggled by this, since I'm not "operating" on the Domain. I just > > want to check that it exists! If this were a destructive change I > > were making, I'd kind of -- barely -- see the argument here, but why > > on earth is this a problem? Am I missing something? -- You received this message because you are subscribed to the Google Groups "Google App Engine for Java" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/google-appengine-java?hl=en.
