SlideShare una empresa de Scribd logo
1 de 25
Descargar para leer sin conexión
D2W Stateful Controllers
Fuego Digital Media QSTP-LLC
Daniel Roy
• 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
• 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
The Basics
query select edit save
Start/Stop
Confirm
Edit
Confirm
Confirm
saveForLater
Save
Delete
edit
Edit CommentreadyToSubmit*
readyToSubmit*
saveAndSubmit
Submit
delete*
confirmDeletion
approveDeletion
confirm
edit*
List Expense
Claims
select
cancel
Notes:
- Cancel is present on all pages, but only
shown for first.
- Any branches with * are optional
and are shown based on business logic
- Any branches with the same name,
are the same page configuration, but
with different branches
Needs to enter
comment?
NO
Edit Comment
YES
WHAT?
WHAT???
??
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
Next Page Delegate
D2WPage
NPD
(select)
D2WPage
NPD
(edit)
D2WPage
NPD
(query)
...
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;
	 }
}
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
ERDBranchDelegate
D2WPage ERDBD
D2WPage
(search)
D2WPage
(add)
D2WPage
(cancel)
ERDBD
D2WPage
(save)
D2WPage
(cancel)
D2WPage
(add)
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");
	 }
}
But wait...
• Must still set and get the
objects on each page
• Lots of classes to write
• Why not reuse the same
delegate?
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
Re-entrant Branch Delegate
D2WPageBD
queryPage
search()
edit()
editPage
selectPage
save()
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
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
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
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);
}
Page Utility Methods
Interaction
editPage
queryPage
listPage
inspectPage
messagePage
pickPage
selectPage
Utility
editingContext()
nestedEditingContext
save()
Utility Method Examples
protected EditPageInterface editPage(Session session, String pageConfigurationName, EOEnterpriseObject enterpriseObject) {
	 EditPageInterface epi = (EditPageInterface) pageForConfigurationNamed(pageConfigurationName, session);
	 epi.setNextPageDelegate(this);
	 epi.setObject(enterpriseObject);
	 return epi;
}
protected WOComponent pageForConfigurationNamed(String pageConfigurationName, Session session) {
	 WOComponent component = D2W.factory().pageForConfigurationNamed(pageConfigurationName, session);
	 if (component instanceof D2WPage) {
	 	 ((D2WPage) component).setNextPageDelegate(this);
	 }
	 return component;
}
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
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
Q&A

Más contenido relacionado

La actualidad más candente

Apache Cayenne for WO Devs
Apache Cayenne for WO DevsApache Cayenne for WO Devs
Apache Cayenne for WO Devs
WO Community
 
D2W Branding Using jQuery ThemeRoller
D2W Branding Using jQuery ThemeRollerD2W Branding Using jQuery ThemeRoller
D2W Branding Using jQuery ThemeRoller
WO Community
 

La actualidad más candente (20)

COScheduler
COSchedulerCOScheduler
COScheduler
 
.Net template solution architecture
.Net template solution architecture.Net template solution architecture
.Net template solution architecture
 
[2015/2016] JavaScript
[2015/2016] JavaScript[2015/2016] JavaScript
[2015/2016] JavaScript
 
Apache Cayenne for WO Devs
Apache Cayenne for WO DevsApache Cayenne for WO Devs
Apache Cayenne for WO Devs
 
HTML5 and CSS3 refresher
HTML5 and CSS3 refresherHTML5 and CSS3 refresher
HTML5 and CSS3 refresher
 
D2W Branding Using jQuery ThemeRoller
D2W Branding Using jQuery ThemeRollerD2W Branding Using jQuery ThemeRoller
D2W Branding Using jQuery ThemeRoller
 
ZZ BC#7.5 asp.net mvc practice and guideline refresh!
ZZ BC#7.5 asp.net mvc practice  and guideline refresh! ZZ BC#7.5 asp.net mvc practice  and guideline refresh!
ZZ BC#7.5 asp.net mvc practice and guideline refresh!
 
Staying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHPStaying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHP
 
Java EE revisits design patterns
Java EE revisits design patternsJava EE revisits design patterns
Java EE revisits design patterns
 
Getting Started with jQuery
Getting Started with jQueryGetting Started with jQuery
Getting Started with jQuery
 
[2015/2016] Backbone JS
[2015/2016] Backbone JS[2015/2016] Backbone JS
[2015/2016] Backbone JS
 
Real World MVC
Real World MVCReal World MVC
Real World MVC
 
Spring data jpa
Spring data jpaSpring data jpa
Spring data jpa
 
Staying Sane with Drupal (A Develper's Survival Guide)
Staying Sane with Drupal (A Develper's Survival Guide)Staying Sane with Drupal (A Develper's Survival Guide)
Staying Sane with Drupal (A Develper's Survival Guide)
 
Introduction to JavaScript
Introduction to JavaScriptIntroduction to JavaScript
Introduction to JavaScript
 
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...
 
Deep Dive: Alfresco Core Repository (... embedded in a micro-services style a...
Deep Dive: Alfresco Core Repository (... embedded in a micro-services style a...Deep Dive: Alfresco Core Repository (... embedded in a micro-services style a...
Deep Dive: Alfresco Core Repository (... embedded in a micro-services style a...
 
How to Write Custom Modules for PHP-based E-Commerce Systems (2011)
How to Write Custom Modules for PHP-based E-Commerce Systems (2011)How to Write Custom Modules for PHP-based E-Commerce Systems (2011)
How to Write Custom Modules for PHP-based E-Commerce Systems (2011)
 
Asp.Net MVC 5 in Arabic
Asp.Net MVC 5 in ArabicAsp.Net MVC 5 in Arabic
Asp.Net MVC 5 in Arabic
 
Spring Web Service, Spring Integration and Spring Batch
Spring Web Service, Spring Integration and Spring BatchSpring Web Service, Spring Integration and Spring Batch
Spring Web Service, Spring Integration and Spring Batch
 

Destacado (14)

Reenabling SOAP using ERJaxWS
Reenabling SOAP using ERJaxWSReenabling SOAP using ERJaxWS
Reenabling SOAP using ERJaxWS
 
Build and deployment
Build and deploymentBuild and deployment
Build and deployment
 
Using Nagios to monitor your WO systems
Using Nagios to monitor your WO systemsUsing Nagios to monitor your WO systems
Using Nagios to monitor your WO systems
 
Chaining the Beast - Testing Wonder Applications in the Real World
Chaining the Beast - Testing Wonder Applications in the Real WorldChaining the Beast - Testing Wonder Applications in the Real World
Chaining the Beast - Testing Wonder Applications in the Real World
 
Filtering data with D2W
Filtering data with D2W Filtering data with D2W
Filtering data with D2W
 
Migrating existing Projects to Wonder
Migrating existing Projects to WonderMigrating existing Projects to Wonder
Migrating existing Projects to Wonder
 
WOver
WOverWOver
WOver
 
iOS for ERREST
iOS for ERRESTiOS for ERREST
iOS for ERREST
 
Advanced Apache Cayenne
Advanced Apache CayenneAdvanced Apache Cayenne
Advanced Apache Cayenne
 
iOS for ERREST - alternative version
iOS for ERREST - alternative versioniOS for ERREST - alternative version
iOS for ERREST - alternative version
 
High availability
High availabilityHigh availability
High availability
 
Deploying WO on Windows
Deploying WO on WindowsDeploying WO on Windows
Deploying WO on Windows
 
KAAccessControl
KAAccessControlKAAccessControl
KAAccessControl
 
"Framework Principal" pattern
"Framework Principal" pattern"Framework Principal" pattern
"Framework Principal" pattern
 

Similar a D2W Stateful Controllers

Controllers & actions
Controllers & actionsControllers & actions
Controllers & actions
Eyal Vardi
 
Vs2010and Ne Tframework
Vs2010and Ne TframeworkVs2010and Ne Tframework
Vs2010and Ne Tframework
KulveerSingh
 
phpWebApp presentation
phpWebApp presentationphpWebApp presentation
phpWebApp presentation
Dashamir Hoxha
 

Similar a D2W Stateful Controllers (20)

ReactJS - A quick introduction to Awesomeness
ReactJS - A quick introduction to AwesomenessReactJS - A quick introduction to Awesomeness
ReactJS - A quick introduction to Awesomeness
 
Controllers & actions
Controllers & actionsControllers & actions
Controllers & actions
 
Conductor vs Fragments
Conductor vs FragmentsConductor vs Fragments
Conductor vs Fragments
 
Asp.Net MVC Framework Design Pattern
Asp.Net MVC Framework Design PatternAsp.Net MVC Framework Design Pattern
Asp.Net MVC Framework Design Pattern
 
SFDC UI - Introduction to Visualforce
SFDC UI -  Introduction to VisualforceSFDC UI -  Introduction to Visualforce
SFDC UI - Introduction to Visualforce
 
React.js: You deserve to know about it
React.js: You deserve to know about itReact.js: You deserve to know about it
React.js: You deserve to know about it
 
Rails vs Web2py
Rails vs Web2pyRails vs Web2py
Rails vs Web2py
 
ASP .net MVC
ASP .net MVCASP .net MVC
ASP .net MVC
 
Rest web service_with_spring_hateoas
Rest web service_with_spring_hateoasRest web service_with_spring_hateoas
Rest web service_with_spring_hateoas
 
Introduction to React JS for beginners
Introduction to React JS for beginners Introduction to React JS for beginners
Introduction to React JS for beginners
 
Nuxeo World Session: Layouts and Content Views
Nuxeo World Session: Layouts and Content ViewsNuxeo World Session: Layouts and Content Views
Nuxeo World Session: Layouts and Content Views
 
ReactJS
ReactJSReactJS
ReactJS
 
Advance java session 5
Advance java session 5Advance java session 5
Advance java session 5
 
Zend framework
Zend frameworkZend framework
Zend framework
 
Vs2010and Ne Tframework
Vs2010and Ne TframeworkVs2010and Ne Tframework
Vs2010and Ne Tframework
 
phpWebApp presentation
phpWebApp presentationphpWebApp presentation
phpWebApp presentation
 
Patterns Are Good For Managers
Patterns Are Good For ManagersPatterns Are Good For Managers
Patterns Are Good For Managers
 
Do iOS Presentation - Mobile app architectures
Do iOS Presentation - Mobile app architecturesDo iOS Presentation - Mobile app architectures
Do iOS Presentation - Mobile app architectures
 
Developing ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller PatternDeveloping ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller Pattern
 
Parallelminds.web partdemo
Parallelminds.web partdemoParallelminds.web partdemo
Parallelminds.web partdemo
 

Más de WO Community (11)

Localizing your apps for multibyte languages
Localizing your apps for multibyte languagesLocalizing your apps for multibyte languages
Localizing your apps for multibyte languages
 
WOdka
WOdkaWOdka
WOdka
 
ERGroupware
ERGroupwareERGroupware
ERGroupware
 
CMS / BLOG and SnoWOman
CMS / BLOG and SnoWOmanCMS / BLOG and SnoWOman
CMS / BLOG and SnoWOman
 
Using GIT
Using GITUsing GIT
Using GIT
 
Persistent Session Storage
Persistent Session StoragePersistent Session Storage
Persistent Session Storage
 
Back2 future
Back2 futureBack2 future
Back2 future
 
WebObjects Optimization
WebObjects OptimizationWebObjects Optimization
WebObjects Optimization
 
Dynamic Elements
Dynamic ElementsDynamic Elements
Dynamic Elements
 
Practical ERSync
Practical ERSyncPractical ERSync
Practical ERSync
 
ERRest: the Basics
ERRest: the BasicsERRest: the Basics
ERRest: the Basics
 

Último

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Último (20)

A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 

D2W Stateful Controllers

  • 1. D2W Stateful Controllers Fuego Digital Media QSTP-LLC Daniel Roy
  • 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
  • 6. Start/Stop Confirm Edit Confirm Confirm saveForLater Save Delete edit Edit CommentreadyToSubmit* readyToSubmit* saveAndSubmit Submit delete* confirmDeletion approveDeletion confirm edit* List Expense Claims select cancel Notes: - Cancel is present on all pages, but only shown for first. - Any branches with * are optional and are shown based on business logic - Any branches with the same name, are the same page configuration, but with different branches Needs to enter comment? NO Edit Comment YES WHAT? WHAT??? ??
  • 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); }
  • 21. Utility Method Examples protected EditPageInterface editPage(Session session, String pageConfigurationName, EOEnterpriseObject enterpriseObject) { EditPageInterface epi = (EditPageInterface) pageForConfigurationNamed(pageConfigurationName, session); epi.setNextPageDelegate(this); epi.setObject(enterpriseObject); return epi; } protected WOComponent pageForConfigurationNamed(String pageConfigurationName, Session session) { WOComponent component = D2W.factory().pageForConfigurationNamed(pageConfigurationName, session); if (component instanceof D2WPage) { ((D2WPage) component).setNextPageDelegate(this); } return component; }
  • 22.
  • 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
  • 25. Q&A