You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by we...@apache.org on 2007/05/23 23:19:22 UTC
svn commit: r541091 - in /myfaces/current/orchestra/core/src/site/xdoc:
bestPractice.xml component-bindings.xml
Author: werpu
Date: Wed May 23 14:19:22 2007
New Revision: 541091
URL: http://svn.apache.org/viewvc?view=rev&rev=541091
Log:
fixed a few things added a chapter regarding the component bindings...
Added:
myfaces/current/orchestra/core/src/site/xdoc/component-bindings.xml
Modified:
myfaces/current/orchestra/core/src/site/xdoc/bestPractice.xml
Modified: myfaces/current/orchestra/core/src/site/xdoc/bestPractice.xml
URL: http://svn.apache.org/viewvc/myfaces/current/orchestra/core/src/site/xdoc/bestPractice.xml?view=diff&rev=541091&r1=541090&r2=541091
==============================================================================
--- myfaces/current/orchestra/core/src/site/xdoc/bestPractice.xml (original)
+++ myfaces/current/orchestra/core/src/site/xdoc/bestPractice.xml Wed May 23 14:19:22 2007
@@ -1,112 +1,120 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE document PUBLIC "-//Apache Software Foundation//DTD XDOC 1.0//EN"
- "http://www.apache.org/dtd/xdoc.dtd">
-<document>
- <properties>
- <title>Best Practice</title>
- </properties>
-
- <body>
- <section name="Best Practice">
-
- Here we will collect what we think is the best practice to use all this stuff.
- <br/>
- However, you are not bound to it.
-
- <li>
- <ul>Have a single bean for your page.<br />
- Means, you CAN use more than one, e.g if you
- have to fill your layout with data it wouldn't make much sense to put this into each
- backing bean.<br/>
- However, taking this approach you enable some additional features the ViewController
- stuff will provide.
- </ul>
- </li>
-
- <subsection name="Single Page Conversation">
-
- <p>
- Single Page conversation are easy, just put the bean into the conversation scope und use
- it in your value-/methodbinding.
- </p>
-
- <p>
- Mostly on save actions end the conversation and maybe restart it to review the data.
- </p>
-
- <p>
- Maybe also provide a way to cancel the current work, which will simply end the conversation.
- (without commit to the database)
- </p>
-
- </subsection>
-
- <subsection name="Multi Page Conversation">
-
- <p>
- For mutli page conversations you have to break through the first suggestion ;-), means,
- its not possible to have the conversation bean the same name than the pages, a bean
- can just have a single name.
- </p>
-
- <p>
- And this is not that bad, the suggestion is to use a simple request scoped bean per page
- and a single conversation scoped data.<br />
- If you have three pages, e.g. startPage.jsp, enterPage.jsp, endPage.jsp you'll end up
- with a structure like (note: the names are suggestions only):
-
- <ul>
- <li>Page:startPage.jsp</li>
- <li>Page:enterPage.jsp<br/>Bean name: enterPage</li>
- <li>Page:endPage.jsp<br/>Bean name: endPage</li>
- <li>Conversation name: pagesData</li>
- </ul>
- </p>
-
- <p>
- You see, there is no bean required for the startPage. We also require the enterPage and endPage
- to check if the conversation is really running.
- </p>
-
- <p>
- We have to ensure that the user starts with the startPage. Reasons why this could be violated are:
- <ul>
- <li>the conversation timed out in the mid of the work</li>
- <li>the user tampered the url</li>
- </ul>
- </p>
-
- <p>
- Now that we have a mini backing bean for the enterPage and the endPage we can put in code
- to ensure it. We can ensure a conversation has been started, else issue a redirect
- or JSF navigation.
- </p>
-
- <p>
- Simply add a method called <code>initView()</code> to the enterPage and endPage bean like the
- following:
- <pre>
-public void initView()
-{
- ConversationUtils.ensureConversationRedirect("pagesData", "/startPage.faces");
-}
- </pre>
-
- <b>Notice:</b> There is also a <code>JsfConversationUtils</code> class which allows you to invoke a navigation.<br/>
- <b>Notice:</b> See the ViewController documentation how to use other strategies or adjust the mapping
- fo the viewId to your bean names.
- </p>
-
- <p>
- Once the core code has settled we will work out a method how to make this more
- developer friendly, though, for a nice solution it looks like we can't
- avoid the introduction of an annotation based solution.<br/>
- Fully optional then, available when you add the core15 module.
- </p>
-
-
- </subsection>
-
- </section>
- </body>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE document PUBLIC "-//Apache Software Foundation//DTD XDOC 1.0//EN"
+ "http://www.apache.org/dtd/xdoc.dtd">
+<document>
+ <properties>
+ <title>Best Practice</title>
+ </properties>
+
+ <body>
+ <section name="Best Practice">
+
+ This page should give some guidance to some best practices
+ we think should be applied to reach the fastest result.
+
+
+ <br/>
+ Feel free to adopt them, feel free to ignore them.
+
+ <p>
+ In various tests and implementations it became clear very early that the best approach
+ is, to have a single page controller under one conversation for one or many pages
+ depending on your scope flow.
+ </p>
+ <p>
+ The reason for this self imposed limitation is that if you end up with too many conversations
+ things become complicated and if you use the conversations on a non page controller level, you will
+ lose some functionality the internal view handler mechanisms of orchestra expose to your bean.
+ </p>
+ <p>
+ Note, that all beans under one page controller are under the same conversation, unless they
+ already are under a different conversation scope when assigned!
+ </p>
+
+ <subsection name="Single Page Conversation">
+
+ <p>
+ Single Page conversations are easy, just put the bean, representing your view controller, into the conversation scope und use
+ it in your value-/methodbinding.
+ </p>
+
+ <p>
+ Mostly on save actions end the conversation and maybe restart it to review the data.
+ </p>
+
+ <p>
+ Maybe also provide a way to cancel the current work, which will simply end the conversation.
+ (without commit to the database)
+ </p>
+
+ </subsection>
+
+ <subsection name="Multi Page Conversation">
+
+ <p>
+ For multi page conversations you have to break through the first suggestion ;-), means,
+ its not possible to have the conversation bean the same name than the pages, a bean
+ can just have a single name.
+ </p>
+
+ <p>
+ And this is not that bad, the suggestion is to use a simple request scoped bean per page
+ and a single conversation scoped data.<br />
+ If you have three pages, e.g. startPage.jsp, enterPage.jsp, endPage.jsp you'll end up
+ with a structure like (note: the names are suggestions only):
+
+ <ul>
+ <li>Page:startPage.jsp</li>
+ <li>Page:enterPage.jsp<br/>Bean name: enterPage</li>
+ <li>Page:endPage.jsp<br/>Bean name: endPage</li>
+ <li>Conversation name: pagesData</li>
+ </ul>
+ </p>
+
+ <p>
+ You see, there is no bean required for the startPage. We also require the enterPage and endPage
+ to check if the conversation is really running.
+ </p>
+
+ <p>
+ We have to ensure that the user starts with the startPage. Reasons why this could be violated are:
+ <ul>
+ <li>the conversation timed out in the mid of the work</li>
+ <li>the user tampered the url</li>
+ </ul>
+ </p>
+
+ <p>
+ Now that we have a mini backing bean for the enterPage and the endPage we can put in code
+ to ensure it. We can ensure a conversation has been started, else issue a redirect
+ or JSF navigation.
+ </p>
+
+ <p>
+ Simply add a method called <code>initView()</code> to the enterPage and endPage bean like the
+ following:
+ <pre>
+public void initView()
+{
+ ConversationUtils.ensureConversationRedirect("pagesData", "/startPage.faces");
+}
+ </pre>
+
+ <b>Notice:</b> There is also a <code>JsfConversationUtils</code> class which allows you to invoke a navigation.<br/>
+ <b>Notice:</b> See the ViewController documentation how to use other strategies or adjust the mapping
+ fo the viewId to your bean names.
+ </p>
+
+ <p>
+ Once the core code has settled we will work out a method how to make this more
+ developer friendly, though, for a nice solution it looks like we can't
+ avoid the introduction of an annotation based solution.<br/>
+ Fully optional then, available when you add the core15 module.
+ </p>
+
+
+ </subsection>
+
+ </section>
+ </body>
</document>
Added: myfaces/current/orchestra/core/src/site/xdoc/component-bindings.xml
URL: http://svn.apache.org/viewvc/myfaces/current/orchestra/core/src/site/xdoc/component-bindings.xml?view=auto&rev=541091
==============================================================================
--- myfaces/current/orchestra/core/src/site/xdoc/component-bindings.xml (added)
+++ myfaces/current/orchestra/core/src/site/xdoc/component-bindings.xml Wed May 23 14:19:22 2007
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE document PUBLIC "-//Apache Software Foundation//DTD XDOC 1.0//EN"
+ "http://www.apache.org/dtd/xdoc.dtd">
+<document>
+ <properties>
+ <title>Apache MyFaces Orchestra - Component Bingings</title>
+ </properties>
+
+ <body>
+ <section name="Component Bindings">
+ <subsection name="Introduction">
+ <subsubsection name="Basic discrepancy">
+ While the best pratice is to have a single page controller under conversation per page or
+ for a full multi page flow, there is a discrepancy between the scope length needed for the conversation
+ and the scope length for associated component bindings.
+ </subsubsection>
+
+ </subsection>
+ <subsection name="Problem">
+ The main problem is, component bindings in a backend bean require a scope lenth of request.
+ The cause is that the component tree is regenerated at every request. Longer component bindings
+ are a possible cause for internal id clashes etc...
+ <p> </p>
+ The main problems we now face are, we have a single page controller/model object which is associated
+ to the view. The page controller/model now is stateful, which is exactly as inded, however we need
+ component bindings in this bean and those are referenced by the view.
+ The bindings under normal circumstances inherit exactly the scope of the page controller.
+ <p> </p>
+ Therefore following construct automatically is bound to fail:
+ <pre>
+<component binding="#{viewcontrollerbean.bindingattribute}" />
+ </pre>
+ The problem here is that the viewcontroller bean has a scope of conversation, the bindingattribute, however, needs
+ a scope of request.
+ This at the first look is a problem impossible to solve.
+ At the second look, Spring itself provides the solution. Since every bean referenced by
+ the framework and the view layer is a Spring bean, we get the solution out of the magical
+ Spring box.
+ </subsection>
+ <subsection name="Solution">
+ Spring in 2.0 has introduced a construct called aop-proxy. This is a special tag which can be embedded
+ into beans which basically does nothing more than to weave a proxy object around an existing object which inherits
+ the scope of the referencing bean.
+ The inner part of the proxy or own bean then can have a scope of its own which can be smaller than the scope
+ of the referencing object.
+ <p> </p>
+ So how does this help:
+ Lets look again at our example
+ <pre>
+<component binding="#{viewcontrollerbean.componentbindingmodel.bindingattribute}" />
+ </pre>
+ The accessor path has slightly changed, we have introduced a second bean a model
+ bean which holds our component bindings.
+ <p> </p>
+ What happens on the spring configuration side is simply following:
+
+ <pre>
+<bean id="componentbindingmodel" scope="request" class="path.to.our.model.class">
+ <aop:scoped-proxy />
+</bean>
+
+<bean id="viewcontrollerbean" scope="conversation" ...>
+ <property name="componentbindingmodel"
+ ref="componentbindingmodel" />
+
+</bean>
+ </pre>
+The associated component binding model class is simply a class which holds the components as attributes and its associated setter
+and getter methods.
+ <p> </p>
+ What happens at call stage: The viewcontrollerbean is instantiated under conversation scope, the proxy
+ object is generated and assigned dependin on its lazy binding stage.
+ At the request end, the content of the componentbindingmodel bean is dropped and only the empty proxy
+ shell still is referenced.
+ At the next request which references parts of the componentbindingmodel object the content again is initialized
+ and can be accessed. This way it is possible to bind the request scoped component bindings to any long running scope
+ no matter being it our conversation scopes or session scopes!
+ </subsection>
+ </section>
+ </body>
+</document>
\ No newline at end of file