2. • Using WebObjects since 2004
• Work with government agencies, private companies and various
foundations globally
• Fuego Content Management System & Fuego Frameworks
• Presence in North America and Middle East
Fuego History
3.
4. • 42% of community uses D2W
• “D2W is to WebObjects apps as the assembly line is to automobiles...you
provide customization directions (D2W rules) to the assembly line (D2W) to
build your end products (WOComponent pages).”
• Flow is controlled by delegates that manage the actions and direction of the
application
• Use ERDBranchDelegate to define the actions displayed on the page by rules
or via introspection
Direct To Web
7. Back in the day...
• Without Project Wonder, rely on nextPageDelegate and
nextPage for navigation
• nextPageDelegate is checked first, and if found call nextPage()
• without nextPageDelegate, nextPage() is called on the D2WPage
component directly
• Single class between each page
9. Plain WebObjects Controller Sample Code
public class ManageUserEditNextPageDelegate implements NextPageDelegate {
public WOComponent nextPage(WOComponent sender) {
NSArray<User> selectedObjects = ((ERDPickPageInterface) sender).selectedObjects();
User currentUser = selectedObjects.get(0);
EditPageInterface epi = (EditPageInterface) D2W.factory().pageForConfigurationNamed("ManageUsers_User_Edit_PC", sender.session());
epi.setNextPageDelegate(new ManageUserSaveNextPageDelegate());
epi.setObject(currentUser);
return (WOComponent) epi;
}
}
10. Enter Project Wonder
• ERDBranchDelegate to the rescue!
• Now you can show multiple branch choices for a page
• Pull choices from D2W context in the method
branchChoicesForContext(), using the D2W rule key
“branchChoices”
• Or, use introspection to find all methods that take a single
WOComponent as parameter
12. ERDBranchDelegate Sample Code
public class ManageUserControllerSelectBranchDelegate extends ERDBranchDelegate {
// Return an edit page for a single selected row in the pick page
public WOComponent edit(WOComponent sender) {
NSArray<User> selectedObjects = ((ERDPickPageInterface) sender).selectedObjects();
User currentUser = selectedObjects.get(0);
EditPageInterface epi = (EditPageInterface) D2W.factory().pageForConfigurationNamed("ManageUsers_User_Edit_PC", sender.session());
epi.setNextPageDelegate(new ManageUserControllerSaveBranchDelegate());
epi.setObject(currentUser);
return (WOComponent) epi;
}
// From the selected items in the pick page, perform a delete
public WOComponent delete(WOComponent sender) {
NSArray<User> users = ((ERDPickPageInterface) sender).selectedObjects();
for (User user : users) {
user.delete();
}
if (users.count() > 0) {
// Assuming all in same EC.
users.get(0).editingContext().saveChanges();
}
return sender.pageWithName("PageWrapper");
}
}
13. But wait...
• Must still set and get the
objects on each page
• Lots of classes to write
• Why not reuse the same
delegate?
14. Benefits of Delegate Reuse
• Enter the controller/delegate many times (one controller for
many pages)
• Reuse the stored state in editing context
• Support one or many flows within the single class
• Define the visible branches using rules
16. Is ERDBranchDelegate Enough?
• Yes....but...no.
• Branch choices are defined in the rules, but can lead to a
complex ruleset depending on the business logic
• Introspection on the ERDBranchDelegate returns all the
methods in the class
17. Hello (Stateful) World!
• FDStatefulController is a re-entrant branch delegate extending
ERDBranchDelegate
• Better separation of MVC
• Override branchChoicesForContext(D2WContext context)
• Reuse page configurations (define the PC in code)
• store state between pages
• editing context
• EOs, etc in subclasses
18. branchChoicesForContext
public class StatefulController extends ERDBranchDelegate {
private NSArray<?> branches;
private EOEditingContext editingContext;
public NSArray<?> getBranches() {
return branches;
}
public void setBranches(NSArray<?> branches) {
this.branches = branches;
}
public EOEditingContext editingContext() {
if (this.editingContext == null) {
this.editingContext = ERXEC.newEditingContext();
}
return this.editingContext;
}
public NSArray branchChoicesForContext(D2WContext context) {
NSArray choices = getBranches();
if (choices == null) {
branches = (NSArray) context.valueForKey(BRANCH_CHOICES);
} else {
NSMutableArray translatedChoices = new NSMutableArray();
for (Iterator iter = choices.iterator(); iter.hasNext();) {
... rest of method continues the same as ERDBranchDelegate
19. StatefulController Code
// Return an edit page for a single selected row in the pick page
public WOComponent edit(WOComponent sender) {
NSArray<User> selectedObjects = ((ERDPickPageInterface) sender).selectedObjects();
User currentUser = selectedObjects.get(0);
setBranches(new NSArray("save"));
EditPageInterface epi = (EditPageInterface) D2W.factory().pageForConfigurationNamed("ManageUsers_User_Edit_PC", sender.session());
epi.setNextPageDelegate(this);
epi.setObject(currentUser);
return (WOComponent) epi;
}
public WOComponent save(WOComponent sender) {
editingContext().saveChanges();
return sender.pageWithName("PageWrapper");
}
// From the selected items in the pick page, perform a delete
public WOComponent delete(WOComponent sender) {
setBranches(null);
NSArray<User> users = ((ERDPickPageInterface) sender).selectedObjects();
ERXUtilities.deleteObjects(editingContext(), users);
return save(sender);
}
23. Summary
• Re-entrant controller provides code reusability
• Specify branch choices programmatically
• Storing the editing context allows easy access to associated
objects during flows and encourages a single point of save
• Utility and convenience methods allow for simple setup and
development of customized flows
24. Resources
• What is Direct To Web?
http://wiki.wocommunity.org/pages/viewpage.action?pageId=1049018
• D2W Flow Control
http://wiki.wocommunity.org/display/documentation/D2W+Flow+Control
• ERDBranchDelegateInterface
http://jenkins.wocommunity.org/job/Wonder/lastSuccessfulBuild/javadoc/er/directtoweb/pages/
ERD2WPage.html#pageController()
• Page controller in ERD2W
http://osdir.com/ml/web.webobjects.wonder-disc/2006-05/msg00041.html