1 / 29

Orca: Order Recording/Customer Assets

Orca: Order Recording/Customer Assets. Technology Series gwl. Orca WorkUnits. A WorkUnit (WU) encapsulates a use-case. Each includes the: Screen navigation logic client-side business rules client-server communication for that use-case. Concept. Attach a WU (indirectly) to HTTP session.

nova
Télécharger la présentation

Orca: Order Recording/Customer Assets

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Orca: Order Recording/Customer Assets Technology Series gwl

  2. Orca WorkUnits A WorkUnit (WU) encapsulates a use-case. Each includes the: • Screen navigation logic • client-side business rules • client-server communication for that use-case

  3. Concept • Attach a WU (indirectly) to HTTP session. • It will instruct Tapestry to display the correct page, depending on its state. • It will interact with the pages in that requests are funneled into the WU via component bindings/Tapestry services.

  4. Concept • WorkUnit services treat the attached WU as king while attached, users may only operate on that use case until done. • WU is persisted between requests • an attached WU may voluntarily give up control to a sub-WU if its logic allows. • When done, a WU is detached from the session.

  5. Concept • When a sub-WU is detached, its parent regains control. • A WU may veto being detached or having a sub-WU attached. • WU’s delegate presentation tasks to Tapestry Pages/Components • Pages/Components are bound to the WU at runtime.

  6. Concept Tapestry Pages New Customer Order Pages WebServer WU • WU’s re-use pages Http Session Customer Search Page Visit Servlet Engine WU MaintainCustomer Pages

  7. Concept • Empower Java Developers • encapsulate the use-case in a single object • delegate presentation to the components that do it best (Tapestry components) • Make the use-case a component too! • Kill the “Back Button” problem (maybe)

  8. WorkUnit data structure • Page list • list of strings corresponding to pages defined in Tapestry app. • these are the pages this WU displays. • Child WU • Value is null at construction time • Value is set when a subWU is attached to this one • Value does not change if child is detached from this WU • Value is set to null when this WU is detached. • Parent WU • Value is valid when this WU is attached as a child of another • Value is null otherwise. • Note that while WU’s can be chained, it places a burden on the size of the serialized state of the engine. Design so that the chain is not too long at any one time.

  9. WU Structure (cont’d) • SavedPages- a stack of visited pages • CurrentPage • the Tapestry name of the page this WU is showing • changed by calling transition() • Dirty flag • Listener Map - described later

  10. NullWorkUnit (NWU) • Whenever no real WU is attached, NWU is automagically attached to the Visit • it’s a singleton, never GC’d • always allows itself to be detached • never allows other WU’s to be attached to it. • when NWU is in control, attachment will turf NWU, then directly attach the new WU to Visit

  11. WU Lifecycle Constructed • Construction • Attachment • Handle requests • Lose control • Regain control • Detachment/Cleanup Attachment Attached Attached (No Handle Requests) Lose Control Handle Requests Regain Control Detachment Detached (GC)

  12. Lifecycle in Detail

  13. Construction • Right now this is simple - no-arg constructors only • MyWorkUnit myNewWU = new MyWorkUnit();

  14. Attachment: • Attachment is made complex by Tapestry rewinding - we explain later. • Some code calls (in a page here): public void startWU(IRequestCycle cycle) throws IRequestCycleException { IWorkUnit myNewWU = new CoolWorkUnit(); IWorkUnitVisit visit = (IWorkUnitVisit)getEngine().getVisit(cycle); visit.attach(myNewWU, cycle); } • and the attachment process begins...

  15. Case 1: NullWU attached • The visit has the NWU instance attached. • NWU allows always allows itself to be detached. • This is the normal case when the user is not working a use-case, but wants to. • Step 1 • AttachDetach asks NWU if myNewWU can be attached to it. NWU always says NO! • Step 2 • since NWU said no, AttachDetach tries to detach NWU. NWU says yes, and is detached • Step 3 • AttachDetach attaches myNewWU is to the visit, and informs myNewWU of this (myNewWU.attached() ). myNewWU is now the current WU. • Step 4 • AttachDetach calls Visit.getWU().display(IRequestCycle cycle) - this triggers myNewWU to call cycle.setPage(getCurrentPage());// the page myNewWU wants to show • Step 2 is simplified above, AttachDetach actually tries to detach the current WU, its parent, and so on until the Visit has no WU. Any WU in the chain can veto this, and by so doing the vetoer regains control and becomes the current WU. But in this case NWU is the only one attached.

  16. Case 2: Attachment rejected • A WU (DirtyWorkUnit) is already attached. It will reject myNewWU as an attachment. ie, if DirtyWorkUnit didn’t want itself to be detached or any other WU to be attached to it because it has unsaved data. • Step 1 • AttachDetach asks DirtyWorkUnit if myNewWU can be attached to it. DirtyWorkUnit says NO because its dirty! • Step 2 • since DirtyWorkUnit said no, AttachDetach tries to detach DirtyWorkUnit . DirtyWorkUnit again says no, because it is dirty. • Step 3 • AttachDetach gives up and leaves DirtyWorkUnit as the current WU • Step 4 • AttachDetach calls Visit.getWU().display(IRequestCycle cycle) - this triggers DirtyWorkUnit to call cycle.setPage(getCurrentPage());// the page DirtyWorkUnit wants to show • Note that by being queried in Step 1 and 2 DirtyWorkUnit could change its state to display a “You have unsaved changes” page in Step 4

  17. Case 3: Attachment accepted • A WU (HappyWorkUnit) is already attached. It does not reject myNewWU as an attachment. • Step 1 • AttachDetach asks HappyWorkUnit if myNewWU can be attached to it. HappyWorkUnit says YES • Step 2 • AttacherDetacher set the parent field in myNewWU to HappyWorkUnit, the child field in HappyWorkUnit to myWorkUnit, notifies HappyWorkUnit that it has been detached, and notifies myWorkUnit that it has been attached to the visit. • End result is that HappyWorkUnit has lost control. • Step 3 • AttachDetach calls Visit.getWU().display(IRequestCycle cycle) - this triggers DirtyWorkUnit to call cycle.setPage(getCurrentPage());// the page DirtyWorkUnitwants to show • Note that when myNewWU is detached from the visit, HappyWorkUnit is automagically re-attached and regains control.

  18. Losing/Regaining Control • WU’s have control only as long as they are directly attached to the Visit • They lose control when detached. This will happen if the WU is removed altogether or if a child is attached to it. • They will regain control if a child WU was attached to it, and then all of its descendants are detached.

  19. Detachment • Anyone can request a WU be detached. Even the WU in control can detach itself (and should if its ‘done’). • As already described, WU’s can veto their detachment. If so the vetoer remains in control • Callers can only try to detach the WU in control, otherwise a CannotDetachException is thrown and the current WU remains in control • If the current WU is successfully detached and it had a parent, the parent regains control and that parent’s child field is *not* nulled out. Thus, the parent regaining control can examine the child’s state • If a WU has a detached child, its child field isn’t changed until a new child is attached in its place, or until the WU itself is detached. visit.detach(aWU)

  20. WorkUnit listenerMap • Work Units have listeners like pages and components. • WorkUnitListenerMap works like the existing Tapestry ListenerMap • instead of throwing ApplicationRuntimeException, it throws StaleLinkException • So, if a page was linked to method executeX() in WU1, but WU2 is in control, a StaleLinkException would be thrown if WU2 does not implement executeX() • It would be possible to provide our own Stale Link page that includes the option ‘return to last know state’. Then the WU in control could be triggered to re-display its current page. public void restoreWU(IRequestCycle cycle) throws RequestCycleException { IWorkUnitVisit visit = (IWorkUnitVisit)getVisit(); visit.getWorkUnit().display(cycle); }

  21. Problem: Tapestry Rewind • Need to defer attachment/detachment until after rewind is done. • Otherwise current WU state is not valid, it can’t reliably veto/allow an attachment/detachment request. • We defer requests for attachment/detachment by using an IMonitor on the Engine. • The monitor counts the rewinds and when the count drops back to 0, the AttacherDetacher is invoked

  22. Interface IWorkUnit • Attachment/Detachment • attach(IWorkUnit) throws CannotAttachException called to request parm WU be attached as child • attached(IWorkUnitVisit, IWorkUnit) called when this WU gains control • detach(IWorkUnit, IRequestCycle) throws CannotDetachException called to request this WU lose control • detached() called when this WU loses control

  23. IWorkUnit (cont’d) • Chaining support • getParentWU() • getChildWU() • Built-in listeners • cancel(IRequestCycle) throws RequestCycleException • done(IRequestCycle) throws RequestCycleException • Display Page support • display(IRequestCycle cycle) • Page dispatch logic • Additional query parameters to identify component • Ad-hoc code to "find" component, invoke methods • Similar code in each servlet or Action that includes component • Servlet / Action for component • Receives request, finds component in standardized way • Needs to be configured with page to render response

  24. Class AbstractWorkUnit • Base class for all except NWU • Implements IWorkUnit • includes basic functionality for pages, display, done and cancel • contains default behavior for attachment/detachment

  25. Class WizardWorkUnit • An abstract subclass for building wizards • extends AbstractWorkUnit • adds listeners for next, back, done • Adds methods Tapestry pages/components can use to enable/disable links/buttons. • isBackButtonDisabled • isNextButtonDisabled • isDoneButtonDisabled

  26. Using WU’s -> a Wizard • Refer to code for details • Defined Tapestry application: WizardTest.application • Engine class = WorkUnitEngine • Visit Class = WorkUnitTestVisit • Pages: • Home - contains a link to start the Wizard • WizardWelcome - first page

  27. Using WU’s -> a Wizard • Pages: • Home - has a link to launch wizard • WizardWelcome - has Next and Cancel buttons • FirstPage, SecondPage, ThirdPage - the pages for the wizard to collect name, phone, and email address each has Back, Next, Done, Cancel buttons. • WorkUnits • WizardTestWorkUnit - uses WizardWelcome + First/Second/Third pages

  28. Wizard - starting WU’s • Home has link that executes: public void launchWizard(IRequestCycle cycle) throws RequestCycleException { IWorkUnitVisit visit = IWorkUnitVisit)getEngine().getVisit(cycle); WizardTestWorkUnit wiz = new WizardTestWorkUnit(); visit.attach(wiz, cycle); } • Attachment eventually calls display() on the WU which shows the WizardWelcome page.

  29. Wizard - example bindings • FirstPage(.jwc) • has a text field + the buttons • Some bindings: <componentid="inputName"type="TextField"> <bindingname="value"property-path="engine.visit.workUnit.name"/> </component> <componentid="submitBack"type="Submit"> <bindingname="disabled"property-path="engine.visit.workUnit.backDisabled"/> <bindingname="listener"property-path="engine.visit.workUnit.listeners.back"/> </component>

More Related