[jboss-cvs] jboss-seam/doc/reference/en/modules ...
Gavin King
gavin.king at jboss.com
Sun Oct 15 19:43:10 EDT 2006
User: gavin
Date: 06/10/15 19:43:10
Modified: doc/reference/en/modules concepts.xml
Log:
update to Seam 1.1
Revision Changes Path
1.33 +235 -22 jboss-seam/doc/reference/en/modules/concepts.xml
(In the diff below, changes in quantity of whitespace are not shown.)
Index: concepts.xml
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/doc/reference/en/modules/concepts.xml,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -b -r1.32 -r1.33
--- concepts.xml 25 Sep 2006 03:36:15 -0000 1.32
+++ concepts.xml 15 Oct 2006 23:43:10 -0000 1.33
@@ -155,6 +155,10 @@
grow without bound if the user abandons conversations.
</para>
<para>
+ Seam serializes processing of concurrent requests that take place in the same long-running
+ conversation context, in the same process.
+ </para>
+ <para>
Alternatively, Seam may be configured to keep conversational state in the client browser.
</para>
</sect2>
@@ -268,6 +272,44 @@
</sect2>
+ <sect2>
+ <title>Concurrency model</title>
+ <para>
+ Neither the servlet nor EJB specifications define any facilities for managing concurrent requests
+ originating from the same client. The servlet container simply lets all threads run concurrently
+ and leaves enforcing threadsafeness to application code. The EJB container allows stateless
+ components to be accessed concurrently, and throws an exception if multiple threads access a
+ stateful session bean.
+ </para>
+ <para>
+ This behavior might have been okay in old-style web applications which were based around fine-grained,
+ synchronous requests. But for modern applications which make heavy use of many fine-grained,
+ asynchronous (AJAX) requests, concurrency is a fact of life, and must be supported by the programming
+ model. Seam weaves a concurrency management layer into its context model.
+ </para>
+ <para>
+ The Seam session and application contexts are multithreaded. Seam will allow concurrent requests
+ in a context to be processed concurrently. The event and page contexts are by nature single threaded.
+ The business process context is strictly speaking multi-threaded, but in practice concurrency
+ is sufficiently rare that this fact may be disregarded most of the time. Finally, Seam enforces a
+ <emphasis>single thread per conversation per process</emphasis> model for the conversation context by
+ serializing concurrent requests in the same long-running conversation context.
+ </para>
+ <para>
+ Since the session context is multithreaded, and often contains volatile state, session scope components
+ are always protected by Seam from concurrent access. Seam serializes requests to session scope session
+ beans and JavaBeans by default (and detects and breaks any deadlocks that occur). This is not the default
+ behaviour for application scoped components however, since application scoped components do not usually
+ hold volatile state and because synchronization at the global level is <emphasis>extremely</emphasis>
+ expensive. However, you can force a serialized threading model on any session bean or JavaBean component by
+ adding the <literal>@Synchronized</literal> annotation.
+ </para>
+ <para>
+ This concurrency model means that AJAX clients can safely use volatile session and conversational state,
+ without the need for any special work on the part of the developer.
+ </para>
+ </sect2>
+
</sect1>
<sect1>
@@ -343,6 +385,9 @@
By default, stateful session beans are bound to the conversation context. They may never
be bound to the page or stateless contexts.
</para>
+ <para>
+ Concurrent requests to session-scoped stateful session beans are always serialized by Seam.
+ </para>
</sect2>
<sect2>
@@ -367,6 +412,12 @@
By default, entity beans are bound to the conversation context. They may never be bound to
the stateless context.
</para>
+ <para>
+ Note that it in a clustered environment is somewhat less efficient to bind an entity bean
+ directly to a conversation or session scoped Seam context variable than it would be to hold
+ a reference to the entity bean in a stateful session bean. For this reason, not all Seam
+ applications define entity beans to be Seam components.
+ </para>
</sect2>
<sect2>
@@ -374,16 +425,22 @@
<para>
Javabeans may be used just like a stateless or stateful session bean. However, they do
not provide the functionality of a session bean (declarative transaction demarcation,
- declarative security, automatic clustered state replication, EJB 3.0 persistence,
+ declarative security, efficient clustered state replication, EJB 3.0 persistence,
timeout methods, etc).
</para>
<para>
- In a later chapter, we show you how to use Seam and Hibernate without an EJB
- container. In this use case, components are JavaBeans instead of session beans.
+ In a later chapter, we show you how to use Seam and Hibernate without an EJB container.
+ In this use case, components are JavaBeans instead of session beans. Note, however, that
+ in many application servers it is somewhat less efficient to cluster conversation or
+ session scoped Seam JavaBean components than it is to cluster stateful session bean
+ components.
</para>
<para>
By default, JavaBeans are bound to the event context.
</para>
+ <para>
+ Concurrent requests to session-scoped JavaBeans are always serialized by Seam.
+ </para>
</sect2>
<sect2>
@@ -395,8 +452,8 @@
</para>
<para>
Message-driven beans may not be bound to a Seam context. Nor do they have access to
- any Seam contexts apart from the <literal>EVENT</literal> and <literal>APPLICATION</literal>
- contexts. However, they do support bijection and some other Seam functionality.
+ the session or conversation state of their "caller". However, they do support bijection
+ and some other Seam functionality.
</para>
</sect2>
@@ -421,6 +478,19 @@
But a much better way is to define the interceptor in <literal>ejb-jar.xml</literal>.
</para>
+ <programlisting><![CDATA[<interceptors>
+ <interceptor>
+ <interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
+ </interceptor>
+</interceptors>
+
+<assembly-descriptor>
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+ <interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
+ </interceptor-binding>
+</assembly-descriptor>]]></programlisting>
+
</sect2>
<sect2>
@@ -539,6 +609,87 @@
</sect2>
<sect2>
+ <title>The <literal>Mutable</literal> interface</title>
+ <para>
+ Many application servers feature an amazingly broken implementation of
+ <literal>HttpSession</literal> clustering, where changes to the state of mutable
+ objects bound to the session are only replicated when the application calls
+ <literal>setAttribute()</literal> explicitly. This is a source of bugs that can
+ not effectively be tested for at development time, since they will only manifest
+ when failover occurs. Furthermore, the actual replication message contains the
+ entire serialized object graph bound to the session attribute, which inefficient.
+ </para>
+ <para>
+ Of course, EJB stateful session beans must perform automatic dirty checking and
+ replication of mutable state and a sophisticated EJB container can introduce
+ optimizations such as attribute-level replication. Unfortunately, not all Seam
+ users have the good fortune to be working in an environment that supports EJB 3.0.
+ So, for session and conversation scoped JavaBean and entity bean components,
+ Seam provides an extra layer of cluster-safe state management over the top
+ of the web container session clustering.
+ </para>
+ <para>
+ For session or conversation scoped JavaBean components, Seam automatically forces
+ replication to occur by calling <literal>setAttribute()</literal> once in every
+ request that the component was invoked by the application. Of course, this strategy
+ is inefficient for read-mostly components. You can control this behavior by
+ implementing the <literal>org.jboss.seam.core.Mutable</literal> interface, or by
+ extending <literal>org.jboss.seam.core.AbstractMutable</literal>, and writing
+ your own dirty-checking logic inside the component. For example,
+ </para>
+
+ <programlisting><![CDATA[@Name("account")
+public class Account extends AbstractMutable
+{
+ private BigDecimal balance;
+
+ public void setBalance(BigDecimal balance)
+ {
+ setDirty(this.balance, balance);
+ this.balance = balance;
+ }
+
+ public BigDecimal getBalance()
+ {
+ return balance;
+ }
+
+ ...
+
+}]]></programlisting>
+
+ <para>
+ For session or conversation scoped entity bean components, Seam automatically forces
+ replication to occur by calling <literal>setAttribute()</literal> once in every
+ request. This strategy is not efficient, so session or conversation scope entity
+ beans should be used with care. You can always write a stateful session bean
+ or JavaBean component to "manage" the entity bean instance. For example,
+ </para>
+
+ <programlisting><![CDATA[@Stateful
+ at Name("account")
+public class AccountManager extends AbstractMutable
+{
+ private Account account; // an entity bean
+
+ @Unwrap
+ public void getAccount()
+ {
+ return account;
+ }
+
+ ...
+
+}]]></programlisting>
+
+ <para>
+ Note that the <literal>EntityHome</literal> class in the Seam Framework provides
+ a great example of this pattern.
+ </para>
+
+ </sect2>
+
+ <sect2>
<title>Built-in components</title>
<para>
Like many good frameworks, Seam eats its own dogfood and is implemented mostly as
@@ -608,9 +759,6 @@
<literal>locale</literal> attribute whenever it instantiates the component.
</para>
<para>
- Note that it is not possible to configure entity beans.
- </para>
- <para>
The same mechanism is used to configure Seam itself. For example, to set the conversation
timeout, we provide a value for <literal>org.jboss.seam.core.manager.conversationTimeout</literal>
in <literal>web.xml</literal> or <literal>seam.properties</literal>. (There is a built-in
@@ -622,8 +770,8 @@
<sect2>
<title>Configuring components via <literal>components.xml</literal></title>
<para>
- The <literal>components.xml</literal> is a bit more powerful than property settings. It
- lets you:
+ The <literal>components.xml</literal> file is a bit more powerful than property settings.
+ It lets you:
</para>
<itemizedlist>
@@ -699,15 +847,24 @@
</components>]]></programlisting>
<para>
+ The <literal><factory></literal> declaration lets you specify a
+ value or method binding expression that will be evaluated to initialize
+ the value of a context variable when it is first referenced.
+ </para>
+
+ <programlisting><![CDATA[<components>
+
+ <factory name="contact" method="#{contactManager.loadContact}" scope="CONVERSATION"/>
+
+</components>]]></programlisting>
+
+ <para>
You can create an "alias" (a second name) for a Seam component like so:
</para>
<programlisting><![CDATA[<components>
- <component name="user"
- class="org.jboss.seam.core.Alias">
- <property name="name">actor</property>
- </component>
+ <factory name="user" value="#{actor}" scope="STATELESS"/>
</components>]]></programlisting>
@@ -717,10 +874,7 @@
<programlisting><![CDATA[<components>
- <component name="userName"
- class="org.jboss.seam.core.Alias">
- <property name="expression">#{actor.id}</property>
- </component>
+ <factory name="contact" value="#{contactManager.contact}" scope="STATELESS"/>
</components>]]></programlisting>
@@ -778,8 +932,8 @@
Finally, you may wire together components using a value-binding expression. Note
that this is quite different to injection using <literal>@In</literal>, since it
happens at component instantiation time instead of invocation time. It is
- therefore much more similar to the dependecy injection facilities offered by
- traditional IoC containers like Spring.
+ therefore much more similar to the dependency injection facilities offered by
+ traditional IoC containers like JSF or Spring.
</para>
<programlisting><![CDATA[<component name="policyPricingWorkingMemory"
@@ -1110,6 +1264,13 @@
}]]></programlisting>
<para>
+ EJB interceptors are stateful, with a lifecycle that is the same as the component
+ they intercept. For interceptors which do not need to maintain state, Seam lets
+ you get a performance optimization by specifying
+ <literal>@Interceptor(stateless=true)</literal>.
+ </para>
+
+ <para>
Much of the functionality of Seam is implemented as a set of built-in Seam interceptors,
including the interceptors named in the previous example. You don't have to explicitly
specify these interceptors by annotating your components; they exist for all interceptable
@@ -1120,6 +1281,15 @@
You can even use Seam interceptors with JavaBean components, not just EJB3 beans!
</para>
+ <para>
+ EJB defines interception not only for business methods (using <literal>@AroundInvoke</literal>),
+ but also for the lifecycle methods <literal>@PostConstruct</literal>, <literal>@PreDestroy</literal>,
+ <literal>@PrePassivate</literal> and <literal>@PostActive</literal>. Seam supports all these
+ lifecycle methods on both component and interceptor not only for EJB3 beans, but also for
+ JavaBean components (except <literal>@PreDestroy</literal> which is not meaningful for JavaBean
+ components).
+ </para>
+
</sect1>
<sect1>
@@ -1144,6 +1314,9 @@
<listitem>
<para>Seam component-driven events</para>
</listitem>
+ <listitem>
+ <para>Seam contextual events</para>
+ </listitem>
</itemizedlist>
<para>
@@ -1293,6 +1466,40 @@
</sect2>
+ <sect2>
+ <title>Contextual events</title>
+ <para>
+ Seam defines a number of built-in events that the application can use to
+ perform special kinds of framework integration. The events are:
+ </para>
+
+ <itemizedlist>
+ <listitem><para><literal>org.jboss.seam.preSetVariable.<name></literal> — called when the context variable <name> is set</para></listitem>
+ <listitem><para><literal>org.jboss.seam.postSetVariable.<name></literal> — called when the context variable <name> is set</para></listitem>
+ <listitem><para><literal>org.jboss.seam.preRemoveVariable.<name></literal> — called when the context variable <name> is unset</para></listitem>
+ <listitem><para><literal>org.jboss.seam.postRemoveVariable.<name></literal> — called when the context variable <name> is unset</para></listitem>
+ <listitem><para><literal>org.jboss.seam.preDestroyContext.<SCOPE></literal> — called before the <SCOPE> context is destroyed</para></listitem>
+ <listitem><para><literal>org.jboss.seam.postDestroyContext.<SCOPE></literal> — called after the <SCOPE> context is destroyed</para></listitem>
+ <listitem><para><literal>org.jboss.seam.beginConversation </literal>— called whenever a long-running conversation begins</para></listitem>
+ <listitem><para><literal>org.jboss.seam.endConversation </literal>— called whenever a long-running conversation ends</para></listitem>
+ <listitem><para><literal>org.jboss.seam.beginPageflow.<name> </literal>— called when the pageflow <name> begins</para></listitem>
+ <listitem><para><literal>org.jboss.seam.endPageflow.<name> </literal>— called when the pageflow <name> ends</para></listitem>
+ <listitem><para><literal>org.jboss.seam.createProcess.<name> </literal>— called when the process <name> is created</para></listitem>
+ <listitem><para><literal>org.jboss.seam.endProcess.<name> </literal>— called when the process <name> ends</para></listitem>
+ <listitem><para><literal>org.jboss.seam.initProcess.<name> </literal>— called when the process <name> is associated with the conversation</para></listitem>
+ <listitem><para><literal>org.jboss.seam.initTask.<name> </literal>— called when the task <name> is associated with the conversation</para></listitem>
+ <listitem><para><literal>org.jboss.seam.startTask.<name> </literal>— called when the task <name> is started</para></listitem>
+ <listitem><para><literal>org.jboss.seam.endTask.<name> </literal>— called when the task <name> is ended</para></listitem>
+ <listitem><para><literal>org.jboss.seam.postCreate.<name> </literal>— called when the component <name> is created</para></listitem>
+ <listitem><para><literal>org.jboss.seam.preDestroy.<name> </literal>— called when the component <name> is destroyed</para></listitem>
+ </itemizedlist>
+
+ <para>
+ Seam components may observe any of these events in just the same way they
+ observe component-driven events.
+ </para>
+ </sect2>
+
</sect1>
<sect1>
@@ -1322,6 +1529,11 @@
@ApplicationException(rollback=true)
public class UnrecoverableException extends RuntimeException { ... }]]></programlisting>
+ <para>
+ Note that <literal>@Redirect</literal> does not work for exceptions
+ which occur during the render phase of the JSF lifecycle.
+ </para>
+
</sect1>
<sect1>
@@ -1329,7 +1541,8 @@
<para>
Session bean and entity bean Seam components support all the usual EJB 3.0 lifecycle
callback (<literal>@PostConstruct</literal>, <literal>@PreDestroy</literal>, etc).
- But Seam also defines its own component lifecycle callbacks.
+ Seam extends all of these callbacks except <literal>@PreDestroy</literal> to JavaBean
+ components. But Seam also defines its own component lifecycle callbacks.
</para>
<para>
The <literal>@Create</literal> method is called every time Seam instantiates a
More information about the jboss-cvs-commits
mailing list