Return-Path: X-Original-To: apmail-myfaces-commits-archive@www.apache.org Delivered-To: apmail-myfaces-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id BE0649872 for ; Tue, 17 Apr 2012 01:30:28 +0000 (UTC) Received: (qmail 99925 invoked by uid 500); 17 Apr 2012 01:30:28 -0000 Delivered-To: apmail-myfaces-commits-archive@myfaces.apache.org Received: (qmail 99834 invoked by uid 500); 17 Apr 2012 01:30:28 -0000 Mailing-List: contact commits-help@myfaces.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "MyFaces Development" Delivered-To: mailing list commits@myfaces.apache.org Received: (qmail 99825 invoked by uid 99); 17 Apr 2012 01:30:28 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 17 Apr 2012 01:30:28 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 17 Apr 2012 01:30:16 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 49F0823889E0 for ; Tue, 17 Apr 2012 01:29:54 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1326868 [1/2] - in /myfaces/orchestra/trunk: core/src/site/ core/src/site/xdoc/ maven/src/site/ maven/src/site/xdoc/ Date: Tue, 17 Apr 2012 01:29:53 -0000 To: commits@myfaces.apache.org From: lu4242@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120417012954.49F0823889E0@eris.apache.org> Author: lu4242 Date: Tue Apr 17 01:29:52 2012 New Revision: 1326868 URL: http://svn.apache.org/viewvc?rev=1326868&view=rev Log: reorganize orchestra documentation Added: myfaces/orchestra/trunk/maven/src/site/xdoc/alternative-configuration.xml (with props) myfaces/orchestra/trunk/maven/src/site/xdoc/bestPractice.xml (with props) myfaces/orchestra/trunk/maven/src/site/xdoc/component-bindings.xml (with props) myfaces/orchestra/trunk/maven/src/site/xdoc/conversation.xml (with props) myfaces/orchestra/trunk/maven/src/site/xdoc/faqs.xml (with props) myfaces/orchestra/trunk/maven/src/site/xdoc/glossary.xml (with props) myfaces/orchestra/trunk/maven/src/site/xdoc/implementation.xml (with props) myfaces/orchestra/trunk/maven/src/site/xdoc/installation.xml (with props) myfaces/orchestra/trunk/maven/src/site/xdoc/introduction.xml (with props) myfaces/orchestra/trunk/maven/src/site/xdoc/multiwindow.xml (with props) myfaces/orchestra/trunk/maven/src/site/xdoc/persistence.xml (with props) myfaces/orchestra/trunk/maven/src/site/xdoc/todo.xml (with props) myfaces/orchestra/trunk/maven/src/site/xdoc/usage.xml (with props) myfaces/orchestra/trunk/maven/src/site/xdoc/viewController.xml (with props) Removed: myfaces/orchestra/trunk/core/src/site/site.xml myfaces/orchestra/trunk/core/src/site/xdoc/alternative-configuration.xml myfaces/orchestra/trunk/core/src/site/xdoc/bestPractice.xml myfaces/orchestra/trunk/core/src/site/xdoc/component-bindings.xml myfaces/orchestra/trunk/core/src/site/xdoc/conversation.xml myfaces/orchestra/trunk/core/src/site/xdoc/faqs.xml myfaces/orchestra/trunk/core/src/site/xdoc/glossary.xml myfaces/orchestra/trunk/core/src/site/xdoc/implementation.xml myfaces/orchestra/trunk/core/src/site/xdoc/installation.xml myfaces/orchestra/trunk/core/src/site/xdoc/introduction.xml myfaces/orchestra/trunk/core/src/site/xdoc/multiwindow.xml myfaces/orchestra/trunk/core/src/site/xdoc/persistence.xml myfaces/orchestra/trunk/core/src/site/xdoc/todo.xml myfaces/orchestra/trunk/core/src/site/xdoc/usage.xml myfaces/orchestra/trunk/core/src/site/xdoc/viewController.xml Modified: myfaces/orchestra/trunk/maven/src/site/site.xml Modified: myfaces/orchestra/trunk/maven/src/site/site.xml URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/maven/src/site/site.xml?rev=1326868&r1=1326867&r2=1326868&view=diff ============================================================================== --- myfaces/orchestra/trunk/maven/src/site/site.xml (original) +++ myfaces/orchestra/trunk/maven/src/site/site.xml Tue Apr 17 01:29:52 2012 @@ -89,6 +89,27 @@ + + + + + + + + + + + + + + + + + + + + + Added: myfaces/orchestra/trunk/maven/src/site/xdoc/alternative-configuration.xml URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/maven/src/site/xdoc/alternative-configuration.xml?rev=1326868&view=auto ============================================================================== --- myfaces/orchestra/trunk/maven/src/site/xdoc/alternative-configuration.xml (added) +++ myfaces/orchestra/trunk/maven/src/site/xdoc/alternative-configuration.xml Tue Apr 17 01:29:52 2012 @@ -0,0 +1,176 @@ + + + + + + + Apache MyFaces Orchestra - Alternative Configuration + + + +
+ The following configuration provides a blueprint for + a single Tomcat installation using Spring 2.0, jpa ri + and runtime weaving. + + + +
    +
  • Prerequisites - Knowledge: Basic Spring 2.0 configuration knowledge, knowledge about + the jpa ri, to the level that knowing what runtime weaving is can be assumed. +
  • +
  • Prerequisites - JDK Versions: JDK 5+ (on non Sun JDKs a working runtime weaving on 5 + or a 6+ non Sun JDK)
  • +
  • Tomcat: 5.5+
  • +
  • Spring 2.x+
  • +
+
+ + The following configuration uses runtime weaving, and + a connection pool. It should work on most Tomcat configurations. + + +
+  <?xml version="1.0" encoding="UTF-8"?>
+  <beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:tx="http://www.springframework.org/schema/tx"
+    xmlns:aop="http://www.springframework.org/schema/aop"
+    xmlns:sa="https://spring-annotation.dev.java.net/context"
+
+    xsi:schemaLocation="
+    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
+    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
+    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"
+  >
+
+    <tx:annotation-driven transaction-manager="transactionManager" />
+    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
+  
+    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
+      <property name="scopes">
+        <map>
+          <entry key="conversation.access">
+            <bean class="org.apache.myfaces.orchestra.conversation.spring.SpringConversationScope">
+              <property name="advices">
+                <list>
+                  <ref bean="persistentContextConversationInterceptor" />
+                </list>
+              </property>
+            </bean>
+          </entry>
+        </map>
+      </property>
+    </bean>
+
+    <bean id="thedataSource" class="org.apache.commons.dbcp.BasicDataSource">
+      <property name="driverClassName" value="org.h2.Driver" />
+      <property name="url"
+        value="jdbc:h2:/DATA/dummydatabase;MODE=MYSQL" />
+    
+      <property name="username" value="theusername" />
+      <property name="password" value="thepassword" />
+    
+      <property name="initialSize">
+        <value>2</value>
+      </property>
+      <property name="maxActive">
+        <value>100</value>
+      </property>
+      <property name="maxIdle">
+        <value>2</value>
+      </property>
+    </bean>
+
+    <bean id="entityManagerFactory"
+        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
+
+      <property name="dataSource" ref="thedataSource" />
+      <property name="jpaDialect">
+        <bean class="org.springframework.orm.jpa.vendor.TopLinkJpaDialect" />
+      </property>   
+      <property name="jpaVendorAdapter">
+        <bean
+            class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter">
+          <property name="showSql" value="false" />
+          <property name="generateDdl" value="true" />
+          <property name="databasePlatform" value="oracle.toplink.essentials.platform.database.MySQL4Platform" />
+        </bean>
+      </property>
+    
+      <property name="jpaProperties">
+        
+        <props>
+          <prop key="toplink.logging.level">INFO</prop>
+          <prop key="toplink.target-database">oracle.toplink.essentials.platform.database.MySQL4Platform</prop>
+          <prop key="toplink.ddl-generation">create-tables</prop>
+          <prop key="toplink.cache.type.default">HardWeak</prop>
+          <prop key="toplink.cache.size.default">5000</prop>
+        </props>
+      </property>    
+      <property name="loadTimeWeaver">
+        <bean
+            class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
+      </property>
+    </bean>
+
+    <bean id="transactionManager"
+        class="org.springframework.orm.jpa.JpaTransactionManager">
+      <property name="entityManagerFactory"
+        ref="entityManagerFactory" />
+    
+    </bean>
+    
+    <bean id="jpaPersistentContextFactory" class="org.apache.myfaces.orchestra.conversation.persistenceContexts.JpaPersistenceContextFactory">
+      <property name="entityManagerFactory" ref="entityManagerFactory" />
+    </bean>
+    <bean id="persistentContextConversationInterceptor" class="org.apache.myfaces.orchestra.conversation.spring.PersistenceContextConversationInterceptor">
+      <property name="persistenceContextFactory" ref="jpaPersistentContextFactory" />
+    </bean>
+
+  </beans>    
+    
+ + This configuration enables load time weaving of the orm classes and thus allows + lazy instantiation of classes. The main issue with this configuration is, that + Tomcat still needs a javaagent passed down as parameter. If this is not done + the loadtime weaving ultimately will fail. + the required javaagent is: +
+-javaagent:<path to the spring weavers>/weavers/spring-agent.jar
+    
+ There are weaverless configurations as well, in spring 2.0.2 it was not yet possible to enable + them for jpa and Tomcat. This situation might change soon, please refer to the Spring documentation + for additional information on how to enable the loadtime weaving of jpa classes. + +
+ + Following key differences can be found: +
    +
  • Load time weaving enabled via: <property name="loadTimeWeaver">
  • +
  • A connection pool was used instead of a plain jdbc connection
  • +
  • Tomcat has to be started with an appropriate javaagent statement
  • +
+
+ +
+ +
Propchange: myfaces/orchestra/trunk/maven/src/site/xdoc/alternative-configuration.xml ------------------------------------------------------------------------------ svn:eol-style = native Added: myfaces/orchestra/trunk/maven/src/site/xdoc/bestPractice.xml URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/maven/src/site/xdoc/bestPractice.xml?rev=1326868&view=auto ============================================================================== --- myfaces/orchestra/trunk/maven/src/site/xdoc/bestPractice.xml (added) +++ myfaces/orchestra/trunk/maven/src/site/xdoc/bestPractice.xml Tue Apr 17 01:29:52 2012 @@ -0,0 +1,227 @@ + + + + + + Apache MyFaces Orchestra - Best Practice + + + +
+ + This page contains information on how the Orchestra developers believe Orchestra + is best used. As always, best practices evolve - see the wiki for the latest + information. + + + +

+ This applies when you have a single page that the user may submit multiple times + (eg select an item from a list and click a button, then select a different item + and click another button). The state of the page changes after each submit, but + this state must be held in memory. +

+ +

+ Write a single managed bean for the view. Configure this bean as belonging + to an unnamed access-scoped conversation and reference it as normal from + your presentation pages (jsp, facelets, clay, etc). +

+ +

+ The conversation will be started when the bean is first accessed, and will + automatically be terminated (ie the bean will be deleted) when navigation + to some other page occurs (well, technically when a page is rendered that + does not reference this managed bean). If you have an action method that wants + to "start fresh" while remaining at the same view, then from the action method call + ConversationUtils.invalidateAndRestartCurrent() to discard the current + conversation. +

+ +

+ If this bean is named to match the view that it is backing + (eg beanname="edit" for the "/edit" viewid), then it is trivial + to get "lifecycle events" from Orchestra's ViewController. Even if + the bean-name does not match the view, there are ways of configuring + things so it still receives the appropriate callbacks. See the + ViewController documentation for more information on this. +

+ +
+ + +

+ This applies when you have a set of pages that cooperate together to interact + with the user, but where the state used by these pages must be held in memory. + Commonly, sequences of pages like this eventually lead to a "save" or "execute" + button which then performs an action using the state that was set up by the user + via the preceding pages. Such sequences are sometimes called a "wizard". +

+ +

+ Use one access-scoped controller for the whole conversation, plus one simple + request-scoped or access-scoped bean per view. For example, if you have three + pages then structure things as follows: + +

    +
  • Page:purchaseStep1.jsp
    Bean name: purchaseStep1
  • +
  • Page:purchaseStep2.jsp
    Bean name: purchaseStep2
  • +
  • Page:purchaseStep3.jsp
    Bean name: purchaseStep3
  • +
  • Conversation bean name: purchaseController
  • +
+

+ +

+ Generally, there is no need to specify a conversationName attribute for these beans, + ie the name of the conversation they are in is the same as the name of the bean. +

+

+ The per-view beans handle logic and state that is specific to that page. If there is state needed + for the page, then use "access" scope, otherwise use "request" scope. Inject the controller bean + into each per-view bean so that state and logic which is shared between views can be accessed. +

+

+ If there is common logic that each page shares, then that can be defined in an abstract base bean + which the per-view beans extend. +

+

+ EL expressions in the pages can reference either the per-view bean or the common controller bean, + whichever is appropriate. +

+

+ There are two problems with workflows: +

    +
  • +

    + A conversation may timeout in the middle of a conversation + (eg the user goes to lunch, then tries to continue on return), and +

    +
  • +
  • +

    + A user may try to leap into the middle of a conversation (eg via a bookmark) +

    +
  • +
+ With the above recommended structure, each per-view bean except the first one can then + check whether the conversation exists and is in an appropriate state for that view. + If not, then a navigation to the proper "entry page" for the conversation can be done. +

+

+ The basic check for the existence of the conversation is fairly simple to do in java code: +

+public void initView()
+{
+    ConversationUtils.ensureConversationRedirect("purchaseController", "/purchaseStep1.jsf");
+}
+          
+ If a set of per-view beans share a common base class then this initView method can be + added to the base class, then overridden only in the page that is redirected to + ("purchaseStep1.jsp" in this example) to prevent circular redirects. This then protects + all of the pages from access without a correctly initialised conversation. +

+ +

+ There is one issue: after redirect it would sometimes be nice to display an error + message indicating *why* the redirect happened, eg "Invalid Conversation State". This + is not easy on a redirect. A forward would be easier to handle, as that data could + be placed in request scope. +

+

+ Without this check, when a user leaps into the middle of a conversation, EL expressions + will trigger the creation of the missing purchaseController (and its associated conversation) + but the bean probably does not have the appropriate state to render the page correctly. +

+ +

+ The orchestra core15 module provides the @ConversationRequire annotation to make this even easier. +

+ +

+ Note that this works even when the purchaseController bean (which is in the purchaseController + conversation, unless otherwise configured) is injected into the per-view bean. The object + injected is actually a proxy, so the conversation is not created until the bean is really + referenced. +

+ +

+ Notice: There is also a JsfConversationUtils-class which allows + you to invoke a navigation rule rather than encoding a url in the call to + method ensureConversationRedirect. +

+ +

+ If the views in a workflow are so simple that there is no logic or state needed, then + rather than declaring "dummy beans" just to receive lifecycle callbacks the way the + ViewController maps viewids to beannames can be configured. In particular, see the + ViewController annotations from the Orchestra core15 module. Having a separate bean + for the "entry page" of a workflow is always a good idea however. +

+ +
+ + + +

+ In some cases a conversation should not terminate until page N has been visited, + but in the middle a user can go off and visit a page that has no references to + any managed beans within the main conversation. When using Access scopes, Orchestra + will interpret a visit to such as page as the user "abandoning" the conversation, + so the conversation will be discarded. In this case, use a manual scoped conversation, + ie one that must be explicitly ended via either a JSF component (ox:endConversation) + or a call to the Orchestra API from an action method. Use access scopes where possible, + though - they are less work. +

+ +
+ + +

+ In almost all cases, using Session scope is a bad idea. All sorts of data goes into + sessions, including data from UI frameworks, and sometimes from the servlet engine + itself. Instead of using session-scope, put all such beans into a single conversation + scope called "session". The most significant benefit from this is that Orchestra's + "conversation context" feature now allows a user to open multiple windows to your + app without problems; each window has a different "conversation context", and each + "conversation context" has a completely independent set of conversations - including + all the beans in the "session" conversation. It's almost like the user connecting + from two different machines - except that any application login (authentication) + data is shared. +

+

+ There are a few places where real session-scoped data might be appropriate, but not + many. Think whether two separate browser windows for a user really should share that + data. And if they should, then make sure that the shared objects are thread-safe, as + two concurrent requests from two different windows will be using the same instance. +

+
+ + +

+ We recommend you read about component binding and the scoping problem. + This document is not specifically about Apache MyFaces Orchestra, but the same issues apply when dealing + with component-bindings and conversation-scoped beans. +

+
+ +
+ +
Propchange: myfaces/orchestra/trunk/maven/src/site/xdoc/bestPractice.xml ------------------------------------------------------------------------------ svn:eol-style = native Added: myfaces/orchestra/trunk/maven/src/site/xdoc/component-bindings.xml URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/maven/src/site/xdoc/component-bindings.xml?rev=1326868&view=auto ============================================================================== --- myfaces/orchestra/trunk/maven/src/site/xdoc/component-bindings.xml (added) +++ myfaces/orchestra/trunk/maven/src/site/xdoc/component-bindings.xml Tue Apr 17 01:29:52 2012 @@ -0,0 +1,150 @@ + + + + + + + Apache MyFaces Orchestra - Component Bindings + + + +
+ + +

+ JSF components interact with backing beans. However the lifecycles of these two types of + objects are very different; beans may last just a request, or longer (eg a session bean). + A component logically may last a number of page views, but physically new instances are + created for each request, when the view is "restored". +

+

+ JSF is designed so that in normal cases views "pull" data from backing beans, "push" data entered by the + user into backing beans, and "invoke" event-handler methods on backing beans. In all cases, the dependency + is unidirectional: views know about beans, but beans do not know about views. And the coupling is done + only via EL strings, not hard references. This means that the lifecycles of the view components and + the backing beans they reference are decoupled, and the lifecycle mismatch is not an issue. +

+

+ However JSF does provide a mechanism for backing beans to access view components in the rare cases where + this is necessary: "bindings". Unfortunately the coupling here is done via direct object references, not + EL strings. And if a bean then holds on to these references then very bad things can happen if the + lifetime of the bean is longer than a request. Just one of the possible problems is the ugly + "duplicate component id" error. +

+

+ Note that "bindings" are not generally a good idea, and should be avoided where possible. In the + remainder of this page we assume that you have some very good reason for wanting bindings, and + show you how they can be used with non-request-scoped beans. +

+
+ +
+ +

+ In order to avoid the lifecycle mismatch between components and beans, any bean that stores a component + binding must be request-scoped. +

+

+ However what has been recommended in the "Orchestra best practices" is an access-scoped backing bean for + a view and an additional (access or manual) conversation-scoped controller for multi-page conversations. + The page controller/model now is stateful, which is exactly what we wanted, however when component bindings + are needed then they should not be stored on these beans because they are not request-scoped. +

+

+ Therefore the following construct is bound to fail: +

+<component binding="#{viewcontrollerbean.bindingattribute}" />          
+        
+ due to the difference in scopes. +

+

+ There are two possible solutions to this problem. +

+
+ + +

+ 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. +

+

+ So how does this help? Lets look again at our example +

+<component binding="#{viewcontrollerbean.componentbindingmodel.bindingattribute}" />          
+        
+

+

+ The accessor path has slightly changed, we have introduced a second bean; a model + bean which specifically holds our component bindings. +

+

+ What happens on the spring configuration side is simply the following: +

+<bean id="componentbindingmodel" scope="request" class="path.to.our.model.class"/>
+<bean id="viewcontrollerbean" scope="conversation.access" ...>
+      <property name="componentbindingmodel"
+            ref="componentbindingmodel" />
+</bean>
+        
+

+

+ The associated component binding model class is a class which only holds the components as attributes and + provides associated setter and getter methods. The viewcontrollerbean class can then invoke its + methods to get access to the bound component instances. +

+

+ When the viewcontrollerbean object is instantiated, Spring sees that it must inject the bean named + "componentbindingmodel" into it. However that bean is marked as an aop:proxy, so what spring injects + is just a "proxy" object, not a real componentbindingmodel bean. Whenever the viewcontrollerbean + then invokes a method on that proxy object, the proxy looks up bean "componentbindingmodel" in + the specified scope (request), then invokes that method on the object it found. This does have a + significant performance impact; each method call on the proxy performs the bean lookup again. + However it always acts on the "latest" version of that bean, which would not happen if a real + reference had been held. At the end of the request, the request-scoped componentbindingmodel object + is discarded as normal, and only the proxy "shell" remains. At the next request, a new componentbindingmodel + instance is created and added into the request scope, and methods invoked on the proxy will then + automatically work against this new object. +

+
+ +

+ Only a few of the methods on the non-request-scoped backing bean will need access to the bound + components. Therefore, these methods can be moved into a request-scoped bean. Add the component + binding methods to this request-scoped bean too, and inject a reference to the "real" backing + bean into it. Alter the view so that EL expressions that need those component bindings to + be evaluated point to the request-scoped bean. +

+

+ Another way of thinking about this is that the "real" backing bean for the page is implemented as + request-scoped, and any state it needs to retain is pushed into a "helper" object that is of + conversation scope. The request-scoped bean has access to the components without problems. +

+

+ While either of these solutions means yet another backing-bean class for the view, there is no + "spring magic" required. +

+
+
+ +
Propchange: myfaces/orchestra/trunk/maven/src/site/xdoc/component-bindings.xml ------------------------------------------------------------------------------ svn:eol-style = native Added: myfaces/orchestra/trunk/maven/src/site/xdoc/conversation.xml URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/maven/src/site/xdoc/conversation.xml?rev=1326868&view=auto ============================================================================== --- myfaces/orchestra/trunk/maven/src/site/xdoc/conversation.xml (added) +++ myfaces/orchestra/trunk/maven/src/site/xdoc/conversation.xml Tue Apr 17 01:29:52 2012 @@ -0,0 +1,261 @@ + + + + + + + Apache MyFaces Orchestra - The Conversation Scope Problem + + + +
+

+ Often a logical operation consists of multiple JSF requests to the server. + For example, purchasing an insurance policy requires completing a number + of related forms (often referred to as a "conversation", "workflow" or + "dialog"), during which the same java objects need to be kept in memory. +

+ +

+ However JSF provides only three scopes for data to be stored in: +

    +
  • Application scope

  • +
  • Session scope

  • +
  • Request scope

  • +
+

+ +

+ Application scope is only rarely of use; such data is shared across all users of that JSF application. + Request scope is not useful for the above scenario; all data stored in request scope is discarded at + the end of each "command". +

+ +

+ Session scope can be used to hold data across multiple requests (a conversation), + but suffers from a number of other issues: +

    +
  • When the conversation is complete, it is best to discard all the related objects in order + to save memory. However this is quite difficult to do when using session scope.

  • +
  • When a user performs some task for a second time (eg purchasing a second insurance policy), + it is usually better for the backing beans to be new instances rather than having whatever + state they had at the end of the previous pass. This is difficult to achieve when the beans + are in session scope; every relevant bean needs to be explicitly deleted or reset. However + when these objects are stored in a conversation this happens automatically as the conversation + (with all its beans) has been discarded.

  • +
  • The user cannot have multiple windows open on the same site. Sessions are typically + tracked using cookies, and all windows associated with the same browser instance + share cookies and therefore are within the same "session". If two windows are created + for the same session then very strange effects can be caused due to the same "backing beans" + being used by the two windows. Note that JSF implementations generally provide support for + multiple concurrent windows (eg MyFaces and Sun RI) but this only means that the JSF + *components* are safe for use with multiple windows; any application that uses only + request-scope beans will therefore work correctly but apps with session-scoped beans + will still suffer confusion.

  • +
+

+ +

+ The Tomahawk library provides a partial solution to this conversation problem with + the t:saveState tag, which allows data to be bound to a JSF View; it is then + available across multiple consecutive requests to the same view. It can also be + "passed" to a following view when navigation occurs. However this can be difficult + to use, as every bean that needs to be part of the conversation needs to be explicitly + tracked. +

+ +

+ The draft JSF 2.0 specification currently defines a new "view" scope which also + provides a partial solution to this issue that is similar to the Tomahawk + t:saveState tag. +

+ +

+ The Orchestra library provides another alternative. + This solution works across all JSF implementations (particularly Apache MyFaces and + the Sun Reference Implementation). It works for Java 1.4 or later. If java1.5 is + being used then custom annotations are available to make its use even easier. +

+ +

+ Orchestra does require conversation-scoped managed beans to be declared via a good + dependency-injection (aka IOC) framework with AOP support. The standard JSF + managed-beans facility does not provide sufficient flexibility. While it should be + possible for Orchestra to be integrated with any appropriate such framework it + initially supports only Spring 2.x. This is no great drawback as there are many + other good reasons to use Spring! In the remainder of this document we shall + assume Spring is the dependency-injection framework being used. +

+ +

+ Various other projects (JBoss Seam, Apache Shale Dialogs, Spring WebFlow) provide + conversation/dialog support that is similar to Orchestra. See the Orchestra wiki pages + for up-to-date comparisons of Orchestra with other projects. +

+
+ +
+

+ The normal behaviour for JSF is that when an EL expression references a + bean that cannot be found anywhere in the current scopes, the managed bean + declarations are searched for the specified name. If a match is found then + the bean declaration is used to create an appropriate object instance and + insert it into the appropriate scope. The JSF standard provides a way for + variable lookup to be extended, and Spring provides an adapter that makes Spring + bean declarations accessable to JSF just like managed beans declared in the standard manner. +

+ +

+ While "managed beans" declared using the standard JSF syntax can only be declared with + app, session or request scope it is possible with Spring 2.0 to declare custom scopes. + Orchestra makes "conversation scopes" available for use. When a bean is instantiated + which is declared to be part of "conversation Foo" then the conversation with that name + is looked up and the bean inserted into it. This scope is user-specific (ie is a child + of the session scope) and is created if it doesn't yet exist. +

+ +

+ So far, the effect is just the same as using session scope for these beans. + However a conversation acts as a container for all the beans configured + with a particular conversation name. When a conversation ends, all beans + associated with that conversation can then be discarded together which is + difficult to achieve with simple session storage. A conversation can be + terminated in a number of ways: +

    +
  • access-scoped conversations end when a request occurs that does not access any bean in that conversation;

  • +
  • a JSF endConversation component is provided that can be inserted into a page;

  • +
  • a direct call can be made from a backing bean, eg after performing a "save" or "cancel" operation;

  • +
  • a conversation timeout can be configured to automatically expire conversations after a specified time limit.

  • +
+ And as conversations have names, multiple conversations (bean groupings) can exist concurrently. +

+ +

+ Conversation names are declared simply by specifying attribute orchestra:conversationName on + the Spring bean definition. If no name is provided, then the bean is placed in its own + private conversation (which happens to have a name equal to the bean name). +

+ +

+ A conversation can have a lifetime of "access" or "manual". + An access-scoped conversation is automatically ended (ie deleted) if a request is executed + which does not reference any bean in that conversation's scope. This is + very convenient when a sequence of pages all have at least one reference + to a bean of that conversation scope. If the user navigates to any other + page (via direct url entry, or clicking a link, etc) then after that new page is + rendered the old (obsolete) conversation scope is automatically discarded. Only + when a user's path through the application can reference pages that do not reference + conversation-scoped beans is the "manual" conversation necessary - and in that case, an + explicit endConversation component (or direct API call) must be used to discard beans + when no longer needed. +

+ +

+ Orchestra also provides the concept of a "conversation context", which holds + a set of named conversations. A "separateConversationContext" JSF component + creates a new context. When this is a parent of any command component + (eg a commandLink) then a new conversation context is automatically + created when that command is executed. This allows multiple windows + to access the same site while having completely independent sets of + objects that are of "conversation scope". A hidden "id" emitted into + pages specifies what the current conversation context is, ensuring the + new windows "sticks" with its associated conversation context. +

+
+
+

+ Conversation-scoped beans are always stored (indirectly) in the user's http session. + This means that Orchestra requires server-side storage. +

+
+
+

+ The JBoss Seam library also provides a conversation scope. The purpose of this + scope is the same in Orchestra and Seam, but the details are a little different. + We aren't Seam experts, so this section is just our best attempt at describing + the fundamental differences; please contact the mailing list if you are a Seam + expert and have corrections for this section... +

+

+ Seam's conversations are "request-centric", ie a request always has an associated + conversation (which may be "transient", ie of request scope!). Beans can be bound + to the current conversation via "out-jection" annotations. Therefore it makes sense + to ask "what is the current conversation for this request" from anywhere, even when + the object making the call is not "in" a conversation. +

+

+ Orchestra instead is "bean-centric", ie a bean instance may have an associated + conversation, but a request does not. A request can access multiple beans, and each + of those beans can potentially be in a different conversation. A method can ask + "what conversation am I being invoked in", ie what conversation-scoped bean has + invoked the current method (and the answer may be "none"). Note that having + multiple conversations is really useful for pages where different parts of the page + (different "panels") have different lifetimes. +

+

+ Seam's concept of "nested" conversations isn't generally needed in Orchestra, as + Orchestra supports multiple concurrent conversations (each with a separate "name"). + In the case where a page calls itself, Orchestra does then need to "nest" data, + as the beans will try to use the same conversation. In this case, a nested + conversation-context must be used. +

+

+ Seam uses an @Begin annotation on a method (or a non-standard "begin-conversation" + JSF navigation rule) to create a long-lived conversation. Orchestra does it automatically; + whenever an instance of a bean is created which is marked as being in a conversation "foo" + then conversation "foo" starts. Seam uses out-jection annotations to indicate which beans + belong in the conversation; instead with Orchestra the bean declarations themselves indicate + which conversation the bean instance is in. +

+

+ Both Seam and Orchestra need a mechanism to end a conversation. For Orchestra's + "manual-lifetime" conversations, the o:endConversation tag or a call to method + Conversation.getCurrentInstance().invalidate() are pretty much equivalent to the + Seam @End annotation. For Orchestra's "access-lifetime" conversations, the conversation + is terminated automatically; we are not aware of any Seam equivalent for this. +

+

+ Seam's conversation-context is almost identical to Orchestra's conversation-context. + However with Seam, pages need to explicitly include the context id into urls, by + using EL expression #{conversation.id} or the s:conversationPropagation tag where + appropriate. Orchestra automatically does this; instead, only links that should not + propagate the conversation context need to be marked (using the o:separateConversationContext + tag). This works for all JSF components as long as they call ExternalContext.encodeURL(), + which all code that generates URLs should do. +

+

+ Seam's "conversation switcher" functionality is equivalent to switching between different + Orchestra "conversation contexts". +

+
+
+

+ The Spring WebFlow library also provides a conversation scope. The purpose of this + scope is the same in Orchestra and Seam, but the details are a little different. +

+

+ WebFlow appears to have a similar approach to Seam (request-centric rather than + Orchestra's bean-centric approach). See the first couple of paragraphs above + describing the Seam/Orchestra differences for the implications of this. +

+
+ +
Propchange: myfaces/orchestra/trunk/maven/src/site/xdoc/conversation.xml ------------------------------------------------------------------------------ svn:eol-style = native Added: myfaces/orchestra/trunk/maven/src/site/xdoc/faqs.xml URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/maven/src/site/xdoc/faqs.xml?rev=1326868&view=auto ============================================================================== --- myfaces/orchestra/trunk/maven/src/site/xdoc/faqs.xml (added) +++ myfaces/orchestra/trunk/maven/src/site/xdoc/faqs.xml Tue Apr 17 01:29:52 2012 @@ -0,0 +1,120 @@ + + + + + + + Apache MyFaces Orchestra - FAQs + + + +
+ + + +

+ Depending on your environment and used JPA-implementation you might experience the problem + that there are database connections which have not been passed back to the connection pool.
+ This can happen if you use entities with e.g. OneToMany mappings and lazy init AND accessing the + OneToMany collection from your JSF view the first time.
+ The EntityManager has to re-establish a connection to your database, but now that this happens + outside of your conversation scoped bean, no one ends the transaction and so no one puts the + connection back to the pool.
+ The problem is that with a growing number of users and a growing number of conversations + (especially not ended conversations - waiting for their timeout) your pool might exhaust.
+ As said before, this might not be the case with all JPA-implementations. But we had at least + one environment where this happened, so here the work-around. +

+

+ To activate the workaround simply put the following code in your spring config and adjust the + names as required. + +

+<bean id="managedDataSource" class="org.apache.myfaces.orchestra.connectionManager.ConnectionManagerDataSource">
+  <property name="dataSource" ref="dataSource"/>
+</bean>
+          
+ + The basic principle is to put a virtual DataSource between the JPA-implementation and + the read DataSource (which should be a connection pool for performance reasons).
+ + You have to configure +
    +
  • the property dataSource to point to the original datasource and

  • +
  • the JPA configuration to use our managedDataSource (adjust the name if required)

  • +
+

+
+ + +

+ Use the <aop:scoped-proxy> configuratino with in the + persistentContextConversationInterceptor definition. + You'll end up with something like: +

+<bean id="persistentContextConversationInterceptor" class="org.apache.myfaces.orchestra.conversation.spring.PersistenceContextConversationInterceptor">
+    <aop:scoped-proxy/>
+    <property name="persistenceContextFactory" ref="persistentContextFactory"/>
+</bean>
+          
+

+

+ The reason is, that, during startup of the spring system when the custom scope will + be initialized, the system might already require a datasource, but at this time + the PropertyPlaceholderConfigurer didn't run already.
+ Using the <aop:scoped-proxy> configuration allows the initialization + process to end cleanly. +

+
+ + +

+ If your ViewController event methods are called twice you probably configured the + ViewControllerPhaseListener in your faces-config.xml which is not required.
+ Orchestra already does this for you. +

+
+ + +


No!

+

+ Each conversation has its own persistence context, but an entity can only be managed + by the context it was loaded by. +
+ Reading an entity may trigger lazy loads. This will always be performed using the + persistence context that loaded the entity, ie this works regardless of who calls + the method on the entity. +
+ However performing operations like merge, delete, etc. require the object to be + passed to a persistence context; if it is passed to the wrong one then unexpected + behaviour will occur. Things like using the object in a query being executed in + a persistence context that is not the one associated with that entity may also + fail. +
+ Rather than passing entity references between conversations, just pass the key of the + object and reload it if access is required from a different conversation. +
+ This is not an Orchestra limitation, but more a technical limitation of how ORMs work today. +

+
+
+ +
Propchange: myfaces/orchestra/trunk/maven/src/site/xdoc/faqs.xml ------------------------------------------------------------------------------ svn:eol-style = native Added: myfaces/orchestra/trunk/maven/src/site/xdoc/glossary.xml URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/maven/src/site/xdoc/glossary.xml?rev=1326868&view=auto ============================================================================== --- myfaces/orchestra/trunk/maven/src/site/xdoc/glossary.xml (added) +++ myfaces/orchestra/trunk/maven/src/site/xdoc/glossary.xml Tue Apr 17 01:29:52 2012 @@ -0,0 +1,172 @@ + + + + + + + Apache MyFaces Orchestra - Glossary + + + +
+
    +
  • POJO +
    + A plain-old-Java-object, according to the Java bean standard. + This is a class with (mostly) private members and a get- and set-method + (also called getter and setter) for each of them. The original aim + of object-relational mapping tools was to persist such pojos into the database with the + help of e.g. an external xml configuration per pojo. When Java 5 came + up this changed a bit, now it is common to use annotations in the Java + source itself. With that, strictly spoken, beans are not pojos anymore. +
  • + +
  • Entity +
    + A pojo with an extended description. The description allows the entitiy + manger to persist the entity into the database. Common + descriptions are XML files or annotations in the Java source. This + data is called metadata. +
  • + +
  • Property +
    + A property is a member variable of your pojo with a defined + set and get method. You have to follow the Java Bean + specification. The following examples show this syntax - + the first column, named property, shows how you would access + this property from the outside (e.g. via reflection or from a JSF-JSP-page). + The second column shows the syntax of defining the member, the next columns + the name of getter and setter. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    propertymembergettersetter
    userIdprivate String userIdgetUserIdsetUserId
    userNameprivate String _userNamegetUserNamesetUserName
    displayedprivate boolean displayedisDisplayedsetDisplayed
    +
  • + +
  • Entity Manager +
    + The "entity manager" manages all your entities, + keeps track of property updates and issues the database statements + required to synchronize the entity state with the database. If you + close an entity manager you will loose the coupling between its + internal state and your entities, they are so called "detached objects" + afterwards. +
  • + +
  • Entity Manager Factory +
    + The "entity manager factory" is + responsible for processing all the entity metadata and to create an + entity manager based on it. +
  • + +
  • DAO - Data Access Object +
    + Usage of data access objects is based on the pattern with the same name. Data access + objects are singletons which contain + all of the database requests your application will issue - generally, one data access object + encapsulates all database requests for one entity. + Thus, the DAO is injected with an entity + manager. +
  • + +
  • Conversation +
    + A conversation is the time-span encapsulating all the + operations in your business logic required to finish a process + (in the end, this will almost always include the need for executing database transactions). + Other names of this principle are: application transaction, unit-of-work +
  • + +
  • Session Scope +
    + The session scope of your servlet container. + Beans put into this scope live until the configured inactivity timout + for the session has been reached or the session is closed explicitly +
  • + +
  • Request Scope +
    + The request scope of your servlet container. + The lifetime of request-scoped-beans is as long as the duration of a + single HTTP request. Once the servlet container finishes sending + the page data, the request will die and with it all the beans put into + this scope. +
  • + +
  • JPA - Java Persistence API +
    + The JPA standardizes the way how + you annotate your entities with regards to persistence. That way you can change the + ORM tool as long as the ORM tool follows the JPA + specification. +
  • + +
  • backing bean +
    + A backing bean is the bean behind a JSF view + (jsp, facelet, etc page). While JSF does not require such a bean, it is + good practice to provide one backing-bean per page as a rule of thumb. +
  • +
+
+ +
Propchange: myfaces/orchestra/trunk/maven/src/site/xdoc/glossary.xml ------------------------------------------------------------------------------ svn:eol-style = native Added: myfaces/orchestra/trunk/maven/src/site/xdoc/implementation.xml URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/maven/src/site/xdoc/implementation.xml?rev=1326868&view=auto ============================================================================== --- myfaces/orchestra/trunk/maven/src/site/xdoc/implementation.xml (added) +++ myfaces/orchestra/trunk/maven/src/site/xdoc/implementation.xml Tue Apr 17 01:29:52 2012 @@ -0,0 +1,227 @@ + + + + + + + Apache MyFaces Orchestra - Implementation Details + + + +
+

+ To understand what features Orchestra can provide, and what its limitations are, + it can be helpful to understand how it works. This is entirely optional, and + you can skip this section if you wish. +

+

+ Please note that the information in this section describes how the current + implementation works. This is subject to change in future releases. +

+
+
+

+ Orchestra uses object "proxies" that intercept calls to real beans in order to + track data flows and to redirect them as appropriate. +

+

+ When a bean is configured to live in an Orchestra scope, any time an instance + of that bean is created then what is returned is not a reference to the actual + type, but instead a proxy object. The proxy object is of the same type (ie + "x instanceof TheExpectedType" will return true). If you use getClass() on the + proxy object, it may show that the proxy is a subclass of the expected type + (depending on how the proxying is implemented). However in most cases this doesn't + matter; the proxy can be treated exactly as if it was of the expected type, and of + course provides all the same methods that the expected type supports. +

+

+ Of course this relies upon instances being created in a way that Orchestra can + intercept in order to create the proxy object. The most common usage is expected + to be JSF with Spring; in this setup a custom JSF VariableResolver is automatically + registered so that EL expressions such as "#{myBean}" cause Spring to handle the + lookup, and Orchestra's Spring scope-handler will then automatically proxy the bean. + However other presentation-tier approaches (eg plain jsp or servlets) and other + bean-management implementations (such as Google Guice) should be usable with + Orchestra as long as there is a mechanism for the appropriate proxies to be + created when needed. +

+

+ The proxy has two distinct functions: to direct calls to an appropriate "real" + underlying bean (similar to Spring's aop:scoped-proxy), and to run an arbitrary + set of "advices" around each method call on the proxy. In particular, an advice is + used to implement Orchestra's persistence support (see later). +

+
+
+

+ The proxy object returned by orchestra during a bean lookup does not directly hold + a reference to the underlying bean. Instead it just keeps: +

    +
  • a reference to a Scope object
  • +
  • a conversation-name string
  • +
  • a bean-name string
  • +
+

+

+ Invoking any method on the proxy object causes it to: +

    +
  • fetch the ConversationManager object for the current user
  • +
  • fetch the current ConversationContext for the user's current window
  • +
  • fetch the correct Conversation instance (using the conversation-name)
  • +
  • + fetch the correct target object from the Conversation (using bean-name), + or (if the instance does not yet exist) create an instance and store it in the + conversation. +
  • +
+ Then the originally invoked method is forwarded to the target object that was found. +

+

+ Any call on a method of the proxy will therefore be forwarded to an instance that is + stored in a specific Conversation object. If the Conversation object is deleted, then + invoking a method on the proxy will just create a new Conversation instance and a + new instance of the target bean. Because of this, proxy objects can be retained + for any length of time; they never point to "stale" objects. This in turn allows + Orchestra to discard conversation objects at appropriate times without breaking + code holding references to those objects. +

+

+ There is of course a performance penalty for this; invoking a method on a + conversation-scoped object (via its proxy) require a couple of hashmap lookups to + locate the target object, plus whatever internal overhead the proxying library + (currently CGLIB) adds. +

+

+ Note that in Orchestra Core 1.0 a spring aop:scoped-proxy tag was needed on bean + definitions in order to enable the above functionality. Orchestra does function + without the indirection feature, but code must then be careful not to store any such + references for later use; instead beans can only be referenced via EL expressions. + It was strongly recommended in Orchestra 1.0 that aop:scoped-proxy be added to + each conversation-scoped bean definition and it is now automatic in Orchestra + Core 1.1. +

+
+
+

+ Conversations are stored within a ConversationContext which is stored within a + ConversationManager which is in turn stored within an HttpSession. +

+

+ A conversation and its associated data therefore lasts as long as the user's + session object, unless explicitly deleted by Orchestra. +

+
+
+

+ When a proxy is invoked, and retrieves a target bean from a specific conversation + it also marks the conversation as "accessed". This allows Orchestra to determine + whether a conversation is currently "in use", or whether the user has navigated off + to some other part of the webapp. When the conversation is marked as "access" scope, + and is not in use then it is simple to detect this and discard the conversation + (together with all the bean instances that are stored in it). +

+

+ Because proxies simply trigger the creation of new instances (and a conversation to + hold it) when needed, a user returning to an "access scope" page simply causes a + "fresh" version of the page state to be created. +

+

+ This approach is quite different from some other libraries that provide conversation + scope. In particular, it does not require any elaborate flow-control state charts + to control navigation. With Orchestra the detection of beans that are no longer in + use is completely automatic. +

+
+
+

+ With manual scope, Conversation instances are only deleted when application code + makes an explicit call to the Orchestra API, or when a JSF tag in a page makes + that call. The application therefore itself determines when a set of beans + (ie a conversation) is no longer needed. The implementation of this is obvious: + a ConversationContext object holds a map of conversations by name, and this + just removes the appropriate (name, Conversation) entry from that map. All the + beans in the conversation then become elegible for garbage-collection. Note + that Orchestra provides an option for beans in a conversation to be notified + when the conversation is terminated, which provides a kind of "destructor" + opportunity. +

+
+
+

+ Each conversation has a name. By default, a conversation-scoped bean will be + placed in a conversation whose name is the bean-name used to retrieve that bean + from the dependency-injection system (Spring or other). Therefore by default + each conversation has only one bean in it. +

+

+ Configuring a group of beans to belong to the same conversation is quite + useful with both Access and Manual scopes. To do this, simply ensure that the + configuration on the bean declaration specifies a conversation name. The + Conversation object has a Map of the objects in it, and so therefore can + hold any number of different beans, keyed by their bean-name. +

+
+
+

+ An http session is typically maintained via a "cookie" that identifies the session + to be used for each request. A web-browser can open multiple windows or tabs which + share the same cookies; in this situation requests from different windows will all + use the same http-session on the server, and therefore access exactly the same + instances of session-scoped objects. +

+

+ Unfortunately reusing session-scoped objects for completely unrelated requests + coming from different windows or tabs of a user's browser can cause nasty problems. +

+

+ The Java Servlet standard does not support more than one session per user. However + Orchestra effectively provides this by keeping conversation objects as children of + a ConversationContext object. All that is needed is for each window to specify a + different ConversationContext object to use. Further documentation on this feature + can be found elsewhere on the Orchestra site. +

+
+
+

+ Each conversation can optionally have a PersistenceContext associated with it. When + this is configured, then after a proxy has been invoked and has determined which + conversation the target bean is in, it configures the PersistenceContext associated + with that conversation as "the global persistence context". Any persistence operations + performed by the target bean (or the ordinary instances it calls) therefore run in + the context of the persistence context for that conversation. When the method on the + target bean returns, the proxy restores the previous persistence context. +

+

+ Conversation instances are stored (indirectly) in the user session, so the persistence + context objects last across multiple requests, and are only discarded when the associated + conversation object is discarded. This allows "long running" persistence operations. +

+

+ As noted elsewhere, this is useful only in applications where the database access and + the web presentation logic exist in the same physical tier. This is common for + small to medium applications, but the largest and most security-sensitive applications + typically keep database access logic in a separate tier and therefore this Orchestra + feature cannot be applied. However there are many single-tier applications where this + functionality can save a lot of developer time and effort. +

+
+ +
Propchange: myfaces/orchestra/trunk/maven/src/site/xdoc/implementation.xml ------------------------------------------------------------------------------ svn:eol-style = native