PATH Documentation > WebObjects

Up Previous Next

Using Nested Editing Contexts

Synopsis

Describes how to use nested editing contexts as a working area for complex edit screens.

Discussion

EOEditingContexts can be viewed as working areas into which objects are fetched and modified. By default, every session is given its own defaultEditingContext as a means of separating different user's objects.

When changes are made to objects within an editing context, the editing context tracks the changes for future saving. When the editing context sends the message saveChanges , it hands off the changes to its parent EOObjectStore. Normally, the parent is the EOObjectStoreCoordinator which in turn hands off the changes to the appropriate EODatabaseContext for each entity. The EODatabaseContext then saves the changes to the database.

Since an EOEditingContext is itself an EOObjectStore, you can nest EOEditingContexts, thereby making different levels of working areas that can saveChanges to its parent level. With a little bit of effort, this feature of EOF can be used within WebObjects applications to provide scratch areas where users can make changes, submit forms, update enterprise objects, submit more forms, and then decide if all the changes should be saved to the session's defaultEditingContext or completely forgotten.

This more complicated approach to editing is necessary because the Web permits users to edit on a special edit page and, without saving or canceling, hyperlink directly to another page, leaving the defaultEditingContext with incomplete or inconsistent enterprise objects. This action can be disastrous unless care is taken to prevent the partial or undesired changes from being saved by accident.

To better illustrate this issue, assume you create a special object edit page that uses multiple Submit buttons to switch between sections of data to be edited. Also, assume that the WOTextfields, WOPopuplists, and so on, are bound directly to the object via key paths. As soon as you edit the data on the first section, and switch to see the data on a different section, the object will be changed to reflect any changes you made in the first section. Assume further that the user clicks a hyperlink in a different frame and jumps to a completely different screen. The user subsequently edits another object and finishes by selecting the Save button. The changes from the first edit screen will also be applied to the database! This is undesirable because the user never acknowledged a save for those changes.

There are two possible ways to work around this problem.

  1. Create a temporary instance variable for every data element that might be changed. Initialize the temporary variables upon entering the edit page. Update the real variables only during the actual saveChanges action.
  2. Create a nested EOEditingContext and fault in the object to be edited. The relationships will automatically be faulted into this temporary nested work area as needed. Bind the new editing instance of the object directly to the page's components. When saveChanges is invoked on the temporary EOEditingContext, the changes will be applied to the session's defaultEditingContext . To apply them to the database, you can invoke saveChanges to the session's defaultEditingContext , after which you can destroy the object and the temporary EOEditingContext.

We discuss the second approach. The techniques presented here can be used to build a reusable framework that manages the nested editing contexts without doubly-nesting them.

Creating the Nested EOEditingContext

The following code creates a nested editing context.

Java Code

 
EOEditingContext ec=session().defaultEditingContext(); 
EOEditingContext nestedEditingContext=new EOEditingContext(ec);

Objective-C Code

 
EOEditingContext *ec=[[self session] defaultEditingContext]; 
EOEditingContext *nestedEditingContext=[[EOEditingContext alloc] initWithParentObjectStore:ec];

Faulting the Original EO into the Nested EOEditingContext

Using the new convenience API from EOUtilities

Java Code

 
EOEnterpriseObject editingObject=(EOEnterpriseObject) EOUtilities.localInstanceOfObject (nestedEditingContext, objectToEdit);

Using the standard API

Java Code

 
EOGlobalID gid=objectToEdit.editingContext().globalIDForObject(objectToEdit); 
EOEnterpriseObject editingObject=nestedEditingContext.faultForGlobalID(gid, nestedEditingContext);

Using the new convenience API from EOUtilities

Objective-C Code

 
id editingObject=[nestedEditingContext localInstanceOfObject: objectToEdit];

Using the standard API

Objective-C Code

 
gid=[[objectToEdit editingContext] globalIDForObject: objectToEdit]; 
id editingObject=[nestedEditingContext faultForGlobalID: gid editingContext: nestedEditingContext];

Saving All the Changes to the Database

The following code saves the changes to a nested editing context.

Java Code

 
try { 
     nestedEditingContext.saveChanges(); 
     session().defaultEditingContext().saveChanges(); 
} 
catch (EOValidationException e) { // handle save error 

Objective-C Code

 
NS_DURING 
     [ nestedEditingContext saveChanges]; 
     [[[self session] defaultEditingContext] saveChanges]; 
NS_HANDLER // handle save error and the exception in variable localException 
NS_ENDHANDLER

WebScript Code

 
NSException *e=[nestedEditingContext tryToSaveChanges]; 
     if  (!e) 
     e=[[[self session] defaultEditingContext] saveChanges]; 
     if (e) { 
     // handle save error and the exception in variable e 
}

Issues to Consider

You should consider the following issues:

See Also

Questions

Keywords

Revision History

24 July, 1998. David Scheck. First Draft.
18 November, 1998. Clif Liu. Second Draft.


© 1999 Apple Computer, Inc.

Up Previous Next