Author: steveh Date: Wed Jan 12 08:39:01 2005 New Revision: 124973 URL: http://svn.apache.org/viewcvs?view=rev&rev=124973 Log: Adding exception handling section to page flow docs. Added: incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-login-form.dia (contents, props changed) incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-login-form.png (contents, props changed) Modified: incubator/beehive/trunk/docs/forrest/src/documentation/content/xdocs/pageflow/pageflow_controllers.xml incubator/beehive/trunk/docs/forrest/src/documentation/content/xdocs/pageflow/pageflow_overview.xml incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-exception-handling.dia incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-exception-handling.png incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1.dia incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1.png
Modified: incubator/beehive/trunk/docs/forrest/src/documentation/content/xdocs/pageflow/pageflow_controllers.xml Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/docs/forrest/src/documentation/content/xdocs/pageflow/pageflow_controllers.xml?view=diff&rev=124973&p1=incubator/beehive/trunk/docs/forrest/src/documentation/content/xdocs/pageflow/pageflow_controllers.xml&r1=124972&p2=incubator/beehive/trunk/docs/forrest/src/documentation/content/xdocs/pageflow/pageflow_controllers.xml&r2=124973 ============================================================================== --- incubator/beehive/trunk/docs/forrest/src/documentation/content/xdocs/pageflow/pageflow_controllers.xml (original) +++ incubator/beehive/trunk/docs/forrest/src/documentation/content/xdocs/pageflow/pageflow_controllers.xml Wed Jan 12 08:39:01 2005 @@ -68,37 +68,6 @@ } </source> <p></p> -<!-- -<p> - Finally, each controller class must contain a method that is -</p> -<ol> - <li>named <code>begin</code></li> - <li>returns a <code>org.apache.beehive.netui.pageflow.Forward</code> object</li> - <li>is decorated with the <code>@Jpf.Action</code> annotation</li> -</ol> -<source> -import org.apache.beehive.netui.pageflow.PageFlowController; -import org.apache.beehive.netui.pageflow.annotations.Jpf; -<strong>import org.apache.beehive.netui.pageflow.Forward;</strong> - [EMAIL PROTECTED] -public class Controller - extends PageFlowController -{ -<strong> @Jpf.Action - Forward begin() - { - return new Forward(); - }</strong> -} -</source> - <p> - The <code>@Jpf.Action</code> annotation marks the <code>begin()</code> method as an <em>action</em> method. - Action s - </p> ---> - <p> Now we have the beginnings of a controller implementation. </p> @@ -129,7 +98,9 @@ <p><strong>Simple Actions</strong> are class-level annotations, that is, annotations that decorate the controller class. (You can also think of simple actions as <em>configurations</em> - of the controller class.) Syntactically they appear as follows:</p> + of the controller class. If you are familiar with Struts, it might help you to know that + simple actions turn into <code><action></code> elements in the struts-config.xml file that is + automatically generated when a controller class is compiled.) Syntactically they appear as follows:</p> <source>@Jpf.Controller( <strong>simpleActions={ @@ -151,7 +122,9 @@ actions: that is, they can navigate users around the Page Flow, handle form submissions, validate form data, handle decision logic, etc. (You can also think of the action methods as <em>configurations</em> of individual methods, in contrast to simple actions, which configure the - entire class.) Syntactically speaking, an action method is a Java method that + entire class. Again, if you are familiar with Struts, know that + action methods, just like simple actions, are complied as <code><action></code> elements in the + struts-config.xml file.) Syntactically speaking, an action method is a Java method that (1) returns the type <code>org.apache.beehive.netui.pageflow.Forward</code> and (2) is decorated with the <code>@Jpf.Action/@Jpf.Forward</code> annotations:</p> @@ -168,27 +141,24 @@ <section> <title>Simple Actions</title> <p> - For the time being, we are going to imagine that our five actions are purely navigational, and, as such, + Two of our five actions are purely navigational, and, as such, implementable as simple actions. - Of course, some of these actions will have to do more, like contain decision - logic, and so they will have to re-implemented—but we'll get to that later. - </p> + Those actions are <code>login</code> and <code>signUp</code>. The remaining actions involve conditional + navigational behavior, so they will be implemented as action methods. + </p> - <p>The implementations appear below. The following + <p>The simple action implementations appear below. The following <code>@Jpf.SimpleAction</code> annotations define a set of mappings between action names and JSP page destinations. When a particular action is invoked, the user is carried to the corresponding JSP page.</p> -<source> + <source> import org.apache.beehive.netui.pageflow.PageFlowController; import org.apache.beehive.netui.pageflow.annotations.Jpf; @Jpf.Controller( <strong>simpleActions={ @Jpf.SimpleAction(name="login", path="login.jsp"), - @Jpf.SimpleAction(name="mypage", path="mypage.jsp"), @Jpf.SimpleAction(name="signUp", path="signup.jsp"), - @Jpf.SimpleAction(name="processLogin", path="mypage.jsp"), - @Jpf.SimpleAction(name="processSignUp", path="thanks.jsp") } )</strong> public class Controller @@ -204,27 +174,31 @@ <title>Actions Methods</title> <p> - Now it is time to re-implement some of our simple actions as action methods. + Now it is time to re-implement the three action methods: <code>login</code>, + <code>processLogin</code>, and <code>processSignUp</code>. </p> <p> - The <code>myPage</code> action, unlike <code>signUp</code> and <code>login</code> - must determine if the user has already authenicated himself or not. If the user + The <code>myPage</code> action + must determine if the user has already authenicated himself or not and the action must + behave differently depending on the + result of that determination. If the user has aleady been authenticated, then the page <code>myPage.jsp</code> will be displayed; if the user has not been authenticated yet, then the page <code>login.jsp</code> will be displayed. </p> - <p>We will implement this behavior in two steps: (1) first will implement a rudimentary <strong>action + <p>We will implement this behavior in two steps: (1) first will implement a <strong>rudimentary action method</strong>, (2) second we will add the <strong>conditional navigational behavior</strong> to the method.</p> <section> - <title>Constant Forwards</title> + <title>Rudimentary Action Methods: Constant Forwards</title> <p>A rudimentary action method must have two syntactical features: (1) it must return the type <code>org.apache.beehive.netui.pageflow.Forward</code> and (2) it must be decorated with - the appropriate metadata annotations.</p> + the appropriate metadata annotations (<code>@Jpf.Action/@Jpf.Forward</code>).</p> - <p>By returning a + <p>The first step in the re-implementation process is to remove the simple action named + <code>mypage</code> and replace it with a method named <code>myPage()</code>. By returning a <code>org.apache.beehive.netui.pageflow.Forward</code> object, the method indicates which page to display to the user. @@ -236,13 +210,18 @@ import org.apache.beehive.netui.pageflow.annotations.Jpf; @Jpf.Controller( - ... + simpleActions={ + @Jpf.SimpleAction(name="login", path="login.jsp"), + @Jpf.SimpleAction(name="signUp", path="signup.jsp"), + @Jpf.SimpleAction(name="processLogin", path="mypage.jsp"), + @Jpf.SimpleAction(name="processSignUp", path="thanks.jsp") + } ) public class Controller extends PageFlowController { <strong> - public Forward login() + public Forward myPage() { ... } @@ -269,14 +248,13 @@ forwards = { @Jpf.Forward( <strong>name="...", path="..."</strong> ), @Jpf.Forward( <strong>name="...", path="..."</strong> ), - @Jpf.Forward( <strong>name="...", path="..."</strong> ), @Jpf.Forward( <strong>name="...", path="..."</strong> ) } ) </source> <p> - By convention, names such as <strong>success</strong> and <strong>failure</strong> + By convention, forward names such as <strong>success</strong> and <strong>failure</strong> are used, but by no means are required. It is good practice, though, to avoid naming the forward based upon the JSP page name since doing so would remove some of the decoupling that Beehive applications attempt to achieve. @@ -295,10 +273,10 @@ { <strong>@Jpf.Action( forwards = { - @Jpf.Forward( name="success", path="login.jsp" ) + @Jpf.Forward( name="success", path="mypage.jsp" ) } )</strong> - public Forward login() + public Forward myPage() { ... } @@ -324,17 +302,17 @@ { <strong>@Jpf.Action( forwards = { - @Jpf.Forward( name="success", path="login.jsp" ) + @Jpf.Forward( name="success", path="mypage.jsp" ) } )</strong> - public Forward login() + public Forward myPage() { <strong>return new Forward( "success" );</strong> } } </source> <p>Now we have re-implemented one of our simple actions as an action method. However, our new action method -doesn't do anything more than the original simple action. The new aciton method remains a purely navigational +doesn't do anything more than the original simple action. The new action method remains a purely navigational action: it is not yet capable of any decision logic and conditional execution. In the next section we will endow the action method with conditional navigational behavior. </p> @@ -342,15 +320,14 @@ </section> <section> - <title>Conditional Forwards</title> + <title>Advanced Action Methods: Conditional Forwards</title> </section> <p> - We define two forwards named <strong>authenticated</strong> and <strong>not_authenticated</strong>, - which are linked to <code>mypage.jsp</code> and <code>login.jsp</code> respectively. - In this case, the determination of authentication is performed by checking a - <strong>session attribute</strong> - to see if the <code>authenticated_user</code> attribute has been set. + The first step in adding conditional navigational behavior is to define <em>two</em> forwards + named <strong>authenticated</strong> and <strong>not_authenticated</strong>, + which are mapped to <code>mypage.jsp</code> and <code>login.do</code> respectively. + </p> <source> @@ -358,9 +335,6 @@ import org.apache.beehive.netui.pageflow.PageFlowController; import org.apache.beehive.netui.pageflow.annotations.Jpf; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - @Jpf.Controller( ... ) @@ -370,20 +344,52 @@ @Jpf.Action( forwards = { <strong>@Jpf.Forward( name="authenticated", path="mypage.jsp" ), - @Jpf.Forward( name="not_authenticated", path="login.jsp" )</strong> + @Jpf.Forward( name="not_authenticated", path="login.do" )</strong> + } + ) + public Forward myPage() + { + ... + } +} +</source> + +<p>But how to do the method decide which forward to invoke? + In this case, the determination of authentication is performed by checking a + <strong>session attribute</strong> + to see if the <code>authenticated_user</code> attribute has been set.</p> + +<source> +import org.apache.beehive.netui.pageflow.Forward; +import org.apache.beehive.netui.pageflow.PageFlowController; +import org.apache.beehive.netui.pageflow.annotations.Jpf; + +<strong>import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession;</strong> + [EMAIL PROTECTED]( + ... +) +public class Controller + extends PageFlowController +{ + @Jpf.Action( + forwards = { + @Jpf.Forward( name="authenticated", path="mypage.jsp" ), + @Jpf.Forward( name="not_authenticated", path="login.do" ) } ) public Forward myPage() { - HttpServletRequest request = getRequest(); + <strong>HttpServletRequest request = getRequest(); HttpSession session = request.getSession(); - <strong>if ( session.getAttribute( "authenticated_user" ) != null ) + if ( session.getAttribute( "authenticated_user" ) != null ) { return new Forward( "authenticated" ); - }</strong> + } - return new Forward( "not_authenticated" ); + return new Forward( "not_authenticated" );</strong> } } </source> @@ -419,7 +425,9 @@ <p> First, define a JavaBean to represent the HTML form to be submitted. This JavaBean can be of any Java type. (In Struts applications the JavaBean must be a subclass of <code>org.apache.struts.action.ActionForm</code>. Similarly, in earlier incarnations of Page Flows the JavaBean had to be a subclass of <code>org.apache.beehive.netui.pageflow.FormData</code>. But this restriction has been loosened in the current incarnation: the JavaBean representation may be any JavaBean type.) </p> - <p>The JavaBean may be defined (1) as a <code>static</code> inner class of the controller itself (see example below) or (2) as a stand-alone Java class in a separate file. The JavaBean class follows normal JavaBean conventions and require no special annotations. The JavaBean shown below is a subclass of <code>FormData</code>, but this is not a requirement. The JavaBean can be of any type. + <p>The JavaBean may be defined (1) as a <code>static</code> inner class of the controller itself + (see example below) or (2) as a stand-alone Java class in a separate file. The + JavaBean class follows normal JavaBean conventions and require no special annotations. </p> <source> @@ -435,8 +443,10 @@ public class Controller extends PageFlowController { - <strong>public static class LoginForm - extends FormData + ... + ... + + <strong>public static class LoginForm { private String username; private String password; @@ -461,10 +471,6 @@ return this.password; } }</strong> - - ... - ... - } </source> @@ -487,13 +493,6 @@ public class Controller extends PageFlowController { - <strong>public static class LoginForm - extends FormData - { - ... - ... - }</strong> - ... ... @@ -501,11 +500,18 @@ { ... }</strong> + + + public static class LoginForm + { + ... + ... + } } </source> <p> - Once again, <code>processLogin(..)</code> is a conditional forward controller method. + Once again, <code>processLogin(...)</code> is a conditional forward controller method. If a user has entered a correct username and password, then they should be directed to <code>mypage.jsp</code>, otherwise they will be returned back to the <code>login.jsp</code> for another attempt. Checking username and password is outside of the scope of JPF, @@ -531,8 +537,8 @@ <strong>@Jpf.Action( forwards = { - @Jpf.Forward( name="authenticated", path="mypage.jsp" ), - @Jpf.Forward( name="not_authenticated", path="login.jsp" ) + @Jpf.Forward( name="login_success", path="mypage.jsp" ), + @Jpf.Forward( name="login_failure", path="login.jsp" ) } )</strong> public Forward processLogin(LoginForm form) @@ -546,23 +552,112 @@ session.setAttribute( "authenticated_user", form.getUsername() ); - return new Forward( "authenticated" ); + return new Forward( "login_success" ); } - return new Forward( "not_authenticated" ); + return new Forward( "login_failure" ); } } </source> - +<p>Having fleshed out the <code>processLogin()</code> action method, the diagram appears as follows.</p> +<p><img src="images/impl-flow-1-login-form.png" alt="implementation page flow"/></p> <p> - Similar implementation would be done for <code>signUp(..)</code>, involving another - <code>FormData</code> subclass such as <code>SignUpForm</code>. + Similar implementation would be done for <code>processSignUp(...)</code>, involving another + form class such as <code>SignUpForm</code>. + </p> </section> - </section> +<section> + <title>Handling Exceptions</title> + <p> + Suppose a new user completes the signup form and clicks the submit button. It is very common + to make mistakes when filling out a long HTML form with many fields. Suppose that a mistake has occured, + like a required field was left out, or the phone number did not have the proper format. Suppose + that an exception was thrown by the processSignUp() method? What then?</p> + <p>A natural design choice would be to have the + <code>myPage</code> action throw an exception and handle the exception by returning the user to + the original signup page. + The following diagram shows how you can interweave exception handling into the page flow to + further refine the paths through the flow. + </p> + <p> + <img src="images/impl-flow-1-exception-handling.png" alt="page flow exception handling"/> + </p> + <p>You can implement exception handling using the <code>@Jpf.Catch</code> + and <code>@Jpf.ExceptionHandler</code> annotations. The <code>@Jpf.Catch</code> defines + some exception to intercept should it arise within the page flow. The <code>@Jpf.ExceptionHandler</code> + annotation is used to define some standard way of handling the intercepted exception.</p> + <source> [EMAIL PROTECTED]( + <strong>catches={ + @Jpf.Catch(method="handleAccountAlreadyExistsException", type=AccountAlreadyExistsException.class) + }</strong>, + simpleActions={ + ... + } +) +public class Controller + extends PageFlowController +{ + ... + ... + + <strong>@Jpf.ExceptionHandler( + forwards={ + @Jpf.Forward(name="signup", path="signup.jsp") + } + )</strong> + protected Forward handleAccountAlreadyExistsException(AccountAlreadyExistsException ex, String actionName, String message, Object form) + { + return new Forward("signup"); + } + +} + </source> +<p>To protect a method with this error handling system, you only need to specify that the method throws the + appropriate sort of exception, in this case, <code>AccountAlreadyExistsException</code>.</p> + + <source> + [EMAIL PROTECTED]( + catches={ + @Jpf.Catch(method="handleAccountAlreadyExistsException", type=AccountAlreadyExistsException.class) + }, + simpleActions={ + ... + } +) +public class Controller + extends PageFlowController +{ + ... + ... + + public Forward processSignUp(SignUpForm form) + <strong>throws AccountAlreadyExistsException</strong> + { + ... + } + + @Jpf.ExceptionHandler( + forwards={ + @Jpf.Forward(name="signup", path="signup.jsp") + } + ) + protected Forward handleAccountAlreadyExistsException(AccountAlreadyExistsException ex, String actionName, String message, Object form) + { + return new Forward("signup"); + } + +} + </source> + +</section> + + </section> <section id="next"> <title>Next...</title> Modified: incubator/beehive/trunk/docs/forrest/src/documentation/content/xdocs/pageflow/pageflow_overview.xml Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/docs/forrest/src/documentation/content/xdocs/pageflow/pageflow_overview.xml?view=diff&rev=124973&p1=incubator/beehive/trunk/docs/forrest/src/documentation/content/xdocs/pageflow/pageflow_overview.xml&r1=124972&p2=incubator/beehive/trunk/docs/forrest/src/documentation/content/xdocs/pageflow/pageflow_overview.xml&r2=124973 ============================================================================== --- incubator/beehive/trunk/docs/forrest/src/documentation/content/xdocs/pageflow/pageflow_overview.xml (original) +++ incubator/beehive/trunk/docs/forrest/src/documentation/content/xdocs/pageflow/pageflow_overview.xml Wed Jan 12 08:39:01 2005 @@ -125,12 +125,21 @@ <ol> <li> <p> - <code>index.jsp</code> directly to <code>mypage.jsp</code> if the user is already logged in. + The user may directly navigate from <code>index.jsp</code> to <code>mypage.jsp</code> + (by clicking a link), if the user is already logged in. </p> </li> <li> <p> - <code>index.jsp</code> to <code>login.jsp</code> if the user explicitely selects the 'login' action. + If the user is not already logged in, attempts to navigate from + <code>index.jsp</code> to <code>mypage.jsp</code> + will be intercepted and the user will be taken to the <code>login.jsp</code> instead. + After successfully logging in, the user will be automatically taken to <code>mypage.jsp</code> + </p> + </li> + <li> + <p> + The user may directly navigate from <code>index.jsp</code> to <code>login.jsp</code> (by clicking a link). After logging in, the user will be automatically taken to <code>mypage.jsp</code>. </p> @@ -141,16 +150,9 @@ </li> <li> <p> - If the user desires to register with the site, he can select the action that will + If the user desires to register with the site, he can click a link that will take him to <code>signup.jsp</code>. One signed up, the <code>thanks.jsp</code> - will be displayed which also allows the user to follow the path outlined in #2 - above to login. - </p> - </li> - <li> - <p> - In the event a user has already authenticated himself, he will be allowed to - go directly to his "My Page" at <code>mypage.jsp</code>. + will be displayed which offers a link to the <code>login.jsp</code> page. </p> </li> </ol> @@ -235,17 +237,9 @@ Now it is apparent that to navigate from <code>index.jsp</code> to <code>mypage.jsp</code>, the user traverses across the <code>myPage</code> action. This action performs the necessary check to determine if the user has already been authenticated. If the user has logged in already, - it will direct the user straight to <code>mypage.jsp</code>. - </p> - <p> - But what if the user hasn't logged in already? A natural design choice would be to have the - <code>myPage</code> action throw an exception and handle the exception in someway. - The following diagram shows how you can interweave exception handling into the page flow to - further refine the paths through the flow. + it will direct the user straight to <code>mypage.jsp</code>; otherwise it will direct the user + to <code>login.jsp</code>. </p> - <p> - <img src="images/impl-flow-1-exception-handling.png" alt="page flow exception handling"/> - </p> </section> <section id="next"> <title>Next...</title> @@ -257,16 +251,7 @@ <ul> <li><a class="jump" href="pageflow_controllers.html">Page Flow Controller</a></li> </ul> - </section> -<!-- -Notes: -Actionsâimplement (1) navigation logic, -(2) provide access to resources via controls, (3) handle form data, -and (4) and contain decision logic. -Actions are implemented as (1) annotations or (2) Controller methods. ---> - - + </section> </body> <footer> <legal> Modified: incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-exception-handling.dia Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-exception-handling.dia?view=diff&rev=124973&p1=incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-exception-handling.dia&r1=124972&p2=incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-exception-handling.dia&r2=124973 ============================================================================== Binary files. No diff available. Modified: incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-exception-handling.png Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-exception-handling.png?view=diff&rev=124973&p1=incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-exception-handling.png&r1=124972&p2=incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-exception-handling.png&r2=124973 ============================================================================== Binary files. No diff available. Added: incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-login-form.dia Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-login-form.dia?view=auto&rev=124973 ============================================================================== Binary file. No diff available. Added: incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-login-form.png Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1-login-form.png?view=auto&rev=124973 ============================================================================== Binary file. No diff available. Modified: incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1.dia Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1.dia?view=diff&rev=124973&p1=incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1.dia&r1=124972&p2=incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1.dia&r2=124973 ============================================================================== Binary files. No diff available. Modified: incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1.png Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1.png?view=diff&rev=124973&p1=incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1.png&r1=124972&p2=incubator/beehive/trunk/docs/forrest/src/documentation/resources/images/impl-flow-1.png&r2=124973 ============================================================================== Binary files. No diff available.
