[seam-commits] Seam SVN: r13808 - modules/persistence/trunk/docs/src/main/docbook/en-US.
seam-commits at lists.jboss.org
seam-commits at lists.jboss.org
Thu Oct 7 06:57:09 EDT 2010
Author: swd847
Date: 2010-10-07 06:57:09 -0400 (Thu, 07 Oct 2010)
New Revision: 13808
Modified:
modules/persistence/trunk/docs/src/main/docbook/en-US/master.xml
modules/persistence/trunk/docs/src/main/docbook/en-US/persistence-general.xml
Log:
update seam-persistence documentation
Modified: modules/persistence/trunk/docs/src/main/docbook/en-US/master.xml
===================================================================
--- modules/persistence/trunk/docs/src/main/docbook/en-US/master.xml 2010-10-07 10:29:36 UTC (rev 13807)
+++ modules/persistence/trunk/docs/src/main/docbook/en-US/master.xml 2010-10-07 10:57:09 UTC (rev 13808)
@@ -6,6 +6,6 @@
<toc/>
<title>Seam Persistence</title>
- <xi:include href="persistence-introduction.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="persistence-general.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</book>
\ No newline at end of file
Modified: modules/persistence/trunk/docs/src/main/docbook/en-US/persistence-general.xml
===================================================================
--- modules/persistence/trunk/docs/src/main/docbook/en-US/persistence-general.xml 2010-10-07 10:29:36 UTC (rev 13807)
+++ modules/persistence/trunk/docs/src/main/docbook/en-US/persistence-general.xml 2010-10-07 10:57:09 UTC (rev 13808)
@@ -4,48 +4,287 @@
<chapter id="persistence">
<title>Seam Persistence Reference</title>
- <section>
- <title>The Seam Managed Persistence Context</title>
- <para>
- The seam managed persistence context is an EntityManager that has its lifecycle managed by Seam. You configure one as follows:
- </para>
+ <para>
+ Seam provides extensive support for the two most popular persistence
+ architectures for Java: Hibernate3, and the Java Persistence API
+ introduced with EJB 3.0. Seam's unique state-management architecture
+ allows the most sophisticated ORM integration of any web application
+ framework.
+ </para>
- <programlisting role="java">
- at SeamManaged
+ <section>
+ <title>Introduction</title>
+
+ <para>
+ Seam grew out of the frustration of the Hibernate team with the
+ statelessness typical of the previous generation of Java application
+ architectures. The state management architecture of Seam was originally
+ designed to solve problems relating to persistence — in particular
+ problems associated with <emphasis>optimistic transaction processing</emphasis>.
+ Scalable online applications always use optimistic transactions. An atomic
+ (database/JTA) level transaction should not span a user interaction unless
+ the application is designed to support only a very small number of concurrent
+ clients. But almost all interesting work involves first displaying data
+ to a user, and then, slightly later, updating the same data. So Hibernate was
+ designed to support the idea of a persistence context which spanned an
+ optimistic transaction.
+ </para>
+
+ <para>
+ Unfortunately, the so-called "stateless" architectures that preceded Seam and
+ EJB 3.0 had no construct for representing an optimistic transaction. So, instead,
+ these architectures provided persistence contexts scoped to the atomic
+ transaction. Of course, this resulted in many problems for users, and is the
+ cause of the number one user complaint about Hibernate: the dreaded
+ <literal>LazyInitializationException</literal>. What we need is a construct
+ for representing an optimistic transaction in the application tier.
+ </para>
+
+ <para>
+ EJB 3.0 recognizes this problem, and introduces the idea of a stateful
+ component (a stateful session bean) with an <emphasis>extended persistence
+ context</emphasis> scoped to the lifetime of the component. This is a
+ partial solution to the problem (and is a useful construct in and of
+ itself) however there are two problems:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ The lifecycle of the stateful session bean must be managed manually
+ via code in the web tier (it turns out that this is a subtle problem
+ and much more difficult in practice than it sounds).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Propagation of the persistence context between stateful components
+ in the same optimistic transaction is possible, but tricky.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Seam solves the first problem by providing conversations, and stateful
+ session bean components scoped to the conversation. (Most conversations
+ actually represent optimistic transactions in the data layer.) This is
+ sufficient for many simple applications (such as the Seam booking
+ demo) where persistence context propagation is not needed. For more
+ complex applications, with many loosly-interacting components in each
+ conversation, propagation of the persistence context across components
+ becomes an important issue. So Seam extends the persistence context
+ management model of EJB 3.0, to provide conversation-scoped extended
+ persistence contexts.
+ </para>
+
+ </section>
+
+ <section id="persistence.seam-managed-persistence-contexts">
+ <title>Seam-managed persistence contexts</title>
+
+ <para>
+ If you're using Seam outside of a Java EE 5 environment, you can't rely upon the
+ container to manage the persistence context lifecycle for you. Even if you are
+ in an EE 5 environment, you might have a complex application with many loosely
+ coupled components that collaborate together in the scope of a single conversation,
+ and in this case you might find that propagation of the persistence context between
+ component is tricky and error-prone.
+ </para>
+
+ <para>
+ In either case, you'll need to use a <emphasis>managed persistence context</emphasis>
+ (for JPA) or a <emphasis>managed session</emphasis> (for Hibernate) in your components.
+ A Seam-managed persistence context is just a built-in Seam component that manages an
+ instance of <literal>EntityManager</literal> or <literal>Session</literal> in the
+ conversation (or any other) context. You can inject it with <literal>@In</literal>.
+ </para>
+
+ <section>
+ <title>Using a Seam-managed persistence context with JPA</title>
+
+ <programlisting role="java">@SeamManaged
@Produces
@PersistenceUnit
@ConversationScoped
EntityManagerFactory producerField;
- </programlisting>
- <para>
- This is just an ordinary resource producer field as defined by the CDI specification, however the presence of the <literal>@SeamManaged</literal>
- annotation tells seam to create a seam managed persistence context from this <literal>EntityManagerFactory</literal>. This managed
- persistence context can be injected normally, and has the same scope and qualifiers that are specified on the resource producer field.
- </para>
- <note>
- <para>
- The more eagle eyed among you may have noticed that the resource producer field appears to be conversation scoped, which the CDI
- specification does not require containers to support. This is in fact not the case, as the @ConversationScoped annotation is removed
- by the seam persistence portable extension. It only specifies the scope of the created SMPC, not the EntityManagerFactory.
- </para>
- </note>
- <programlisting role="java">
- at Inject
-EntityManager smpc;
- </programlisting>
- <para>
- The seam managed persistence context provides the following features:
- </para>
- <itemizedlist>
- <listitem>Automatic enrollment in the active transaction</listitem>
- <listitem>The ability to use EL in JPA queries</listitem>
- </itemizedlist>
- </section>
- <section>
- <title>Seam Transactions</title>
- <para>Seam provides a lightweight UserTransaction wrapper called SeamTransaction.</para>
- <para>Seam also provides a transaction intercepter. In EE environments the normal <literal>@TransactionAttribute</literal> annotation
- can be used to demarcate transaction boundaries on managed beans, not just EJB's.</para>
-
- </section>
+ </programlisting>
+ <para>
+ This is just an ordinary resource producer field as defined by the CDI specification, however the presence of the <literal>@SeamManaged</literal>
+ annotation tells seam to create a seam managed persistence context from this <literal>EntityManagerFactory</literal>. This managed
+ persistence context can be injected normally, and has the same scope and qualifiers that are specified on the resource producer field.
+ </para>
+ <para>
+ This will work even in a SE environment where <code>@PersistenceUnit</code> injection is not normally supported. This is because
+ the seam persistence extensions will bootstrap the <code>EntityManagerFactory</code> for you.
+ </para>
+ <note>
+ <para>
+ The more eagle eyed among you may have noticed that the resource producer field appears to be conversation scoped, which the CDI
+ specification does not require containers to support. This is in fact not the case, as the @ConversationScoped annotation is removed
+ by the seam persistence portable extension. It only specifies the scope of the created SMPC, not the EntityManagerFactory.
+ </para>
+ </note>
+ <para>
+ Now we can have our <literal>EntityManager</literal> injected using:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Inject EntityManager entityManager;]]></programlisting>
+
+ <warning>
+ <para>
+ If you are using EJB3 and mark your class or method
+ <literal>@TransactionAttribute(REQUIRES_NEW)</literal> then the
+ transaction and persistence context shouldn't be propagated to method
+ calls on this object. However as the Seam-managed persistence
+ context is propagated to any component within the conversation, it
+ will be propagated to methods marked <literal>REQUIRES_NEW</literal>.
+ Therefore, if you mark a method <literal>REQUIRES_NEW</literal> then
+ you should access the entity manager using @PersistenceContext.
+ </para>
+ </warning>
+
+ </section>
+
+ <section>
+ <title>Seam-managed persistence contexts and atomic conversations</title>
+ <para>
+ Persistence contexts scoped to the conversation allows you to program optimistic
+ transactions that span multiple requests to the server without the need to use the
+ <literal>merge()</literal> operation , without the need to re-load
+ data at the beginning of each request, and without the need to wrestle with the
+ <literal>LazyInitializationException</literal> or
+ <literal>NonUniqueObjectException</literal>.
+ </para>
+
+ <para>
+ As with any optimistic transaction management, transaction isolation and consistency
+ can be achieved via use of optimistic locking. Fortunately, both Hibernate and EJB
+ 3.0 make it very easy to use optimistic locking, by providing the
+ <literal>@Version</literal> annotation.
+ </para>
+
+ <para>
+ By default, the persistence context is flushed (synchronized with the database)
+ at the end of each transaction. This is sometimes the desired behavior. But very
+ often, we would prefer that all changes are held in memory and only written to
+ the database when the conversation ends successfully. This allows for truly
+ atomic conversations. As the result of a truly stupid and shortsighted decision
+ by certain non-JBoss, non-Sun and non-Sybase members of the EJB 3.0 expert group,
+ there is currently no simple, usable and portable way to implement atomic
+ conversations using EJB 3.0 persistence. However, Hibernate provides this feature
+ as a vendor extension to the <literal>FlushModeType</literal>s defined by the
+ specification, and it is our expectation that other vendors will soon provide
+ a similar extension.
+ </para>
+
+ <para>
+ Seam lets you specify <literal>FlushModeType.MANUAL</literal> when beginning a
+ conversation. Currently, this works only when Hibernate is the underlying
+ persistence provider, but we plan to support other equivalent vendor extensions.
+ </para>
+
+ <para>
+ TODO: The next section needs to be updated to seam 3.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@In EntityManager em; //a Seam-managed persistence context
+
+ @Begin(flushMode=MANUAL)
+ public void beginClaimWizard() {
+ claim = em.find(Claim.class, claimId);
+ }]]></programlisting>
+
+ <para>
+ Now, the <literal>claim</literal> object remains managed by the persistence context
+ for the rest of the conversation. We can make changes to the claim:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[public void addPartyToClaim() {
+ Party party = ....;
+ claim.addParty(party);
+ }]]></programlisting>
+
+ <para>
+ But these changes will not be flushed to the database until we explicitly force
+ the flush to occur:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@End
+ public void commitClaim() {
+ em.flush();
+ }]]></programlisting>
+
+ <para>
+ Of course, you could set the <literal>flushMode</literal> to <literal>MANUAL</literal>
+ from pages.xml, for example in a navigation rule:
+ </para>
+
+ <programlisting role="XML"><![CDATA[<begin-conversation flush-mode="MANUAL" />]]></programlisting>
+
+ <para>
+ You can set any Seam Managed Persistence Context to use manual flush
+ mode:
+ </para>
+
+ <programlisting><![CDATA[<components xmlns="http://jboss.com/products/seam/components"
+ xmlns:core="http://jboss.com/products/seam/core">
+ <core:manager conversation-timeout="120000" default-flush-mode="manual" />
+ </components>]]></programlisting>
+
+ </section>
+
+
+ <section>
+ <title>Using EL in EJB-QL/HQL</title>
+ <para>
+ Seam proxies the <literal>EntityManager</literal> or <literal>Session</literal>
+ object whenever you use a Seam-managed persistence context or inject a container
+ managed persistence context using <literal>@PersistenceContext</literal>. This
+ lets you use EL expressions in your query strings, safely and efficiently. For
+ example, this:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[User user = em.createQuery("from User where username=#{user.username}")
+ .getSingleResult();]]></programlisting>
+
+ <para>is equivalent to:</para>
+
+ <programlisting role="JAVA"><![CDATA[User user = em.createQuery("from User where username=:username")
+ .setParameter("username", user.getUsername())
+ .getSingleResult();]]></programlisting>
+
+ <para>
+ Of course, you should never, ever write it like this:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[User user = em.createQuery("from User where username=" + user.getUsername()) //BAD!
+ .getSingleResult();]]></programlisting>
+
+ <para>
+ (It is inefficient and vulnerable to SQL injection attacks.)
+ </para>
+
+ </section>
+
+ <section>
+ <title>Setting up the EntityManager</title>
+
+ <para>
+ Sometimes you may want to perform some additional setup on the <code>EntityManager</code> after
+ it has been created. For example, if you are using Hibernate you may want to set a filter. Seam
+ persistence fires a <code>SeamManagedPersistenceContextCreated</code> event when a Seam managed
+ persistence context is created. You can observe this event and perform any setup you require in
+ an observer method. For example:
+ </para>
+
+ <programlisting role="JAVA">public void setupEntityManager(@Observes SeamManagedPersistenceContextCreated event) {
+ Session session = (Session)event.getEntityManager().getDelegate();
+ session.enableFilter("myfilter");
+}
+ </programlisting>
+
+ </section>
+
+ </section>
+
</chapter>
More information about the seam-commits
mailing list