You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sk...@apache.org on 2008/02/26 15:10:34 UTC
svn commit: r631219 [2/3] - /myfaces/orchestra/trunk/core/src/site/xdoc/
Modified: myfaces/orchestra/trunk/core/src/site/xdoc/implementation.xml
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/site/xdoc/implementation.xml?rev=631219&r1=631218&r2=631219&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/site/xdoc/implementation.xml (original)
+++ myfaces/orchestra/trunk/core/src/site/xdoc/implementation.xml Tue Feb 26 06:10:33 2008
@@ -1,6 +1,6 @@
<?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">
+ "http://www.apache.org/dtd/xdoc.dtd">
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -21,207 +21,207 @@
-->
<document>
- <properties>
- <title>Apache MyFaces Orchestra - Implementation Details</title>
- </properties>
+ <properties>
+ <title>Apache MyFaces Orchestra - Implementation Details</title>
+ </properties>
- <body>
- <section name="Overview">
- <p>
- 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.
- </p>
- <p>
- Please note that the information in this section describes how the current
- implementation works. This is subject to change in future releases.
- </p>
- </section>
- <section name="Proxies">
- <p>
- Orchestra uses object "proxies" that intercept calls to real beans in order to
- track data flows and to redirect them as appropriate.
- </p>
- <p>
- 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.
- </p>
- <p>
- 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.
- </p>
- <p>
- 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).
- </p>
- </section>
- <section name="Indirection">
- <p>
- The proxy object returned by orchestra during a bean lookup does not directly hold
- a reference to the underlying bean. Instead it just keeps:
- <ul>
- <li>a reference to a Scope object</li>
- <li>a conversation-name string</li>
- <li>a bean-name string</li>
- </ul>
- </p>
- <p>
- Invoking any method on the proxy object causes it to:
- <ul>
- <li>fetch the ConversationManager object for the current user</li>
- <li>fetch the current ConversationContext for the user's current window</li>
- <li>fetch the correct Conversation instance (using the conversation-name)</li>
- <li>
- 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.
- </li>
- </ul>
- Then the originally invoked method is forwarded to the target object that was found.
- </p>
- <p>
- 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.
- </p>
- <p>
- 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.
- </p>
- <p>
- 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.
- </p>
- </section>
- <section name="Storing Conversations">
- <p>
- Conversations are stored within a ConversationContext which is stored within a
- ConversationManager which is in turn stored within an HttpSession.
- </p>
- <p>
- A conversation and its associated data therefore lasts as long as the user's
- session object, unless explicitly deleted by Orchestra.
- </p>
- </section>
- <section name="Access Scope">
- <p>
- 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).
- </p>
- <p>
- 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.
- </p>
- <p>
- 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.
- </p>
- </section>
- <section name="Manual Scope">
- <p>
- 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.
- </p>
- </section>
- <section name="Multiple beans in a single Scope">
- <p>
- 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.
- </p>
- <p>
- 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.
- </p>
- </section>
- <section name="Multiple Window Support">
- <p>
- 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.
- </p>
- <p>
- Unfortunately reusing session-scoped objects for completely unrelated requests
- coming from different windows or tabs of a user's browser can cause nasty problems.
- </p>
- <p>
- 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.
- </p>
- </section>
- <section name="Persistence">
- <p>
- 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.
- </p>
- <p>
- 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.
- </p>
- <p>
- 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.
- </p>
- </section>
- </body>
+ <body>
+ <section name="Overview">
+ <p>
+ 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.
+ </p>
+ <p>
+ Please note that the information in this section describes how the current
+ implementation works. This is subject to change in future releases.
+ </p>
+ </section>
+ <section name="Proxies">
+ <p>
+ Orchestra uses object "proxies" that intercept calls to real beans in order to
+ track data flows and to redirect them as appropriate.
+ </p>
+ <p>
+ 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.
+ </p>
+ <p>
+ 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.
+ </p>
+ <p>
+ 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).
+ </p>
+ </section>
+ <section name="Indirection">
+ <p>
+ The proxy object returned by orchestra during a bean lookup does not directly hold
+ a reference to the underlying bean. Instead it just keeps:
+ <ul>
+ <li>a reference to a Scope object</li>
+ <li>a conversation-name string</li>
+ <li>a bean-name string</li>
+ </ul>
+ </p>
+ <p>
+ Invoking any method on the proxy object causes it to:
+ <ul>
+ <li>fetch the ConversationManager object for the current user</li>
+ <li>fetch the current ConversationContext for the user's current window</li>
+ <li>fetch the correct Conversation instance (using the conversation-name)</li>
+ <li>
+ 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.
+ </li>
+ </ul>
+ Then the originally invoked method is forwarded to the target object that was found.
+ </p>
+ <p>
+ 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.
+ </p>
+ <p>
+ 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.
+ </p>
+ <p>
+ 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.
+ </p>
+ </section>
+ <section name="Storing Conversations">
+ <p>
+ Conversations are stored within a ConversationContext which is stored within a
+ ConversationManager which is in turn stored within an HttpSession.
+ </p>
+ <p>
+ A conversation and its associated data therefore lasts as long as the user's
+ session object, unless explicitly deleted by Orchestra.
+ </p>
+ </section>
+ <section name="Access Scope">
+ <p>
+ 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).
+ </p>
+ <p>
+ 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.
+ </p>
+ <p>
+ 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.
+ </p>
+ </section>
+ <section name="Manual Scope">
+ <p>
+ 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.
+ </p>
+ </section>
+ <section name="Multiple beans in a single Scope">
+ <p>
+ 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.
+ </p>
+ <p>
+ 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.
+ </p>
+ </section>
+ <section name="Multiple Window Support">
+ <p>
+ 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.
+ </p>
+ <p>
+ Unfortunately reusing session-scoped objects for completely unrelated requests
+ coming from different windows or tabs of a user's browser can cause nasty problems.
+ </p>
+ <p>
+ 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.
+ </p>
+ </section>
+ <section name="Persistence">
+ <p>
+ 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.
+ </p>
+ <p>
+ 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.
+ </p>
+ <p>
+ 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.
+ </p>
+ </section>
+ </body>
</document>
Modified: myfaces/orchestra/trunk/core/src/site/xdoc/index.xml
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/site/xdoc/index.xml?rev=631219&r1=631218&r2=631219&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/site/xdoc/index.xml (original)
+++ myfaces/orchestra/trunk/core/src/site/xdoc/index.xml Tue Feb 26 06:10:33 2008
@@ -1,6 +1,6 @@
<?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">
+ "http://www.apache.org/dtd/xdoc.dtd">
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -21,21 +21,21 @@
-->
<document>
- <properties>
- <title>About Apache MyFaces Orchestra - Core</title>
- </properties>
-
- <body>
- <section name="Apache MyFaces Orchestra - Core">
-
- <p>
- The Apache MyFaces Orchestra Core module contains all the stuff not requiring any Java 5.0 feature.
- </p>
-
- <p>
- Please find the documentation in the navigation panel on the left side.
- </p>
+ <properties>
+ <title>About Apache MyFaces Orchestra - Core</title>
+ </properties>
+
+ <body>
+ <section name="Apache MyFaces Orchestra - Core">
+
+ <p>
+ The Apache MyFaces Orchestra Core module contains all the stuff not requiring any Java 5.0 feature.
+ </p>
+
+ <p>
+ Please find the documentation in the navigation panel on the left side.
+ </p>
- </section>
- </body>
+ </section>
+ </body>
</document>
Modified: myfaces/orchestra/trunk/core/src/site/xdoc/installation.xml
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/site/xdoc/installation.xml?rev=631219&r1=631218&r2=631219&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/site/xdoc/installation.xml (original)
+++ myfaces/orchestra/trunk/core/src/site/xdoc/installation.xml Tue Feb 26 06:10:33 2008
@@ -1,6 +1,6 @@
<?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">
+ "http://www.apache.org/dtd/xdoc.dtd">
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -21,69 +21,69 @@
-->
<document>
- <properties>
- <title>Apache MyFaces Orchestra - Installation</title>
- </properties>
-
- <body>
- <section name="Installation">
- In the following, we will assume that you know how to setup
- <ul>
- <li><p>a servlet container (Tomcat, Jetty, etc)</p></li>
- <li><p>your ORM tool (OpenJPA, Toplink.essentials, Hibernate, etc)</p></li>
- <li><p>your JSF implementation (MyFaces, JSF-RI, etc)</p></li>
- </ul>
- <p>
- For a beginner these are big assumptions; none of these technologies are simple.
- However we simply cannot conver these topics in a brief guide. In addition, these
- subjects are covered well elsewhere.
+ <properties>
+ <title>Apache MyFaces Orchestra - Installation</title>
+ </properties>
+
+ <body>
+ <section name="Installation">
+ In the following, we will assume that you know how to setup
+ <ul>
+ <li><p>a servlet container (Tomcat, Jetty, etc)</p></li>
+ <li><p>your ORM tool (OpenJPA, Toplink.essentials, Hibernate, etc)</p></li>
+ <li><p>your JSF implementation (MyFaces, JSF-RI, etc)</p></li>
+ </ul>
+ <p>
+ For a beginner these are big assumptions; none of these technologies are simple.
+ However we simply cannot conver these topics in a brief guide. In addition, these
+ subjects are covered well elsewhere.
</p>
- <p>
+ <p>
For an absolute beginner in using these technologies, we recommend taking a look at the
<a href="http://code.google.com/p/facesgoodies/">Faces-Goodies</a> project - a perfect way
of kickstarting you in the world of JSF, Spring and JPA and then return back to include Apache
Orchestra.
</p>
- <p>
+ <p>
The installation guide will show you how to setup a JPA entity manager for Orchestra (so you are
working with the new JavaPersistence API standard). Later we hope to add chapters on integrating
directly with Hibernate and Toplink.
</p>
- <subsection name="Prerequisites">
- <ul>
- <li><p>Apache MyFaces Orchestra core</p></li>
- <li><p>Apache MyFaces Orchestra core15 (optional; requires java1.5 or later)</p></li>
- <li><p>Spring 2.x</p></li>
- <li><p>a JSF implementation (e.g. JSF-RI, MyFaces)</p></li>
- <li><p>a JPA implementation (e.g. OpenJPA, toplink.essentials (formerly
- Oracle Toplink)</p></li>
- <li><p>and all their dependencies
- <br/>
- This might sound somehow vague; however, the exact names of the necessary libraries
- depends on the JSF and JPA implementation. If you have to setup
- an application architecture like this from scratch it might be best to take a look at our
- examples package, and there in the file "pom.xml" which includes a section on the
+ <subsection name="Prerequisites">
+ <ul>
+ <li><p>Apache MyFaces Orchestra core</p></li>
+ <li><p>Apache MyFaces Orchestra core15 (optional; requires java1.5 or later)</p></li>
+ <li><p>Spring 2.x</p></li>
+ <li><p>a JSF implementation (e.g. JSF-RI, MyFaces)</p></li>
+ <li><p>a JPA implementation (e.g. OpenJPA, toplink.essentials (formerly
+ Oracle Toplink)</p></li>
+ <li><p>and all their dependencies
+ <br/>
+ This might sound somehow vague; however, the exact names of the necessary libraries
+ depends on the JSF and JPA implementation. If you have to setup
+ an application architecture like this from scratch it might be best to take a look at our
+ examples package, and there in the file "pom.xml" which includes a section on the
necessary dependencies.</p>
- </li>
- </ul>
- </subsection>
-
- <subsection name="Spring Configuration">
- <p>
- Apache MyFaces Orchestra uses the powerful Spring framework to provide its conversation scope.
- Spring is a dependency injection framework - just like the JSF managed-bean facility which
- is configured in the faces-config files of traditional JSF applications.
- However Spring offers many very nice additional features, including some that are
- essential for Apache Orchestra. In particular it allows us to create a new scope-type.
- </p>
- <p>
- Lets start with the Spring configuration for the conversation scope and the JPA entity-manager
- factory. This configuration file has to be placed into the WEB-INF directory of your web
- application using the name applicationContext.xml. This can be configured with a
- context-parameter in your web.xml; for more information, take a look at the Spring documentation.
- </p>
- <pre>
+ </li>
+ </ul>
+ </subsection>
+
+ <subsection name="Spring Configuration">
+ <p>
+ Apache MyFaces Orchestra uses the powerful Spring framework to provide its conversation scope.
+ Spring is a dependency injection framework - just like the JSF managed-bean facility which
+ is configured in the faces-config files of traditional JSF applications.
+ However Spring offers many very nice additional features, including some that are
+ essential for Apache Orchestra. In particular it allows us to create a new scope-type.
+ </p>
+ <p>
+ Lets start with the Spring configuration for the conversation scope and the JPA entity-manager
+ factory. This configuration file has to be placed into the WEB-INF directory of your web
+ application using the name applicationContext.xml. This can be configured with a
+ context-parameter in your web.xml; for more information, take a look at the Spring documentation.
+ </p>
+ <pre>
<![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
@@ -170,168 +170,168 @@
</beans>
]]>
</pre>
- <p>
- Basically, all you need to do is copy this configuration segment and paste it
+ <p>
+ Basically, all you need to do is copy this configuration segment and paste it
into your Spring configuration file. Then you'll need to adapt the settings in the element
entityManagerFactory - namely the jpaProperties. For a more detailed explanation, we have
included the following instructions - it is not necessary to read through them.
</p>
- <ul>
- <li>1. initialization of orchestra modules
- <br />
- The Spring import statement will ensure that all <code>spring-orchestra-init.xml</code>
- files are processed. Orchestra sets up some defaults in these init files that are
- necessary for the correct functioning of Orchestra.
- </li>
- <li>2. the conversation scopes
- <br/>
- Here we configure both "conversation.access" and "conversation.manual" as new Spring
- custom scopes. This configuration allows us to use scope="conversation.access"
- or scope="conversation.manual" within our bean declarations. The scope definition
- also allows a number of advices (interceptors) to be configured; advices intercept
- each method call to a bean in that scope. We add an interceptor here to ensure that
- on any call to a bean in that scope the entity manager (aka persistence context) is
- set to be the appropriate one for that conversation.
- <br/>
- If your application does not have to deal with persistence, and you would still like to use
- the conversation scopes you can delete the advices from this configuration.
- <br />
- Optionally you can configure the timeout used to automatically end a conversation.
- The <code>timeout</code> property accepts a numeric value which means a timespan
- in minutes.
- <br />
- Notice: <b>Without this timeout configuration, a manual conversation won't die if you do
- not explicitly end it using the conversation API.</b>
- </li>
-
- <li>3. the "persistence context conversation interceptor"
- <br/>
- This tells spring what class to use for the interceptor specified in the scope
- definitions. This orchestra class does the hard work of keeping the right
- persistence context set up at all times.
- </li>
-
- <li>4. conversation - persistence adapter
- <br/>
- Depending on the ORM tool you want to use you will have to configure an appropriate
- persistenceContextFactory. Apache MyFaces Orchestra provides a JPA implementation
- in its current release; other adapters may be added in the future.
- </li>
-
- <li>5.persistence
- <br/>
- This enables the standard Spring support for persistence annotations such as
- @PersistenceContext; any bean instantiated by spring will be scanned for
- annotations and the appropriate dependencies injected.
- <br/>
- This section also sets up database transaction support.
- <br/>
- As this is all standard Spring functionality, have a look at the Spring
- documentation for further details and options. For our example, we use
- <code><tx:annotation-driven/></code>.
- <br/>
- If you are using Java 1.4 you can choose a non-annotation-based approach.
- </li>
- </ul>
- <p>
- <b>Notice</b>
- : You will be able to configure multiple conversation
- scopes (each one of them will need to have a distinct name)
+ <ul>
+ <li>1. initialization of orchestra modules
+ <br />
+ The Spring import statement will ensure that all <code>spring-orchestra-init.xml</code>
+ files are processed. Orchestra sets up some defaults in these init files that are
+ necessary for the correct functioning of Orchestra.
+ </li>
+ <li>2. the conversation scopes
+ <br/>
+ Here we configure both "conversation.access" and "conversation.manual" as new Spring
+ custom scopes. This configuration allows us to use scope="conversation.access"
+ or scope="conversation.manual" within our bean declarations. The scope definition
+ also allows a number of advices (interceptors) to be configured; advices intercept
+ each method call to a bean in that scope. We add an interceptor here to ensure that
+ on any call to a bean in that scope the entity manager (aka persistence context) is
+ set to be the appropriate one for that conversation.
+ <br/>
+ If your application does not have to deal with persistence, and you would still like to use
+ the conversation scopes you can delete the advices from this configuration.
+ <br />
+ Optionally you can configure the timeout used to automatically end a conversation.
+ The <code>timeout</code> property accepts a numeric value which means a timespan
+ in minutes.
+ <br />
+ Notice: <b>Without this timeout configuration, a manual conversation won't die if you do
+ not explicitly end it using the conversation API.</b>
+ </li>
+
+ <li>3. the "persistence context conversation interceptor"
+ <br/>
+ This tells spring what class to use for the interceptor specified in the scope
+ definitions. This orchestra class does the hard work of keeping the right
+ persistence context set up at all times.
+ </li>
+
+ <li>4. conversation - persistence adapter
+ <br/>
+ Depending on the ORM tool you want to use you will have to configure an appropriate
+ persistenceContextFactory. Apache MyFaces Orchestra provides a JPA implementation
+ in its current release; other adapters may be added in the future.
+ </li>
+
+ <li>5.persistence
+ <br/>
+ This enables the standard Spring support for persistence annotations such as
+ @PersistenceContext; any bean instantiated by spring will be scanned for
+ annotations and the appropriate dependencies injected.
+ <br/>
+ This section also sets up database transaction support.
+ <br/>
+ As this is all standard Spring functionality, have a look at the Spring
+ documentation for further details and options. For our example, we use
+ <code><tx:annotation-driven/></code>.
+ <br/>
+ If you are using Java 1.4 you can choose a non-annotation-based approach.
+ </li>
+ </ul>
+ <p>
+ <b>Notice</b>
+ : You will be able to configure multiple conversation
+ scopes (each one of them will need to have a distinct name)
using different persistence strategies or without persistence at all.
- </p>
- <p>That's all for Spring now -
- according to the JPA specification and your JPA implementation, you will also
- have to provide a META-INF/persistence.xml too. Please check your JPA provider
+ </p>
+ <p>That's all for Spring now -
+ according to the JPA specification and your JPA implementation, you will also
+ have to provide a META-INF/persistence.xml too. Please check your JPA provider
documentation on how to do this.
</p>
- </subsection>
- <subsection name="JSF configuration">
- <p>
- Next you have to add some entries to your web.xml configuration. They are:
- <ul>
- <li><p>the Spring and Apache MyFaces Orchestra listeners</p></li>
- <li><p>the Apache MyFaces Orchestra Filter</p></li>
- </ul>
- </p>
- <p>In the end, the configuration will look like this:</p>
- <pre>
+ </subsection>
+ <subsection name="JSF configuration">
+ <p>
+ Next you have to add some entries to your web.xml configuration. They are:
+ <ul>
+ <li><p>the Spring and Apache MyFaces Orchestra listeners</p></li>
+ <li><p>the Apache MyFaces Orchestra Filter</p></li>
+ </ul>
+ </p>
+ <p>In the end, the configuration will look like this:</p>
+ <pre>
<![CDATA[
<listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
- <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
+ <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
- <listener-class>org.apache.myfaces.orchestra.conversation.servlet.ConversationManagerSessionListener</listener-class>
+ <listener-class>org.apache.myfaces.orchestra.conversation.servlet.ConversationManagerSessionListener</listener-class>
</listener>
]]>
- </pre>
- <p>and</p>
- <pre>
+ </pre>
+ <p>and</p>
+ <pre>
<![CDATA[
<filter>
- <filter-name>orchestraFilter</filter-name>
- <filter-class>org.apache.myfaces.orchestra.conversation.jsf.filter.OrchestraServletFilter</filter-class>
+ <filter-name>orchestraFilter</filter-name>
+ <filter-class>org.apache.myfaces.orchestra.conversation.jsf.filter.OrchestraServletFilter</filter-class>
</filter>
<filter-mapping>
- <filter-name>orchestraFilter</filter-name>
- <url-pattern>*.faces</url-pattern>
+ <filter-name>orchestraFilter</filter-name>
+ <url-pattern>*.faces</url-pattern>
</filter-mapping>
]]>
- </pre>
- <p>
- <b>Notice:</b> Replace the <code>*.faces</code> url-pattern by the one used by your application.
- </p>
- </subsection>
-
- <subsection name="Mixed environment installation">
- <p>
- If your application has only JSF pages then no further configuration is required.
- </p>
- <p>
- However if your application includes jsp, plain servlets, or anything else that
- does not pass through the FacesServlet then two additional filters must be
- defined:
- </p>
+ </pre>
+ <p>
+ <b>Notice:</b> Replace the <code>*.faces</code> url-pattern by the one used by your application.
+ </p>
+ </subsection>
+
+ <subsection name="Mixed environment installation">
+ <p>
+ If your application has only JSF pages then no further configuration is required.
+ </p>
+ <p>
+ However if your application includes jsp, plain servlets, or anything else that
+ does not pass through the FacesServlet then two additional filters must be
+ defined:
+ </p>
<pre>
<![CDATA[
- <filter>
- <filter-name>frameworkAdapterFilter</filter-name>
- <filter-class>org.apache.myfaces.orchestra.frameworkAdapter.basic.BasicFrameworkAdapterFilter</filter-class>
- </filter>
-
- <filter>
- <filter-name>requestParameterFilter</filter-name>
- <filter-class>org.apache.myfaces.orchestra.requestParameterProvider.RequestParameterServletFilter</filter-class>
- </filter>
-
- <filter-mapping>
- <filter-name>frameworkAdapterFilter</filter-name>
- <url-pattern>*.jsp</url-pattern>
- </filter-mapping>
-
- <filter-mapping>
- <filter-name>requestParameterFilter</filter-name>
- <url-pattern>*.jsp</url-pattern>
- </filter-mapping>
+ <filter>
+ <filter-name>frameworkAdapterFilter</filter-name>
+ <filter-class>org.apache.myfaces.orchestra.frameworkAdapter.basic.BasicFrameworkAdapterFilter</filter-class>
+ </filter>
+
+ <filter>
+ <filter-name>requestParameterFilter</filter-name>
+ <filter-class>org.apache.myfaces.orchestra.requestParameterProvider.RequestParameterServletFilter</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>frameworkAdapterFilter</filter-name>
+ <url-pattern>*.jsp</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>requestParameterFilter</filter-name>
+ <url-pattern>*.jsp</url-pattern>
+ </filter-mapping>
]]></pre>
- </subsection>
+ </subsection>
- <subsection name="Conclusion">
- That's all for the basic configuration of Apache MyFaces Orchestra; now you should have
- working conversation scopes and correctly configured persistence. In fact there is nothing
- special in creating the database access objects (DAO) or your business objects (BO). Your
- JSF page backing beans will also look the same - however, you configure them in Spring and
- put them into the conversation scope now, rather than session scope.
- </subsection>
-
- </section>
- <section name="User provided configurations">
- <ul>
- <li><p><a href="alternative-configuration.html">A spring configuration using toplink and load time weaving with tomcat</a></p></li>
- </ul>
- </section>
- </body>
-</document>
\ No newline at end of file
+ <subsection name="Conclusion">
+ That's all for the basic configuration of Apache MyFaces Orchestra; now you should have
+ working conversation scopes and correctly configured persistence. In fact there is nothing
+ special in creating the database access objects (DAO) or your business objects (BO). Your
+ JSF page backing beans will also look the same - however, you configure them in Spring and
+ put them into the conversation scope now, rather than session scope.
+ </subsection>
+
+ </section>
+ <section name="User provided configurations">
+ <ul>
+ <li><p><a href="alternative-configuration.html">A spring configuration using toplink and load time weaving with tomcat</a></p></li>
+ </ul>
+ </section>
+ </body>
+</document>
Modified: myfaces/orchestra/trunk/core/src/site/xdoc/introduction.xml
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/site/xdoc/introduction.xml?rev=631219&r1=631218&r2=631219&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/site/xdoc/introduction.xml (original)
+++ myfaces/orchestra/trunk/core/src/site/xdoc/introduction.xml Tue Feb 26 06:10:33 2008
@@ -1,6 +1,6 @@
<?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">
+ "http://www.apache.org/dtd/xdoc.dtd">
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -21,36 +21,36 @@
-->
<document>
- <properties>
- <title>The Apache MyFaces Orchestra Core Module</title>
- </properties>
+ <properties>
+ <title>The Apache MyFaces Orchestra Core Module</title>
+ </properties>
- <body>
- <section name="Apache MyFaces Orchestra Core">
- <p>The Orchestra Core library provides the following features as described in the
- documentation for the Orchestra project:
- <ul>
- <li><p><a href="conversation.html">Conversation scope</a> (aka dialog scope) for beans.</p></li>
- <li><p><a href="persistence.html">Conversation-scope persistence</a> contexts. This fixes the
- dreaded LazyInitializationException or NonUniqueObjectException problems when working with
- persistent objects.</p></li>
- </ul>
- </p>
- <p>Orchestra Core requires only Java 1.4 and JSF 1.1.</p>
- </section>
- <section name="Important Information">
- <p>
- At the current time, Orchestra is not safe for use with distributed sessions.
- If you need this feature, please contact the development list.
- </p>
- <p>
- Orchestra persistence features presume the presentation tier has access to the database,
- ie that the presentation and database-access tiers are combined. This is often the case
- in small-to-medium web applications. Large or security-sensitive applications which separate
- database access out into an isolated tier (eg use a "full EJB stack") cannot use the Orchestra
- persistence facilities, although they can still make use of the regular conversational support
- for beans in the presentation layer.
- </p>
- </section>
- </body>
+ <body>
+ <section name="Apache MyFaces Orchestra Core">
+ <p>The Orchestra Core library provides the following features as described in the
+ documentation for the Orchestra project:
+ <ul>
+ <li><p><a href="conversation.html">Conversation scope</a> (aka dialog scope) for beans.</p></li>
+ <li><p><a href="persistence.html">Conversation-scope persistence</a> contexts. This fixes the
+ dreaded LazyInitializationException or NonUniqueObjectException problems when working with
+ persistent objects.</p></li>
+ </ul>
+ </p>
+ <p>Orchestra Core requires only Java 1.4 and JSF 1.1.</p>
+ </section>
+ <section name="Important Information">
+ <p>
+ At the current time, Orchestra is not safe for use with distributed sessions.
+ If you need this feature, please contact the development list.
+ </p>
+ <p>
+ Orchestra persistence features presume the presentation tier has access to the database,
+ ie that the presentation and database-access tiers are combined. This is often the case
+ in small-to-medium web applications. Large or security-sensitive applications which separate
+ database access out into an isolated tier (eg use a "full EJB stack") cannot use the Orchestra
+ persistence facilities, although they can still make use of the regular conversational support
+ for beans in the presentation layer.
+ </p>
+ </section>
+ </body>
</document>
Modified: myfaces/orchestra/trunk/core/src/site/xdoc/persistence.xml
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/site/xdoc/persistence.xml?rev=631219&r1=631218&r2=631219&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/site/xdoc/persistence.xml (original)
+++ myfaces/orchestra/trunk/core/src/site/xdoc/persistence.xml Tue Feb 26 06:10:33 2008
@@ -1,6 +1,6 @@
<?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">
+ "http://www.apache.org/dtd/xdoc.dtd">
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -21,220 +21,220 @@
-->
<document>
- <properties>
- <title>Conversation Scoped Persistence</title>
- </properties>
-
- <body>
- <section name="Introduction To Conversation Scoped Persistence">
- <p>Orchestra's persistence support aims to simplify developers life when it comes
- to build web based applications that extensively use ORM persistence including
- JPA (Java Persistence API), Toplink or Hibernate.</p>
- <p>Persistent objects often participate in a conversation (ie a sequence of requests).
- For example, an address-management module may need to read a person from a database
- on the first request of a conversation, then later requests may modify attributes
- and add child records for address, telephone, email, etc. Only at the end of the
- conversation is the data saved back to the database.</p>
- </section>
-
- <section name="The Problem">
- <p>Whoever has web-application development experience with an ORM layer
- has run into exceptions like the dreaded LazyInitializationException which
- occurs when following a relationship from one persistent object to another,
- or the NonUniqueObjectException that occurs if you try to <code>merge</code>
- detached objects back into the persistence session. Most of those problems,
- if not all, result from the fact that a persistence session is opened and closed
- for each HTTP request. In this case, the ORM tool has no chance to manage your
- entities for the duration of a business process - once you close a persistence
- layer session at the end of the HTTP request, all entities are detached from the
- persistence layer session.</p>
- <p>The magic is to keep such a persistence session open as long as required, but
- as short as possible, contrary to the well-known OpenSessionInView or
- OpenSessionPerRequest-patterns. In those patterns, the session is closed too early
- for completing a full business process. Keeping the session alive for exactly the
- necessary timespan is one of the cool features of Apache MyFaces Orchestra.</p>
- <p>The demarcation of such a timespan is defined by a conversation in Orchestra. A
- conversation is completely detached from the pageflow, it doesn't matter if the
- conversation spans multiple requests on a single page or multiple pages.</p>
- <p>A conversation scope is (like the request or session scope) a place where you can
- store your beans. A conversation-scoped bean will have an attached entity manager
- which is in use for each database access until the application ends the conversation.</p>
- </section>
-
- <section name="Quick review of the Java Persistence API (JPA)">
- <p>JPA defines the concept of a "PersistenceContext", aka an EntityManager (or in Hibernate
- terminology, a "Session"). This represents a pool of persistent objects. First the context
- has to be created. Then data can be loaded from the database, causing objects to be created
- and placed in the context. Objects in the context can be modified, and new objects can be
- placed in the context. When entityManager.flush() is called, any modified data in the
- context is written back out to the database.</p>
- <p>When an object is read from the database which has a reference to some other persistent
- object, what happens depends on whether that reference ("relation") is marked as "eager"
- or "lazy":
- <ul>
- <li><p>For eager relations, the associated data is read immediately from the database,
- and an object created to hold it (which is also added to the persistence context). The
- relation can then be followed (ie the reference used) even after the associated
- persistence context is no longer valid, as the object is already in memory.</p></li>
- <li><p>For lazy relations, the reference in the original object points instead at a
- JPA-created proxy object, and only if a method is invoked on the proxy is a database
- operation triggered to load the actual object. Lazy relations are very useful, but mean
- that the relation can only be followed while the persistence context is still valid; if
- the proxy is triggered after the persistence context is no longer valid then a
- LazyInitializationException occurs.</p></li>
- </ul>
- </p>
- <p>A context can be closed (which automatically flushes it). When this happens, all objects in
- the context become "detached"; code that holds references to them can still access the objects.
- However because the context no longer exists, they cannot be written back to the database.
- In addition, any attempt to fetch a related object causes a LazyIntializationException because
- there is no longer a context into which the related object can be fetched.</p>
- <p>Contexts are closed when no longer used because they do take up a lot of memory. The art of
- persistence is to keep contexts around for as long as necessary but no longer. Note that in
- some ORM implementations it is possible to partially discard contexts, ie to remove from the
- context objects that are known to no longer be needed, but that is not a general-purpose
- solution; it is just too hard to manually track exactly what is in use and what is not.</p>
- <p>An object which has been detached (ie whose context has been closed) can be reattached to a
- different context. This allows code to load an object, detach it, modify it and later
- (potentially days later) create a new context, reattach the object then flush the new
- context causing that object to be written to the database. Of course if the database has
- been modified in the meantime then the save will fail.</p>
- <p>The above information about JPA also applies to Hibernate and Toplink, which work in
- a very similar manner.</p>
- </section>
-
- <section name="Using EJBs (separated web tier and business logic)">
- <p>When using the full jee framework, the web and logic tiers are strongly separated, and may be
- on separate physical machines. The logic tier (EJBs) are responsible for performing all
- database access; they use declarative security and other mechanisms to ensure that external
- code (including a web tier, native gui applications, etc) can only read data that they have
- rights to read, and can only modify data via the APIs provided by the EJBs.</p>
- <p>In this case, the web tier has no database connection, and clearly can only navigate relations
- that are present in the serialized data returned by EJBs. In the old days (before JPA),
- fields representing such relationships would simply be null, and accessing them would
- trigger a NullPointerException or similar. If an EJB uses JPA to load objects, then
- returns those objects to a remote client, then any attempt to navigate a relationship
- that is not populated will instead result in a LazyInitializationException; the effect
- is the same but the difference exists because JPA uses proxy objects to implement lazy
- loading. These proxy objects get returned along with the "real" data, but as there is
- no longer a context that the real referenced objects can be loaded into (and no
- database connection to do it with!) they cannot execute.</p>
- <p>In practice, this does mean that the EJB tier has to be very aware of the needs of its
- presentation tier (eg the web tier), but this does seem unavoidable, and is the price
- of the strong separation between business and presentation.</p>
- <p>Because an application using this architecture provides no database connection to
- the web tier, Orchestra <i>can not provide any support for conversation-scoped persistence
- contexts</i>. Orchestra's persistence support is only for use with applications that have
- their business logic and presentation logic in the same tier.</p>
- <p>Note that JBoss Seam provides similar "conversation-scoped" persistence support, but this
- also only applies when the business logic and the presentation logic are in the same
- "tier". When remote EJBs are used to implement interactions with the database then
- there is simply nothing the web tier can do about this.</p>
- </section>
-
- <section name="Single Tier Applications -- Old Style">
- <p>Much code that does not use EJBs is nevertheless written in the stateless-session-bean
- style. When displaying a persistent object a backing bean method will open a
- persistence-context, read the relevant objects into it and then close the context.
- JSF components then render the object, but must be careful not to access any
- relations that were not initialised before the context was closed. A later action
- method which wants to save data will open a new context, reattach the object
- retrieved earlier, flush the context to the database, then close the context again.</p>
- <p>An alternative is to allow the object context to exist for the entire http request,
- closing it only when the request is about to return (after render phase). This is
- referred to as the "Open Session In View" pattern. In this way, the context is cached
- (eg in a thread-local variable) for the duration of the request, and any JSF action
- method that wants to access persistent objects just retrieves that context and uses
- it. This is an extremely useful pattern, with no known drawbacks.</p>
- <p>However with "Open Session In View" the context is still tied to just one request.
- This still exposes the application to potential LazyInitialisationExceptions, as
- follows:
- <ul>
- <li><p>request #1 loads an object from the database and stores it in the http session.
- The page is nicely rendered, and no LazyInitialisationException can occur. The pool
- is closed at the end of the request.</p></li>
- <li><p>request #2 is executed, which tries to display more data from the object that
- is cached in the session. That data is not currently loaded, however, and the
- object is no longer in a context. An exception therefore occurs.</p></li>
- </ul>
- </p>
- </section>
-
- <section name="Single Tier Applications -- With Conversation Scoped Persistence">
- <p>The solution to the problems described above is simply to store the PersistenceContext
- object in the http session, and only close it after the conversation has ended, ie
- when it has been decided to write to the database or abandon any changes made.</p>
- <p>Although the default behaviour of JPA is to close the persistence context when a
- transaction commits or rolls back, this is optional and simply disabling this allows
- the persistence context to be cached over multiple requests. Instead, the db
- connection associated with the persistence context is simply removed from the
- context at the end of each request and returned to the connection pool. At the
- start of the next request a different connection is retrieved from the db pool
- and attached to the persistence context again.</p>
- <p>Note that database transactions still occur; typically a transaction is started
- on the context's connection at the beginning of each request and committed at the
- end of each request. However as long as no flush() operation has been invoked on
- the context, modifications made to objects in the context do not get written to
- disk. Of course it is not possible for a real database transaction to be kept
- open across requests, as that would require the database to keep rows in the
- database locked for as long as the http session lasts (potentially hours), which
- is simply unacceptable.</p>
- <p>There are dangers to this approach; a persistence context can become large if
- many objects have been loaded into it. Care needs to be taken to control the
- amount of persistent data read/written during a conversation. Manual removal
- of objects from the context which are no longer needed can be useful, or
- secondary persistence contexts can be created to perform operations on objects
- that are not needed to be kept in the conversation scope - particularly reads of
- objects that will not be modified as part of the conversation.</p>
- <p>There is also a potential problem when inserting new objects into the context
- which have a database key that is generated via a database write. In this case,
- the database write occurs in the request in which the object was added to the
- context, even though the object's data does not get written until the end of
- the conversation. If the conversation is "rolled back" then the key operation
- remains, as that transaction has long since been committed.</p>
- </section>
-
- <section name="Handling Transactions">
- <p>The scope of a persistence context and database transaction boundaries
- (begin/commit) are separate issues. Multiple database transactions *can*
- occur within the lifetime of a single persistence context. It isn't the
- default - by default, close/rollback will close the associated context.
- However it is possible to disable this default in which case the
- persistence-context can last longer.</p>
- </section>
-
- <section name="How to Use Orchestra Conversation Scoped Persistence">
- <p>When configured appropriately, Spring will automatically scan the beans
- it loads for the standard persistence annotations, and injects a persistence
- context where requested by the bean. Orchestra ensures that the persistence
- context Spring injects is the appropriate one for the current conversation.</p>
- <p>Your code is therefore simply straightforward:<pre>
+ <properties>
+ <title>Conversation Scoped Persistence</title>
+ </properties>
+
+ <body>
+ <section name="Introduction To Conversation Scoped Persistence">
+ <p>Orchestra's persistence support aims to simplify developers life when it comes
+ to build web based applications that extensively use ORM persistence including
+ JPA (Java Persistence API), Toplink or Hibernate.</p>
+ <p>Persistent objects often participate in a conversation (ie a sequence of requests).
+ For example, an address-management module may need to read a person from a database
+ on the first request of a conversation, then later requests may modify attributes
+ and add child records for address, telephone, email, etc. Only at the end of the
+ conversation is the data saved back to the database.</p>
+ </section>
+
+ <section name="The Problem">
+ <p>Whoever has web-application development experience with an ORM layer
+ has run into exceptions like the dreaded LazyInitializationException which
+ occurs when following a relationship from one persistent object to another,
+ or the NonUniqueObjectException that occurs if you try to <code>merge</code>
+ detached objects back into the persistence session. Most of those problems,
+ if not all, result from the fact that a persistence session is opened and closed
+ for each HTTP request. In this case, the ORM tool has no chance to manage your
+ entities for the duration of a business process - once you close a persistence
+ layer session at the end of the HTTP request, all entities are detached from the
+ persistence layer session.</p>
+ <p>The magic is to keep such a persistence session open as long as required, but
+ as short as possible, contrary to the well-known OpenSessionInView or
+ OpenSessionPerRequest-patterns. In those patterns, the session is closed too early
+ for completing a full business process. Keeping the session alive for exactly the
+ necessary timespan is one of the cool features of Apache MyFaces Orchestra.</p>
+ <p>The demarcation of such a timespan is defined by a conversation in Orchestra. A
+ conversation is completely detached from the pageflow, it doesn't matter if the
+ conversation spans multiple requests on a single page or multiple pages.</p>
+ <p>A conversation scope is (like the request or session scope) a place where you can
+ store your beans. A conversation-scoped bean will have an attached entity manager
+ which is in use for each database access until the application ends the conversation.</p>
+ </section>
+
+ <section name="Quick review of the Java Persistence API (JPA)">
+ <p>JPA defines the concept of a "PersistenceContext", aka an EntityManager (or in Hibernate
+ terminology, a "Session"). This represents a pool of persistent objects. First the context
+ has to be created. Then data can be loaded from the database, causing objects to be created
+ and placed in the context. Objects in the context can be modified, and new objects can be
+ placed in the context. When entityManager.flush() is called, any modified data in the
+ context is written back out to the database.</p>
+ <p>When an object is read from the database which has a reference to some other persistent
+ object, what happens depends on whether that reference ("relation") is marked as "eager"
+ or "lazy":
+ <ul>
+ <li><p>For eager relations, the associated data is read immediately from the database,
+ and an object created to hold it (which is also added to the persistence context). The
+ relation can then be followed (ie the reference used) even after the associated
+ persistence context is no longer valid, as the object is already in memory.</p></li>
+ <li><p>For lazy relations, the reference in the original object points instead at a
+ JPA-created proxy object, and only if a method is invoked on the proxy is a database
+ operation triggered to load the actual object. Lazy relations are very useful, but mean
+ that the relation can only be followed while the persistence context is still valid; if
+ the proxy is triggered after the persistence context is no longer valid then a
+ LazyInitializationException occurs.</p></li>
+ </ul>
+ </p>
+ <p>A context can be closed (which automatically flushes it). When this happens, all objects in
+ the context become "detached"; code that holds references to them can still access the objects.
+ However because the context no longer exists, they cannot be written back to the database.
+ In addition, any attempt to fetch a related object causes a LazyIntializationException because
+ there is no longer a context into which the related object can be fetched.</p>
+ <p>Contexts are closed when no longer used because they do take up a lot of memory. The art of
+ persistence is to keep contexts around for as long as necessary but no longer. Note that in
+ some ORM implementations it is possible to partially discard contexts, ie to remove from the
+ context objects that are known to no longer be needed, but that is not a general-purpose
+ solution; it is just too hard to manually track exactly what is in use and what is not.</p>
+ <p>An object which has been detached (ie whose context has been closed) can be reattached to a
+ different context. This allows code to load an object, detach it, modify it and later
+ (potentially days later) create a new context, reattach the object then flush the new
+ context causing that object to be written to the database. Of course if the database has
+ been modified in the meantime then the save will fail.</p>
+ <p>The above information about JPA also applies to Hibernate and Toplink, which work in
+ a very similar manner.</p>
+ </section>
+
+ <section name="Using EJBs (separated web tier and business logic)">
+ <p>When using the full jee framework, the web and logic tiers are strongly separated, and may be
+ on separate physical machines. The logic tier (EJBs) are responsible for performing all
+ database access; they use declarative security and other mechanisms to ensure that external
+ code (including a web tier, native gui applications, etc) can only read data that they have
+ rights to read, and can only modify data via the APIs provided by the EJBs.</p>
+ <p>In this case, the web tier has no database connection, and clearly can only navigate relations
+ that are present in the serialized data returned by EJBs. In the old days (before JPA),
+ fields representing such relationships would simply be null, and accessing them would
+ trigger a NullPointerException or similar. If an EJB uses JPA to load objects, then
+ returns those objects to a remote client, then any attempt to navigate a relationship
+ that is not populated will instead result in a LazyInitializationException; the effect
+ is the same but the difference exists because JPA uses proxy objects to implement lazy
+ loading. These proxy objects get returned along with the "real" data, but as there is
+ no longer a context that the real referenced objects can be loaded into (and no
+ database connection to do it with!) they cannot execute.</p>
+ <p>In practice, this does mean that the EJB tier has to be very aware of the needs of its
+ presentation tier (eg the web tier), but this does seem unavoidable, and is the price
+ of the strong separation between business and presentation.</p>
+ <p>Because an application using this architecture provides no database connection to
+ the web tier, Orchestra <i>can not provide any support for conversation-scoped persistence
+ contexts</i>. Orchestra's persistence support is only for use with applications that have
+ their business logic and presentation logic in the same tier.</p>
+ <p>Note that JBoss Seam provides similar "conversation-scoped" persistence support, but this
+ also only applies when the business logic and the presentation logic are in the same
+ "tier". When remote EJBs are used to implement interactions with the database then
+ there is simply nothing the web tier can do about this.</p>
+ </section>
+
+ <section name="Single Tier Applications -- Old Style">
+ <p>Much code that does not use EJBs is nevertheless written in the stateless-session-bean
+ style. When displaying a persistent object a backing bean method will open a
+ persistence-context, read the relevant objects into it and then close the context.
+ JSF components then render the object, but must be careful not to access any
+ relations that were not initialised before the context was closed. A later action
+ method which wants to save data will open a new context, reattach the object
+ retrieved earlier, flush the context to the database, then close the context again.</p>
+ <p>An alternative is to allow the object context to exist for the entire http request,
+ closing it only when the request is about to return (after render phase). This is
+ referred to as the "Open Session In View" pattern. In this way, the context is cached
+ (eg in a thread-local variable) for the duration of the request, and any JSF action
+ method that wants to access persistent objects just retrieves that context and uses
+ it. This is an extremely useful pattern, with no known drawbacks.</p>
+ <p>However with "Open Session In View" the context is still tied to just one request.
+ This still exposes the application to potential LazyInitialisationExceptions, as
+ follows:
+ <ul>
+ <li><p>request #1 loads an object from the database and stores it in the http session.
+ The page is nicely rendered, and no LazyInitialisationException can occur. The pool
+ is closed at the end of the request.</p></li>
+ <li><p>request #2 is executed, which tries to display more data from the object that
+ is cached in the session. That data is not currently loaded, however, and the
+ object is no longer in a context. An exception therefore occurs.</p></li>
+ </ul>
+ </p>
+ </section>
+
+ <section name="Single Tier Applications -- With Conversation Scoped Persistence">
+ <p>The solution to the problems described above is simply to store the PersistenceContext
+ object in the http session, and only close it after the conversation has ended, ie
+ when it has been decided to write to the database or abandon any changes made.</p>
+ <p>Although the default behaviour of JPA is to close the persistence context when a
+ transaction commits or rolls back, this is optional and simply disabling this allows
+ the persistence context to be cached over multiple requests. Instead, the db
+ connection associated with the persistence context is simply removed from the
+ context at the end of each request and returned to the connection pool. At the
+ start of the next request a different connection is retrieved from the db pool
+ and attached to the persistence context again.</p>
+ <p>Note that database transactions still occur; typically a transaction is started
+ on the context's connection at the beginning of each request and committed at the
+ end of each request. However as long as no flush() operation has been invoked on
+ the context, modifications made to objects in the context do not get written to
+ disk. Of course it is not possible for a real database transaction to be kept
+ open across requests, as that would require the database to keep rows in the
+ database locked for as long as the http session lasts (potentially hours), which
+ is simply unacceptable.</p>
+ <p>There are dangers to this approach; a persistence context can become large if
+ many objects have been loaded into it. Care needs to be taken to control the
+ amount of persistent data read/written during a conversation. Manual removal
+ of objects from the context which are no longer needed can be useful, or
+ secondary persistence contexts can be created to perform operations on objects
+ that are not needed to be kept in the conversation scope - particularly reads of
+ objects that will not be modified as part of the conversation.</p>
+ <p>There is also a potential problem when inserting new objects into the context
+ which have a database key that is generated via a database write. In this case,
+ the database write occurs in the request in which the object was added to the
+ context, even though the object's data does not get written until the end of
+ the conversation. If the conversation is "rolled back" then the key operation
+ remains, as that transaction has long since been committed.</p>
+ </section>
+
+ <section name="Handling Transactions">
+ <p>The scope of a persistence context and database transaction boundaries
+ (begin/commit) are separate issues. Multiple database transactions *can*
+ occur within the lifetime of a single persistence context. It isn't the
+ default - by default, close/rollback will close the associated context.
+ However it is possible to disable this default in which case the
+ persistence-context can last longer.</p>
+ </section>
+
+ <section name="How to Use Orchestra Conversation Scoped Persistence">
+ <p>When configured appropriately, Spring will automatically scan the beans
+ it loads for the standard persistence annotations, and injects a persistence
+ context where requested by the bean. Orchestra ensures that the persistence
+ context Spring injects is the appropriate one for the current conversation.</p>
+ <p>Your code is therefore simply straightforward:<pre>
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
public class ComponentDAO
{
- @PersistenceContext
- private EntityManager entityManager;
- ....
+ @PersistenceContext
+ private EntityManager entityManager;
+ ....
}
- </pre></p>
- <p>Spring's annotation support does require, however, that the class containing
- the annotation be declared as a Spring bean, and instantiated via Spring. This
- means that all code which uses an instance of the above class needs to have it
- injected, rather than using the new() operator to create the instance. Existing
- code therefore may need to be restructured to take advantage of persistence
- annotations with Orchestra. The persistence context object that Spring injects
- is actually a proxy which looks up the correct EntityManager object to use
- on each method call, so it is safe to use singleton scope (Spring's default
- scope). Of course if the class has any other non-static members then the
- scope should be set to "prototype", to avoid conflicts between different
- instances of this class in different conversations.</p>
- </section>
-
- <section name="Documentation Still TODO">
- <p>TODO: document Orchestra's transaction support features</p>
- <p>TODO: is the persistence-context serializable? Are all persistent objects
- in the context always serializable?</p>
- </section>
- </body>
+ </pre></p>
+ <p>Spring's annotation support does require, however, that the class containing
+ the annotation be declared as a Spring bean, and instantiated via Spring. This
+ means that all code which uses an instance of the above class needs to have it
+ injected, rather than using the new() operator to create the instance. Existing
+ code therefore may need to be restructured to take advantage of persistence
+ annotations with Orchestra. The persistence context object that Spring injects
+ is actually a proxy which looks up the correct EntityManager object to use
+ on each method call, so it is safe to use singleton scope (Spring's default
+ scope). Of course if the class has any other non-static members then the
+ scope should be set to "prototype", to avoid conflicts between different
+ instances of this class in different conversations.</p>
+ </section>
+
+ <section name="Documentation Still TODO">
+ <p>TODO: document Orchestra's transaction support features</p>
+ <p>TODO: is the persistence-context serializable? Are all persistent objects
+ in the context always serializable?</p>
+ </section>
+ </body>
</document>
Modified: myfaces/orchestra/trunk/core/src/site/xdoc/todo.xml
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/site/xdoc/todo.xml?rev=631219&r1=631218&r2=631219&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/site/xdoc/todo.xml (original)
+++ myfaces/orchestra/trunk/core/src/site/xdoc/todo.xml Tue Feb 26 06:10:33 2008
@@ -1,6 +1,6 @@
<?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">
+ "http://www.apache.org/dtd/xdoc.dtd">
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -21,15 +21,15 @@
-->
<document>
- <properties>
- <title>Apache MyFaces Orchestra - TODO</title>
- </properties>
+ <properties>
+ <title>Apache MyFaces Orchestra - TODO</title>
+ </properties>
- <body>
- <section name="TODO">
- <ul>
- <li>...</li>
- </ul>
- </section>
- </body>
-</document>
\ No newline at end of file
+ <body>
+ <section name="TODO">
+ <ul>
+ <li>...</li>
+ </ul>
+ </section>
+ </body>
+</document>