Author: rich Date: Fri Aug 19 16:10:24 2005 New Revision: 233572 URL: http://svn.apache.org/viewcvs?rev=233572&view=rev Log: First crack at docs for Page Flow inheritance.
tests: validate in docs/forrest/release Added: beehive/trunk/docs/forrest/release/src/documentation/content/xdocs/pageflow/pageflow_inheritance.xml (with props) Added: beehive/trunk/docs/forrest/release/src/documentation/content/xdocs/pageflow/pageflow_inheritance.xml URL: http://svn.apache.org/viewcvs/beehive/trunk/docs/forrest/release/src/documentation/content/xdocs/pageflow/pageflow_inheritance.xml?rev=233572&view=auto ============================================================================== --- beehive/trunk/docs/forrest/release/src/documentation/content/xdocs/pageflow/pageflow_inheritance.xml (added) +++ beehive/trunk/docs/forrest/release/src/documentation/content/xdocs/pageflow/pageflow_inheritance.xml Fri Aug 19 16:10:24 2005 @@ -0,0 +1,280 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V2.0//EN" + "http://forrest.apache.org/dtd/document-v20.dtd"> +<document> + <header> + <title>Page Flow Inheritance</title> + </header> + <body> + <section id="intro"> + <title>Introduction</title> + <p> + Page Flow inheritance is a powerful way to share actions, exception handlers, state, etc. among + controller classes. The basic idea is simple: you use normal Java inheritance to share pieces + of controller classes. This document shows ways in which you might use the feature, and also shows + areas that go beyond what you might expect from standard Jave inheritance. + </p> + </section> + <section id="basic"> + <title>Basic Inheritance</title> + <section id="inheritingMembers"> + <title>Inheriting Plain Members</title> + <p> + If you derive from a base class, you inherit all its public/protected member variables and methods. + Just as usual. + </p> + </section> + <section id="inheritingAnnotatedMembers"> + <title>Inheriting Annotated Members</title> + <p> + If you derive from a base class, then you inherit all its public/protected <em>annotated</em> + members, like action methods (<code>@Jpf.Action</code>), exception handlers + (<code>@Jpf.ExceptionHandler</code>), or shared flow fields (<code>@Jpf.SharedFlowField</code>). + This is not surprising, but it is important to point out. Inheriting an action method means that + you <em>inherit the action</em>. In the following example, <code>DerivedFlow</code> inherits its + <code>begin</code> action from <code>BaseFlow</code>. + </p> + <source> +package base; +... [EMAIL PROTECTED] +public class BaseFlow extends PageFlowController +{ + @Jpf.Action( + forwards={ + @Jpf.Forward(name="index", path="index.jsp") + } + ) + public Forward begin() + { + return new Forward("index"); + } +} </source> + <source> +package derived; +... [EMAIL PROTECTED] +public class DerivedFlow extends BaseFlow +{ +} </source> + <p> + As usual, hitting /derived/DerivedFlow.jpf in your browser will execute the <code>begin</code> + action on <code>DerivedFlow</code>. In this case, it executes the <em>inherited</em> + <code>begin</code> action. Pretty simple. + </p> + <note> + You may have noticed that "index.jsp" is a local path, and you may have wondered whether hitting + /derived/DerivedFlow.jpf will take you to /base/index.jsp or /derived/index.jsp. The page flow can + actually be configured to work either way; see <a class="jump" href="#paths">Local Paths</a>, below. + </note> + </section> + <section id="inheritingControllerAnnotation"> + <title>Inheriting the <code>@Jpf.Controller</code> annotation</title> + <p> + When you extend a base class controller, you inherit its <code>@Jpf.Controller</code> annotation + in a special way: it is <em>merged</em> with the <code>@Jpf.Controller</code> annotation on your + derived class. Here is a very simple example: + </p> + <source> +package base; +... [EMAIL PROTECTED](nested=true) +public class BaseFlow extends PageFlowController +{ + ... +} </source> + <source> +package derived; +... [EMAIL PROTECTED]( + simpleActions={ + @Jpf.SimpleAction(name="begin", path="index.jsp") + } +) +public class DerivedFlow extends BaseFlow +{ +} </source> + <p> + The controller <code>DerivedFlow</code> inherits <code>nested=true</code> from the base class, and + still keeps its <code>simpleActions</code>. It is as if <code>DerivedFlow</code> defined the + following <code>@Jpf.Controller</code> annotation: + </p> + <source> [EMAIL PROTECTED]( + nested=true, + simpleActions={ + @Jpf.SimpleAction(name="begin", path="index.jsp") + } +) </source> + <p> + A more common example involves merging of arrays of annotations, like <code>@Jpf.SimpleAction</code> + or <code>@Jpf.Forward</code>. In the following example, <code>ChildFlow</code> inherits the + simple action <code>baseAction</code> and a catch for <code>LoginException</code>. + </p> + <source> +package parent; +... [EMAIL PROTECTED]( + simpleActions={ + @Jpf.SimpleAction(name="begin", path="page1.jsp"), + @Jpf.SimpleAction(name="baseAction", navigateTo=Jpf.NavigateTo.previousPage) + }, + catches={ + @Jpf.Catch(type=LoginException.class, path="loginError.jsp") + } +) +public class ParentFlow extends PageFlowController +{ +} </source> + <source> +package child; +... [EMAIL PROTECTED]( + simpleActions={ + @Jpf.SimpleAction(name="begin", path="index.jsp") + }, + catches={ + @Jpf.Catch(type=Exception.class, path="error.jsp") + } +) +public class ChildFlow extends ParentFlow +{ +} </source> + <p> + It is as if <code>ChildFlow</code> was defined with the following <code>@Jpf.Controller</code> + annotation: + </p> + <source> [EMAIL PROTECTED]( + simpleActions={ + @Jpf.SimpleAction(name="begin", path="index.jsp"), + @Jpf.SimpleAction(name="baseAction", navigateTo=Jpf.NavigateTo.previousPage) + }, + catches={ + @Jpf.Catch(type=LoginException.class, path="loginError.jsp"), + @Jpf.Catch(type=Exception.class, path="error.jsp") + } +) </source> + <p> + The basic rule is that attributes (e.g, <code>nested=true</code>) are inherited, while arrays + (e.g., <code>simpleActions={...}</code> are inherited and merged. + </p> + </section> + </section> + <section id="advanced"> + <title>Advanced Inheritance</title> + <section id="overriding"> + <title>Overriding</title> + <p> + You may have noticed from the <code>ParentFlow</code>/<code>ChildFlow</code> example above that + the <code>begin</code> action in <code>ChildFlow</code> overrode the one in <code>ParentFlow</code>. + The simple rule is that any annotation or attribute within your <code>@Jpf.Controller</code> + will override one of the same name/type in the base class. In the following example, the + <code>@Jpf.Catch</code> for <code>LoginException</code> is overridden in <code>DerivedFlow</code>. + </p> + <source> +package base; +... [EMAIL PROTECTED]( + catches={ + @Jpf.Catch(type=LoginException.class, path="loginError.jsp") + } +) +public class BaseFlow extends PageFlowController +{ +} </source> + <source> +package derived; +... [EMAIL PROTECTED]( + catches={ + @Jpf.Catch(type=LoginException.class, method="handleLoginException") + } +) +public class DerivedFlow extends BaseFlow +{ + @Jpf.ExceptionHandler( + forwards={ + @Jpf.Forward(name="errorPage", path="error.jsp") + } + ) + public Forward handleLoginException(LoginException ex, String actionName, String message, Object formBean) + { + ... + return new Forward("errorPage"); + } +} </source> + </section> + <section id="abstract"> + <title>Abstract base classes</title> + <p> + If you make your base controller class <code>abstract</code>, then you are free from some usual + restrictions: + </p> + <ul> + <li>Even if it is a page flow controller, it does not need to have a <code>begin</code> action.</li> + <li> + Even if it has <code>nested=true</code> in <code>@Jpf.Controller</code>, it does not have to + have at least one <code>@Jpf.Forward</code> or <code>@Jpf.SimpleAction</code> with a + <code>returnAction</code> attribute. This would normally be required. + </li> + <li> + If you have a local path (e.g., "index.jsp", which does not start with "/"), you will + <em>not</em> receive a warning if the file does not exist. A derived page flow may have a + local file with this name. + </li> + <li> + It is not required to have the <code>@Jpf.Controller</code> annotation. + </li> + </ul> + </section> + </section> + <section id="paths"> + <title>Local Paths</title> + <p> + In a derived controller class, you may inherit an action that forwards to a local path (a path that + does not begin with a "/"). In the following example, <code>DerivedFlow</code> inherits a + <code>begin</code> action that forwards to "index.jsp": + </p> + <source> +package base; +... [EMAIL PROTECTED]( + simpleActions={ + @Jpf.SimpleAction(name="begin", path="index.jsp") + } +) +public class BaseFlow extends PageFlowController +{ +} </source> + <source> +package derived; +... [EMAIL PROTECTED] +public class DerivedFlow extends BaseFlow +{ +} </source> + <p> + If you hit /derived/DerivedFlow.jpf, where do you end up? /base/index.jsp or /derived/index.jsp? + By default, you end up at /derived/index.jsp; the local path is relative to the current page flow + (/derived/DerivedFlow.jpf). You can change this behavior, though, by setting + <code>inheritLocalPaths=true</code> in your derived class's <code>@Jpf.Controller</code> annotation, + e.g., + </p> + <source> +package derived; +... [EMAIL PROTECTED](<strong>inheritLocalPaths=true</strong>) +public class DerivedFlow extends BaseFlow +{ +} </source> + <p> + Now, if you hit /derived/DerivedFlow.jpf, you will see the content of /base/index.jsp. + </p> + <note> + Even when <code>inheritLocalPaths=true</code>, you won't leave (destroy) the current page flow by + going to a path that's inherited from a base class. + </note> + </section> + </body> +</document> \ No newline at end of file Propchange: beehive/trunk/docs/forrest/release/src/documentation/content/xdocs/pageflow/pageflow_inheritance.xml ------------------------------------------------------------------------------ svn:eol-style = native