<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Vikash28&#039;s Blog</title>
	<atom:link href="http://vikash28.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://vikash28.wordpress.com</link>
	<description>Just another WordPress.com weblog</description>
	<lastBuildDate>Sat, 31 Dec 2011 10:42:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='vikash28.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Vikash28&#039;s Blog</title>
		<link>http://vikash28.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://vikash28.wordpress.com/osd.xml" title="Vikash28&#039;s Blog" />
	<atom:link rel='hub' href='http://vikash28.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Agile Methodology</title>
		<link>http://vikash28.wordpress.com/2011/11/06/agile-methodology/</link>
		<comments>http://vikash28.wordpress.com/2011/11/06/agile-methodology/#comments</comments>
		<pubDate>Sun, 06 Nov 2011 13:38:16 +0000</pubDate>
		<dc:creator>vikash28</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vikash28.wordpress.com/?p=199</guid>
		<description><![CDATA[<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=199&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=199&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://vikash28.wordpress.com/2011/11/06/agile-methodology/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4093cf2bdffa21a21a476dc8f7079984?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">vikash28</media:title>
		</media:content>
	</item>
		<item>
		<title>ALGORITHMS</title>
		<link>http://vikash28.wordpress.com/2011/09/01/algorithms/</link>
		<comments>http://vikash28.wordpress.com/2011/09/01/algorithms/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 11:11:34 +0000</pubDate>
		<dc:creator>vikash28</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vikash28.wordpress.com/?p=167</guid>
		<description><![CDATA[<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=167&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=167&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://vikash28.wordpress.com/2011/09/01/algorithms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4093cf2bdffa21a21a476dc8f7079984?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">vikash28</media:title>
		</media:content>
	</item>
		<item>
		<title>JBoss Seam</title>
		<link>http://vikash28.wordpress.com/2011/05/08/jboss-seam/</link>
		<comments>http://vikash28.wordpress.com/2011/05/08/jboss-seam/#comments</comments>
		<pubDate>Sun, 08 May 2011 13:18:12 +0000</pubDate>
		<dc:creator>vikash28</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vikash28.wordpress.com/?p=159</guid>
		<description><![CDATA[Que1:What&#8217;s Seam? Ans1:It&#8217;s a contextual component &#38; used as an application framework for enterprise Java. Ques2: What&#8217;re its main principles? Ans2: They are: (a) One kind of &#8220;stuff&#8221;: Seam defines a uniform component model for all business logic in your application. There is no distinction between presentation tier components and business logic components in Seam. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=159&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Que1:What&#8217;s Seam?<br />
Ans1:It&#8217;s a contextual component &amp; used as an application framework for enterprise Java.</p>
<p>Ques2: What&#8217;re its main principles?<br />
Ans2: They are:</p>
<p>(a) One kind of &#8220;stuff&#8221;: Seam defines a uniform component model for all business logic in your application.<br />
There is no distinction between presentation tier components and business logic components in Seam. You can layer your<br />
application according to whatever architecture you devise.</p>
<p>(b) Integrate JSF with EJB 3.0: JSF and EJB 3.0 are two of the best new features of Java EE 5.<br />
EJB3 is a brand new component model for server side business and persistence logic. Meanwhile, JSF is a great component model<br />
for the presentation tier. But the Java EE 5 specification provides no standard way to integrate the two component<br />
models. Seam unifies the component models of JSF and EJB3, eliminating glue code, and letting the developer think about the<br />
business problem.<br />
It is possible to write Seam applications where &#8220;everything&#8221; is an EJB. EJB3.0 is a fine-grained component &amp; like an<br />
annotated JavaBean component. With seam we can even use session beans as JSF action listeners!<br />
We can use any Java class as a seam component &amp; not just EJB3.0.</p>
<p>(c) Integrated AJAX: Seam supports the best open source JSF-based AJAX solutions: JBoss RichFaces and ICEfaces. These<br />
solutions let you add AJAX capability to your user interface without the need to write any JavaScript code.</p>
<p>(d) Business process as a first class construct: Optionally, Seam provides transparent business process management via jBPM.<br />
It&#8217;s very easy to implement complex workflows, collaboration and task management using jBPM and Seam.<br />
Seam even allows you to define presentation tier pageflow using the same language (jPDL) that jBPM uses for business process<br />
definition.<br />
JSF provides an incredibly rich event model for the presentation tier. Seam enhances this model by exposing jBPM&#8217;s business<br />
process related events via exactly the same event handling mechanism, providing a uniform event model for Seam&#8217;s uniform<br />
component model.</p>
<p>(e) Declarative state management: We&#8217;re all used to the concept of declarative transaction management and declarative<br />
security from the early days of EJB. EJB 3.0 even introduces declarative persistence context management. In all the three<br />
cases associated with a particular context, we need to ensure that all needed cleanup occurs when the context ends.<br />
Seam takes the concept of declarative state management much further and applies it to application state.<br />
Traditionally, J2EE applications implement state management manually, by getting and setting servlet session and request<br />
attributes. This approach to state management is the source of many bugs and memory leaks when applications fail to clean<br />
up session attributes, or when session data associated with different workflows collides in a multi-window application. Seam<br />
has the potential to almost entirely eliminate this class of bugs.<br />
Declarative application state management&#8217;s proper handling is made possible by the richness of the context model defined by<br />
Seam. Seam extends the context model defined by the servlet spec—request, session, application—with two new<br />
contexts—conversation and business process—that are more meaningful from the point of view of the business logic.<br />
Seam&#8217;s conversation-scoped persistence contexts mean you&#8217;ll rarely have to see a LazyInitializationException.<br />
The problems with the refresh button? The back button? With duplicate form submission? With propagating messages across a<br />
post-then-redirect? Seam&#8217;s conversation management solves these problems without you even needing to really think about them.<br />
They&#8217;re all symptoms of the broken state management architecture that has been prevalent since the earliest days of the web.</p>
<p>(f) Bijection: The notion of Inversion of Control or dependency injection exists in both JSF and EJB3, as well as in<br />
numerous so-called &#8220;lightweight containers&#8221;. Most of these containers emphasize injection of components that implement<br />
stateless services. Even when injection of stateful components is supported (such as in JSF), it is virtually useless for<br />
handling application state because the scope of the stateful component cannot be defined with sufficient flexibility,<br />
and because components belonging to wider scopes may not be injected into components belonging to narrower scopes.<br />
Bijection differs from IoC in that it is dynamic, contextual, and bidirectional. You can think of it as a mechanism for<br />
aliasing contextual variables (names in the various contexts bound to the current thread) to attributes of the component.<br />
Bijection allows auto-assembly of stateful components by the container. It even allows a component to safely and easily<br />
manipulate the value of a context variable, just by assigning it to an attribute of the component.</p>
<p>(g) Workspace management and multi-window browsing: Seam applications let the user freely switch between multiple browser<br />
tabs, each associated with a different, safely isolated, conversation. Applications may even take advantage of workspace<br />
management, allowing the user to switch between conversations (workspaces) in a single browser tab. Seam provides not only<br />
correct multi-window operation, but also multiwindow-like operation in a single window!</p>
<p>(h) Prefer annotations to XML: EJB 3.0 embraces annotations and &#8220;configuration by exception&#8221; as the easiest way to provide<br />
information to the container in a declarative form. Unfortunately, JSF is still heavily dependent on verbose XML<br />
configuration files. Seam extends the annotations provided by EJB 3.0 with a set of annotations for declarative state<br />
management and declarative context demarcation. This lets you eliminate the noisy JSF managed bean declarations and reduce<br />
the required XML to just that information which truly belongs in XML (the JSF navigation rules).</p>
<p>(i) Integration testing is easy: Seam components, being plain Java classes, are by nature unit testable. But for complex<br />
applications, unit testing alone is insufficient. Integration testing has traditionally been a messy and difficult task for<br />
Java web applications. Therefore, Seam provides for testability of Seam applications as a core feature of the framework. You<br />
can easily write JUnit or TestNG tests that reproduce a whole interaction with a user, exercising all components of the<br />
system apart from the view (the JSP or Facelets page). You can run these tests directly inside your IDE, where Seam will<br />
automatically deploy EJB components using JBoss Embedded.</p>
<p>(j) The specs ain&#8217;t perfect: We think the latest incarnation of Java EE is great. But we know it&#8217;s never going to be perfect.<br />
Where there are holes in the specifications (for example, limitations in the JSF lifecycle for GET requests), Seam fixes them.</p>
<p>(k) There&#8217;s more to a web application than serving HTML pages: Today&#8217;s web frameworks think too small. They let you get user<br />
input off a form and into your Java objects. And then they leave you hanging. A truly complete web application framework<br />
should address problems like persistence, concurrency, asynchronicity, state management, security, email, messaging, PDF and<br />
chart generation, workflow, wikitext rendering, webservices, caching and more. Once you scratch the surface of Seam, you&#8217;ll<br />
be amazed at how many problems become simpler&#8230;<br />
Seam integrates JPA and Hibernate3 for persistence, the EJB Timer Service and Quartz for lightweight asychronicity, jBPM for<br />
workflow, JBoss Rules for business rules, Meldware Mail for email, Hibernate Search and Lucene for full text search, JMS for<br />
messaging and JBoss Cache for page fragment caching. Seam layers an innovative rule-based security framework over JAAS and<br />
JBoss Rules. There&#8217;s even JSF tag libraries for rendering PDF, outgoing email, charts and wikitext. Seam components may be<br />
called synchronously as a Web Service, asynchronously from client-side JavaScript or Google Web Toolkit or, of course,<br />
directly from JSF.</p>
<p>It turns out that the combination of Seam, JSF and EJB3 is the simplest way to write a complex web application in Java. You<br />
won&#8217;t believe how little code is required!</p>
<p>Ques3: What&#8217;s the folder structure of the seam-based application?<br />
Ans3: Suppose our project name is registration &amp; it&#8217;s at the location examples/registration.<br />
Below is the folder structure:<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
examples/registration/view: Contains Web pages, images and stylesheets.<br />
examples/registration/resources: Resources such as deployment descriptors and data import scripts.<br />
examples/registration/src: Java source code.<br />
examples/registration/build.xml: The Ant build script.</p>
<p>Ques4: Before running the seam example on JBoss AS, what are the things need to be set?<br />
Ans4: First, make sure you have Ant correctly installed, with $ANT_HOME and $JAVA_HOME set correctly.<br />
Then set the JBoss AS 4.2 installation location  in the build.properties file in the root folder of your Seam project.<br />
start JBoss AS now by typing bin/run.sh or bin/run.bat in the root directory of your JBoss installation.<br />
Now, build and deploy the example by typing ant deploy in the examples/registration directory.<br />
Finally, try it with accessing http://localhost:8080/seam-registration/ [http://localhost:8080/seam-registration/] with<br />
your web browser.</p>
<p>Ques5: How to run its test application?<br />
Ans5: Most of the examples come with a suite of TestNG integration tests. The easiest way to run the tests is to run ant<br />
testexample inside the examples/registration directory. It is also possible to run the tests inside your IDE using the<br />
TestNG plugin.</p>
<p>Ques6: Details of the deployment descriptors used in the seam application?<br />
Ans6:<br />
components.xml: Seam component deployment descriptor -&gt;<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
If you&#8217;ve used many Java frameworks before, you&#8217;ll be used to having to declare all your component classes in some kind of<br />
XML file that gradually grows more and more unmanageable as your project matures. Most Seam applications require a very small<br />
amount of XML that does not grow very much as the project gets bigger.<br />
Nevertheless, it is often useful to be able to provide for some external configuration of some components<br />
(particularly the components built in to Seam). You have a couple of options here, but the most flexible option is to provide<br />
this configuration in a file called components.xml, located in the WEB-INF directory. We&#8217;ll use the components.xml file to<br />
tell Seam how to find our EJB components in JNDI:</p>
<p>&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;UTF-8&#8243;?&gt;<br />
&lt;components xmlns=&#8221;http://jboss.com/products/seam/components&#8221;<br />
xmlns:core=&#8221;http://jboss.com/products/seam/core&#8221;<br />
xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221;<br />
xsi:schemaLocation=<br />
&#8220;http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.1.xsd<br />
http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.1.xsd&#8221;&gt;<br />
&lt;core:init jndi-pattern=&#8221;@jndiPattern@&#8221;/&gt;<br />
&lt;/components&gt;</p>
<p>This code configures a property named jndiPattern of a built-in Seam component named org.jboss.seam.core.init. The<br />
funny @ symbols are there because our Ant build script puts the correct JNDI pattern in when we deploy the application.</p>
<p>web.xml: The web deployment description -&gt;<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
The presentation layer for our mini-application will be deployed in a WAR. So we&#8217;ll need a web deployment descriptor.</p>
<p>&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;UTF-8&#8243;?&gt;<br />
&lt;web-app version=&#8221;2.5&#8243;<br />
xmlns=&#8221;http://java.sun.com/xml/ns/javaee&#8221;<br />
xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221;<br />
xsi:schemaLocation=&#8221;http://java.sun.com/xml/ns/javaee<br />
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&#8221;&gt;</p>
<p>&lt;!&#8211; Seam &#8211;&gt;<br />
&lt;listener&gt;<br />
&lt;listener-class&gt;org.jboss.seam.servlet.SeamListener&lt;/listener-class&gt;<br />
&lt;/listener&gt;</p>
<p>&lt;!&#8211; JSF &#8211;&gt;<br />
&lt;listener&gt;<br />
&lt;listener-class&gt;com.sun.faces.config.ConfigureListener&lt;/listener-class&gt;<br />
&lt;/listener&gt;</p>
<p>&lt;context-param&gt;<br />
&lt;param-name&gt;javax.faces.DEFAULT_SUFFIX&lt;/param-name&gt;<br />
&lt;param-value&gt;.xhtml&lt;/param-value&gt;<br />
&lt;/context-param&gt;</p>
<p>&lt;servlet&gt;<br />
&lt;servlet-name&gt;Faces Servlet&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;javax.faces.webapp.FacesServlet&lt;/servlet-class&gt;<br />
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;</p>
<p>&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;Faces Servlet&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;*.seam&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;</p>
<p>&lt;session-config&gt;<br />
&lt;session-timeout&gt;10&lt;/session-timeout&gt;<br />
&lt;/session-config&gt;</p>
<p>&lt;/web-app&gt;</p>
<p>This web.xml file configures Seam and JSF. The configuration you see here is pretty much identical in all Seam applications.</p>
<p>faces-config.xml: The JSF configration -&gt;<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Most Seam applications use JSF views as the presentation layer. So usually we&#8217;ll need faces-config.xml. In our case, we are<br />
going to use Facelets for defining our views, so we need to tell JSF to use Facelets as its templating engine.</p>
<p>&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;UTF-8&#8243;?&gt;<br />
&lt;faces-config version=&#8221;1.2&#8243;<br />
xmlns=&#8221;http://java.sun.com/xml/ns/javaee&#8221;<br />
xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221;<br />
xsi:schemaLocation=&#8221;http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd&#8221;&gt;</p>
<p>&lt;!&#8211; Facelets support &#8211;&gt;<br />
&lt;application&gt;<br />
&lt;view-handler&gt;com.sun.facelets.FaceletViewHandler&lt;/view-handler&gt;<br />
&lt;/application&gt;</p>
<p>&lt;/faces-config&gt;</p>
<p>Note that we don&#8217;t need any JSF managed bean declarations! Our managed beans are annotated Seam components. In Seam<br />
applications, the faces-config.xml is used much less often than in plain JSF.</p>
<p>In fact, once you have all the basic descriptors set up, the only XML you need to write as you add new functionality to a<br />
Seam application is orchestration: navigation rules or jBPM process definitions. Seam takes the view that process flow and<br />
configuration data are the only things that truly belong in XML.</p>
<p>ejb-jar.xml: The EJB deployment descriptor -&gt;<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
The ejb-jar.xml file integrates Seam with EJB3, by attaching the SeamInterceptor to all session beans in the archive.</p>
<p>&lt;ejb-jar xmlns=&#8221;http://java.sun.com/xml/ns/javaee&#8221;<br />
xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221;<br />
xsi:schemaLocation=&#8221;http://java.sun.com/xml/ns/javaee<br />
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd&#8221; version=&#8221;3.0&#8243;&gt;</p>
<p>&lt;interceptors&gt;<br />
&lt;interceptor&gt;<br />
&lt;interceptor-class&gt;org.jboss.seam.ejb.SeamInterceptor&lt;/interceptor-class&gt;<br />
&lt;/interceptor&gt;<br />
&lt;/interceptors&gt;</p>
<p>&lt;assembly-descriptor&gt;<br />
&lt;interceptor-binding&gt;<br />
&lt;ejb-name&gt;*&lt;/ejb-name&gt;<br />
&lt;interceptor-class&gt;org.jboss.seam.ejb.SeamInterceptor&lt;/interceptor-class&gt;<br />
&lt;/interceptor-binding&gt;<br />
&lt;/assembly-descriptor&gt;</p>
<p>&lt;/ejb-jar&gt;</p>
<p>persistence.xml: The EJB persistence deployment descriptor -&gt;<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
The persistence.xml file tells the EJB persistence provider where to find the datasource, and contains some vendor-specific<br />
settings. In this case, enables automatic schema export at startup time.</p>
<p>&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;UTF-8&#8243;?&gt;<br />
&lt;persistence xmlns=&#8221;http://java.sun.com/xml/ns/persistence&#8221;<br />
xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221;<br />
xsi:schemaLocation=&#8221;http://java.sun.com/xml/ns/persistence<br />
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd&#8221; version=&#8221;1.0&#8243;&gt;</p>
<p>&lt;persistence-unit name=&#8221;userDatabase&#8221;&gt;<br />
&lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;<br />
&lt;jta-data-source&gt;java:/DefaultDS&lt;/jta-data-source&gt;<br />
&lt;properties&gt;<br />
&lt;property name=&#8221;hibernate.hbm2ddl.auto&#8221; value=&#8221;create-drop&#8221;/&gt;<br />
&lt;/properties&gt;<br />
&lt;/persistence-unit&gt;<br />
&lt;/persistence&gt;</p>
<p>application.xml: The EAR deployment descriptor -&gt;<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Finally, since our application is deployed as an EAR, we need a deployment descriptor there, too.</p>
<p>&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;UTF-8&#8243;?&gt;<br />
&lt;application xmlns=&#8221;http://java.sun.com/xml/ns/javaee&#8221;<br />
xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221;<br />
xsi:schemaLocation=&#8221;http://java.sun.com/xml/ns/javaee<br />
http://java.sun.com/xml/ns/javaee/application_5.xsd&#8221; version=&#8221;5&#8243;&gt;</p>
<p>&lt;display-name&gt;Seam Registration&lt;/display-name&gt;</p>
<p>&lt;module&gt;<br />
&lt;web&gt;<br />
&lt;web-uri&gt;jboss-seam-registration.war&lt;/web-uri&gt;<br />
&lt;context-root&gt;/seam-registration&lt;/context-root&gt;<br />
&lt;/web&gt;<br />
&lt;/module&gt;</p>
<p>&lt;module&gt;<br />
&lt;ejb&gt;jboss-seam-registration.jar&lt;/ejb&gt;<br />
&lt;/module&gt;</p>
<p>&lt;module&gt;<br />
&lt;ejb&gt;jboss-seam.jar&lt;/ejb&gt;<br />
&lt;/module&gt;</p>
<p>&lt;module&gt;<br />
&lt;java&gt;jboss-el.jar&lt;/java&gt;<br />
&lt;/module&gt;</p>
<p>&lt;/application&gt;</p>
<p>This deployment descriptor links modules in the enterprise archive and binds the web application to the context root<br />
/seam-registration.</p>
<p>Ques7: What are the commands we need to enter to get start with seam application?<br />
Ans7:<br />
(a) The Seam distribution includes a command line utility that makes it really easy to set up an Eclipse project, generate<br />
some simple Seam skeleton code, and reverse engineer an application from a preexisting database. It works best with JBoss AS. You can also use the generated project<br />
It works with other J2EE or Java EE 5 application servers by making a few manual changes to the project configuration. We can use it<br />
without eclipse as well as in conjunction with Eclipse for debugging and integration testing.<br />
Seam-gen is basically just a big ugly Ant script wrapped around Hibernate Tools, together with some templates. That makes it<br />
easy to customize if you need to, so this&#8217;s how we can reverse engineer an application from a preexisting database.</p>
<p>Before you start: Make sure you have JDK 5 or JDK 6, JBoss AS 4.2 and Ant 1.6, along with recent versions of Eclipse, the<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
JBoss IDE plugin for Eclipse and the TestNG plugin for Eclipse correctly installed before starting. Add your JBoss<br />
installation to the JBoss Server View in Eclipse. Start JBoss in debug mode. Finally, start a command prompt in the directory<br />
where you unzipped the Seam distribution.</p>
<p>JBoss has sophisticated support for hot re-deployment of WARs and EARs. Unfortunately, due to bugs in the JVM, repeated<br />
redeployment of an EAR—which is common during development—eventually causes the JVM to run out of perm gen space. For this<br />
reason, we recommend running JBoss in a JVM with a large perm gen space at development time. If you&#8217;re running JBoss from<br />
JBoss IDE, you can configure this in the server launch configuration, under &#8220;VM arguments&#8221;. We suggest the following values:<br />
-Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512</p>
<p>If you don&#8217;t have so much memory available, the following is our minimum recommendation:<br />
-Xms256m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=256</p>
<p>If you&#8217;re running JBoss from the command line, you can configure the JVM options in bin/run.conf. If you don&#8217;t want to bother<br />
with this stuff now, you don&#8217;t have to—come back to it later, when you get your first OutOfMemoryException.</p>
<p>Setting up a new Eclipse project: Go to cd jboss-seam-2.0.x, then type &#8216;seam setup&#8217;; enter all the details then type<br />
&#8216;seam create-project&#8217; to create a new project. Here all the information we have provided is stored in the file<br />
seam-gen/build.properties, but we can also modify them simply by running seam setup a second time.<br />
Now we can create a new project in our Eclipse workspace directory, by typing: &#8216;seam new-project&#8217;.<br />
This copies the Seam jars, dependent jars and the JDBC driver jar to a new Eclipse project, and generates all needed<br />
resources and configuration files, a facelets template file and stylesheet,along with Eclipse metadata and an Ant build<br />
script.The Eclipse project will be automatically deployed to an exploded directory structure in JBoss AS as soon as you add<br />
the project using New -&gt; Project&#8230; -&gt; General -&gt; Project -&gt; Next, typing the Project name (helloworld in this case), and<br />
then clicking Finish. Do not select Java Project from the New Project wizard.</p>
<p>The generated project includes three database and persistence configurations. The persistence-test.xml and import-test.sql<br />
files are used when running the TestNG unit tests against HSQLDB. The database schema and the test data in import-test.sql<br />
is always exported to the database before running tests. The myproject-dev-ds.xml, persistence-dev.xmland import-dev.sql<br />
files are for use when deploying the application to your development database. The schema might be exported automatically at<br />
deployment, depending upon whether you told seam-gen that you are working with an existing database. The<br />
myproject-prod-ds.xml, persistence-prod.xml and import-prod.sql files are for use when deploying the application to your<br />
production database. The schema is not exported automatically at deployment.</p>
<p>Creating a new action: Type &#8216;seam new-action&#8217; (To add a new seam component &amp; corresponding page).</p>
<p>Creating a form with an action: Type &#8216;seam new-form&#8217; (To create a new form).</p>
<p>Generating an application from an existing database: Type &#8216;seam generate-entities&#8217;<br />
(it&#8217;s called reverse-engineering where from an existing database tables we get entity beans, session beans, pages etc).</p>
<p>Generating an application from existing JPA/EJB3 entities: First i need to place my existing, valid entity classes inside the<br />
src/model. Now type &#8216;seam generate-ui&#8217;.<br />
Restart the deployment, and go to http://localhost:8080/helloworld.</p>
<p>Deploying the application as an EAR:<br />
By default, the application will be deployed with the dev profile. The EAR will include the persistence-dev.xml and<br />
import-dev.sql files, and the myproject-dev-ds.xml file will be deployed. You can change the profile, and use the prod<br />
profile, by typing: seam -Dprofile=prod deploy.</p>
<p>You can even define new deployment profiles for your application. Just add appropriately named files to your project—for<br />
example, persistence-staging.xml, import-staging.sql and myproject-staging-ds.xml—and select the name of the profile<br />
using -Dprofile=staging.</p>
<p>Seam and incremental hot deployment: When you deploy your Seam application as an exploded directory, you&#8217;ll get some support<br />
for incremental hot deployment at development time. You need to enable debug mode in both Seam and Facelets, by adding this<br />
line to components.xml: &lt;core:init debug=&#8221;true&#8221;&gt;.</p>
<p>Now, the following files may be redeployed without requiring a full restart of the web application:<br />
• any facelets page<br />
• any pages.xml file</p>
<p>But if we want to change any Java code, we still need to do a full restart of the application. (In JBoss this may be<br />
accomplished by touching the top level deployment descriptor: application.xml for an EAR deployment, or web.xml for a WAR<br />
deployment).</p>
<p>But if you really want a fast edit/compile/test cycle, Seam supports incremental redeployment of JavaBean components. To make<br />
use of this functionality, you must deploy the JavaBean components into the WEB-INF/dev directory, so that they will be<br />
loaded by a special Seam classloader, instead of by the WAR or EAR classloader.</p>
<p>You need to be aware of the following limitations:<br />
• the components must be JavaBean components, they cannot be EJB3 beans (we are working on fixing this limitation).<br />
• entities can never be hot-deloyed.<br />
• components deployed via components.xml may not be hot-deployed.<br />
• the hot-deployable components will not be visible to any classes deployed outside of WEB-INF/dev.<br />
• Seam debug mode must be enabled and jboss-seam-debug.jar must be in WEB-INF/lib.<br />
• You must have the Seam filter installed in web.xml.<br />
• You may see errors if the system is placed under any load and debug is enabled.<br />
If you create a WAR project using seam-gen, incremental hot deployment is available out of the box for classes in the<br />
src/action source directory. However, seam-gen does not support incremental hot deployment for EAR projects.</p>
<p>Using Seam with JBoss 4.0:<br />
Seam 2.0 was developed for JavaServer Faces 1.2. When using JBoss AS, we recommend using JBoss 4.2, which bundles the<br />
JSF 1.2 reference implementation. However, it is still possible to use Seam 2.0 on the JBoss 4.0 platform. There are two<br />
basic steps required to do this: install an EJB3-enabled version of JBoss 4.0 and replace MyFaces with the JSF 1.2 reference<br />
implementation. Once you complete these steps, Seam 2.0 applications can be deployed to JBoss 4.0.</p>
<p>Install JBoss 4.0: JBoss 4.0 does not ship a default configuration compatible with Seam. To run Seam, you must install<br />
JBoss 4.0.5 using the JEMS 1.2 installer with the ejb3 profile selected. Seam will not run with an installation that doesn&#8217;t<br />
include EJB3 support. The JEMS installer can be downloaded from http://labs.jboss.com/jemsinstaller/downloads.</p>
<p>Install the JSF 1.2 RI: The web configuration for JBoss 4.0 can be found in the server/default/deploy/jbosswebtomcat55.sar.<br />
You&#8217;ll need to delete myfaces-api.jar any myfaces-impl.jar from the jsflibs directory. Then, you&#8217;ll need to copy jsf-api.jar,<br />
jsf-impl.jar, el-api.jar, and el-ri.jar to that directory. The JSF JARs can be found in the Seam lib directory. The el JARs<br />
can be obtained from the Seam 1.2 release. You&#8217;ll also need to edit the conf/web.xml, replacing myfaces-impl.jar with<br />
jsf-impl.jar.</p>
<p>Ques8: Show the architecture of the deployed ear file in the JBOSS deploy folder?<br />
Ans7:It&#8217;s given below:</p>
<p>my-application.ear/<br />
jboss-seam.jar<br />
META-INF/<br />
MANIFEST.MF<br />
application.xml<br />
my-application.war/<br />
META-INF/<br />
MANIFEST.MF<br />
WEB-INF/<br />
web.xml<br />
components.xml<br />
faces-config.xml<br />
login.jsp<br />
register.jsp<br />
&#8230;<br />
my-application.jar/<br />
META-INF/<br />
MANIFEST.MF<br />
persistence.xml<br />
seam.properties<br />
org/<br />
jboss/<br />
myapplication/<br />
User.class<br />
Login.class<br />
LoginBean.class<br />
Register.class<br />
RegisterBean.class<br />
&#8230;</p>
<p>Make sure you reference jboss-seam.jar from manifests of the EJB-JAR and WAR.</p>
<p>Ques9: Configuring Seam components?<br />
Ans9: Seam provides two basic approaches to configuring components: configuration via property settings in a properties file<br />
or in web.xml, and configuration via components.xml.</p>
<p>Configuring components via property settings: Seam components may be provided with configuration properties either via<br />
servlet context parameters or via a properties file named seam.properties in the root of the classpath.<br />
The configurable Seam component must expose JavaBeans-style property setter methods for the configurable attributes. If a<br />
Seam component named com.jboss.myapp.settings has a setter method named setLocale(), we can provide a property named<br />
com.jboss.myapp.settings.locale in the seam.properties file or as a servlet context parameter, and Seam will set the value of<br />
the locale attribute whenever it instantiates the component.<br />
To set the conversation timeout, we provide a value for org.jboss.seam.core.manager.conversationTimeout in web.xml or<br />
seam.properties.</p>
<p>Configuring components via components.xml: The components.xml file is a bit more powerful than property settings.<br />
It lets you:</p>
<p>• Configure components that have been installed automatically—including both built-in components, and application components<br />
that have been annotated with the @Name annotation and picked up by Seam&#8217;s deployment scanner.<br />
• Install classes with no @Name annotation as Seam components—this is most useful for certain kinds of infrastructural<br />
components which can be installed multiple times with different names (for example Seam-managed persistence contexts).<br />
• Install components that do have a @Name annotation but are not installed by default because of an @Install annotation that<br />
indicates the component should not be installed.<br />
• Override the scope of a component.<br />
A components.xml file may appear in one of three different places:<br />
• The WEB-INF directory of a war.<br />
• The META-INF directory of a jar.<br />
• Any directory of a jar that contains classes with an @Name annotation.</p>
<p>Usually, Seam components are installed when the deployment scanner discovers a class with a @Name annotation sitting in an<br />
archive with a seam.properties file or a META-INF/components.xml file. (Unless the component has an @Install annotation<br />
indicating it should not be installed by default.) The components.xml file lets us handle special cases where we need<br />
to override the annotations.</p>
<p>For example, the following components.xml file installs jBPM:<br />
&lt;components xmlns=&#8221;http://jboss.com/products/seam/components&#8221;<br />
xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221;<br />
xmlns:bpm=&#8221;http://jboss.com/products/seam/bpm&#8221;&gt;<br />
&lt;bpm:jbpm/&gt;<br />
&lt;/components&gt;</p>
<p>This example does the same thing:<br />
&lt;components&gt;<br />
&lt;component/&gt;<br />
&lt;/components&gt;</p>
<p>This one installs and configures two different Seam-managed persistence contexts:<br />
&lt;components xmlns=&#8221;http://jboss.com/products/seam/components&#8221;<br />
xmlns:persistence=&#8221;http://jboss.com/products/seam/persistence&#8221;<br />
&lt;persistence:managed-persistence-context name=&#8221;customerDatabase&#8221;<br />
persistence-unit-jndi-name=&#8221;java:/customerEntityManagerFactory&#8221;/&gt;<br />
&lt;persistence:managed-persistence-context name=&#8221;accountingDatabase&#8221;<br />
persistence-unit-jndi-name=&#8221;java:/accountingEntityManagerFactory&#8221;/&gt;<br />
&lt;/components&gt;</p>
<p>As does this one:<br />
&lt;components&gt;</p>
<p>&lt;component name=&#8221;customerDatabase&#8221;&gt;<br />
&lt;property name=&#8221;persistenceUnitJndiName&#8221;&gt;java:/customerEntityManagerFactory&lt;/property&gt;<br />
&lt;/component&gt;</p>
<p>&lt;component name=&#8221;accountingDatabase&#8221;<br />
class=&#8221;org.jboss.seam.persistence.ManagedPersistenceContext&#8221;&gt;<br />
&lt;property name=&#8221;persistenceUnitJndiName&#8221;&gt;java:/accountingEntityManagerFactory&lt;/<br />
property&gt;<br />
&lt;/component&gt;</p>
<p>&lt;/components&gt;</p>
<p>This example creates a session-scoped Seam-managed persistence context (this is not recommended in practice):<br />
&lt;components xmlns=&#8221;http://jboss.com/products/seam/components&#8221;<br />
xmlns:persistence=&#8221;http://jboss.com/products/seam/persistence&#8221;<br />
&lt;persistence:managed-persistence-context name=&#8221;productDatabase&#8221; scope=&#8221;session&#8221;<br />
persistence-unit-jndi-name=&#8221;java:/productEntityManagerFactory&#8221;/&gt;<br />
&lt;/components&gt;</p>
<p>&lt;components&gt;<br />
&lt;component name=&#8221;productDatabase&#8221; scope=&#8221;session&#8221;<br />
class=&#8221;org.jboss.seam.persistence.ManagedPersistenceContext&#8221;&gt;<br />
&lt;property name=&#8221;persistenceUnitJndiName&#8221;&gt;java:/productEntityManagerFactory&lt;/property&gt;<br />
&lt;/component&gt;<br />
&lt;/components&gt;</p>
<p>It is common to use the auto-create option for infrastructural objects like persistence contexts,<br />
which saves you from having to explicitly specify create=true when you use the @In annotation.</p>
<p>&lt;components xmlns=&#8221;http://jboss.com/products/seam/components&#8221;<br />
xmlns:persistence=&#8221;http://jboss.com/products/seam/persistence&#8221;<br />
&lt;persistence:managed-persistence-context name=&#8221;productDatabase&#8221; auto-create=&#8221;true&#8221;<br />
persistence-unit-jndi-name=&#8221;java:/productEntityManagerFactory&#8221;/&gt;<br />
&lt;/components&gt;</p>
<p>&lt;components&gt;<br />
&lt;component name=&#8221;productDatabase&#8221; auto-create=&#8221;true&#8221;<br />
class=&#8221;org.jboss.seam.persistence.ManagedPersistenceContext&#8221;&gt;<br />
&lt;property name=&#8221;persistenceUnitJndiName&#8221;&gt;java:/productEntityManagerFactory&lt;/property&gt;<br />
&lt;/component&gt;<br />
&lt;/components&gt;</p>
<p>The &lt;factory&gt; declaration lets you specify a value or method binding expression that will be<br />
evaluated to initialize the value of a context variable when it is first referenced.<br />
&lt;components&gt;<br />
&lt;factory name=&#8221;contact&#8221; method=&#8221;#{contactManager.loadContact}&#8221; scope=&#8221;CONVERSATION&#8221;/&gt;<br />
&lt;/components&gt;</p>
<p>You can create an &#8220;alias&#8221; (a second name) for a Seam component like so:<br />
&lt;components&gt;<br />
&lt;factory name=&#8221;user&#8221; value=&#8221;#{actor}&#8221; scope=&#8221;STATELESS&#8221;/&gt;<br />
&lt;/components&gt;</p>
<p>You can even create an &#8220;alias&#8221; for a commonly used expression:<br />
&lt;components&gt;<br />
&lt;factory name=&#8221;contact&#8221; value=&#8221;#{contactManager.contact}&#8221; scope=&#8221;STATELESS&#8221;/&gt;<br />
&lt;/components&gt;</p>
<p>It is especially common to see the use of auto-create=&#8221;true&#8221; with the &lt;factory&gt; declaration:<br />
&lt;components&gt;<br />
&lt;factory name=&#8221;session&#8221; value=&#8221;#{entityManager.delegate}&#8221; scope=&#8221;STATELESS&#8221; autocreate=&#8221;true&#8221;/&gt;<br />
&lt;/components&gt;</p>
<p>Sometimes we want to reuse the same components.xml file with minor changes during both deployment and testing. Seam lets you<br />
place wildcards of the form @wildcard@ in the components.xml file which can be replaced either by your Ant build script<br />
(at deployment time) or by providing a file named components.properties in the classpath (at development time).</p>
<p>Using XML Namespaces: Throughout the examples, there have been two competing ways of declaring components: with<br />
and without the use of XML namespaces. The following shows a typical components.xml file without namespaces:</p>
<p>&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;UTF-8&#8243;?&gt;<br />
&lt;components xmlns=&#8221;http://jboss.com/products/seam/components&#8221;<br />
xsi:schemaLocation=&#8221;http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.1.xsd&#8221;&gt;<br />
&lt;component&gt;<br />
&lt;property name=&#8221;debug&#8221;&gt;true&lt;/property&gt;<br />
&lt;property name=&#8221;jndiPattern&#8221;&gt;@jndiPattern@&lt;/property&gt;<br />
&lt;/component&gt;<br />
&lt;/components&gt;</p>
<p>As you can see, this is somewhat verbose. Even worse, the component and attribute names cannot be validated at development<br />
time.</p>
<p>The namespaced version looks like this:</p>
<p>&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;UTF-8&#8243;?&gt;<br />
&lt;components xmlns=&#8221;http://jboss.com/products/seam/components&#8221;<br />
xmlns:core=&#8221;http://jboss.com/products/seam/core&#8221;<br />
xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221;<br />
xsi:schemaLocation=&#8221;http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.1.xsd<br />
http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.1.xsd&#8221;&gt;<br />
&lt;core:init debug=&#8221;true&#8221; jndi-pattern=&#8221;@jndiPattern@&#8221;/&gt;<br />
&lt;/components&gt;</p>
<p>Even though the schema declarations are verbose, the actual XML content is lean and easy to understand. The schemas provide<br />
detailed information about each component and the attributes available, allowing XML editors to offer intelligent<br />
autocomplete. The use of namespaced elements makes generating and maintaining correct components.xml files much simpler.</p>
<p>Now, this works great for the built-in Seam components, but what about user components? There are two options. First, Seam<br />
supports mixing the two models, allowing the use of the generic &lt;component&gt; declarations for user components, along with<br />
namespaced declarations for built-in components. But even better, Seam allows you to quickly declare namespaces for your own<br />
components.</p>
<p>Any Java package can be associated with an XML namespace by annotating the package with the @Namespace annotation.</p>
<p>@Namespace(value=&#8221;http://jboss.com/products/seam/examples/seampay&#8221;)<br />
package org.jboss.seam.example.seampay;<br />
import org.jboss.seam.annotations.Namespace;</p>
<p>That is all you need to do to use the namespaced style in components.xml! Now we can write:</p>
<p>&lt;components xmlns=&#8221;http://jboss.com/products/seam/components&#8221;<br />
xmlns:pay=&#8221;http://jboss.com/products/seam/examples/seampay&#8221; &#8230; &gt;<br />
&lt;pay:payment-home new-instance=&#8221;#{newPayment}&#8221; created-message=&#8221;Created a new payment to #{newPayment.payee}&#8221; /&gt;<br />
&lt;pay:payment name=&#8221;newPayment&#8221; payee=&#8221;Somebody&#8221; account=&#8221;#{selectedAccount}&#8221; payment-date=&#8221;#{currentDatetime}&#8221;<br />
created-date=&#8221;#{currentDatetime}&#8221; /&gt;<br />
&#8230;<br />
&lt;/components&gt;</p>
<p>Or:</p>
<p>&lt;components xmlns=&#8221;http://jboss.com/products/seam/components&#8221;<br />
xmlns:pay=&#8221;http://jboss.com/products/seam/examples/seampay&#8221; &#8230; &gt;<br />
&lt;pay:payment-home&gt;<br />
&lt;pay:new-instance&gt;&#8221;#{newPayment}&#8221;&lt;/pay:new-instance&gt;<br />
&lt;pay:created-message&gt;Created a new payment to #{newPayment.payee}&lt;/pay:createdmessage&gt;<br />
&lt;/pay:payment-home&gt;<br />
&lt;pay:payment name=&#8221;newPayment&#8221;&gt;<br />
&lt;pay:payee&gt;Somebody&#8221;&lt;/pay:payee&gt;<br />
&lt;pay:account&gt;#{selectedAccount}&lt;/pay:account&gt;<br />
&lt;pay:payment-date&gt;#{currentDatetime}&lt;/pay:payment-date&gt;<br />
&lt;pay:created-date&gt;#{currentDatetime}&lt;/pay:created-date&gt;<br />
&lt;/pay:payment&gt;<br />
&#8230;<br />
&lt;/components&gt;</p>
<p>These examples illustrate the two usage models of a namespaced element. In the first declaration, the &lt;pay:payment-home&gt;<br />
references the paymentHome component:</p>
<p>package org.jboss.seam.example.seampay;<br />
&#8230;<br />
@Name(&#8220;paymentHome&#8221;)<br />
public class PaymentController<br />
extends EntityHome&lt;Payment&gt;<br />
{<br />
&#8230;<br />
}</p>
<p>In the second declaration, the &lt;pay:payment&gt; element refers to the Payment class in the org.jboss.seam.example.seampay<br />
package. In this case Payment is an entity that is being declared as a Seam component:</p>
<p>package org.jboss.seam.example.seampay;<br />
&#8230;<br />
@Entity<br />
public class Payment<br />
implements Serializable<br />
{<br />
&#8230;<br />
}</p>
<p>If we want validation and autocompletion to work for user-defined components, we will need a schema. Seam does not yet<br />
provide a mechanism to automatically generate a schema for a set of components, so it is necessary to generate one manually.<br />
The schema definitions for the standard Seam packages can be used for guidance.</p>
<p>The following are the the namespaces used by Seam:<br />
• components — http://jboss.com/products/seam/components<br />
• core — http://jboss.com/products/seam/core<br />
• drools — http://jboss.com/products/seam/drools<br />
• framework — http://jboss.com/products/seam/framework<br />
• jms — http://jboss.com/products/seam/jms<br />
• remoting — http://jboss.com/products/seam/remoting<br />
• theme — http://jboss.com/products/seam/theme<br />
• security — http://jboss.com/products/seam/security<br />
• mail — http://jboss.com/products/seam/mail<br />
• web — http://jboss.com/products/seam/web<br />
• pdf — http://jboss.com/products/seam/pdf<br />
• spring — http://jboss.com/products/seam/spring</p>
<p>Events, interceptors and exception handling: Complementing the contextual component model, there are two further basic<br />
concepts that facilitate the extreme loose-coupling that is the distinctive feature of Seam applications. The first<br />
is a strong event model where events may be mapped to event listeners via JSF-like method binding expressions. The second is<br />
the pervasive use of annotations and interceptors to apply cross-cutting concerns to components which implement business<br />
logic.</p>
<p>Seam events: The Seam component model was developed for use with event-driven applications, specifically to enable the<br />
development of fine-grained, loosely-coupled components in a fine-grained eventing model. Events in Seam come in several<br />
types, most of which we have already seen:</p>
<p>• JSF events<br />
• jBPM transition events<br />
• Seam page actions<br />
• Seam component-driven events<br />
• Seam contextual events</p>
<p>All of these various kinds of events are mapped to Seam components via JSF EL method binding expressions. For a JSF event,<br />
this is defined in the JSF template:</p>
<p>&lt;h:commandButton value=&#8221;Click me!&#8221; action=&#8221;#{helloWorld.sayHello}&#8221;/&gt;</p>
<p>For a jBPM transition event, it is specified in the jBPM process definition or pageflow definition:</p>
<p>&lt;start-page name=&#8221;hello&#8221; view-id=&#8221;/hello.jsp&#8221;&gt;<br />
&lt;transition to=&#8221;hello&#8221;&gt;<br />
&lt;action expression=&#8221;#{helloWorld.sayHello}&#8221;/&gt;<br />
&lt;/transition&gt;<br />
&lt;/start-page&gt;</p>
<p>Page actions: A Seam page action is an event that occurs just before we render a page. We declare page actions<br />
in WEB-INF/pages.xml. We can define a page action for either a particular JSF view id:</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/hello.jsp&#8221; action=&#8221;#{helloWorld.sayHello}&#8221;/&gt;<br />
&lt;/pages&gt;</p>
<p>Or we can use a * wildcard as a suffix to the view-id to specify an action that applies to all view<br />
ids that match the pattern:</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/hello/*&#8221; action=&#8221;#{helloWorld.sayHello}&#8221;/&gt;<br />
&lt;/pages&gt;</p>
<p>If multiple wildcarded page actions match the current view-id, Seam will call all the actions, in<br />
order of least-specific to most-specific.</p>
<p>The page action method can return a JSF outcome. If the outcome is non-null, Seam will use the<br />
defined navigation rules to navigate to a view.</p>
<p>Furthermore, the view id mentioned in the &lt;page&gt; element need not correspond to a real JSP or Facelets page! So, we can<br />
reproduce the functionality of a traditional action-oriented framework like Struts or WebWork using page actions.</p>
<p>For example:<br />
TODO: translate struts action into page action</p>
<p>This is quite useful if you want to do complex things in response to non-faces requests (for example, HTTP GET requests).</p>
<p>Multiple or conditional page actions my be specified using the &lt;action&gt; tag:</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/hello.jsp&#8221;&gt;<br />
&lt;action execute=&#8221;#{helloWorld.sayHello}&#8221; if=&#8221;#{not validation.failed}&#8221;/&gt;<br />
&lt;action execute=&#8221;#{hitCount.increment}&#8221;/&gt;<br />
&lt;/page&gt;<br />
&lt;/pages&gt;</p>
<p>Mapping request parameters to the model: Seam lets us provide a value binding that maps a named request parameter to an<br />
attribute of a model object.</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/hello.jsp&#8221; action=&#8221;#{helloWorld.sayHello}&#8221;&gt;<br />
&lt;param name=&#8221;firstName&#8221; value=&#8221;#{person.firstName}&#8221;/&gt;<br />
&lt;param name=&#8221;lastName&#8221; value=&#8221;#{person.lastName}&#8221;/&gt;<br />
&lt;/page&gt;<br />
&lt;/pages&gt;</p>
<p>The &lt;param&gt; declaration is bidirectional, just like a value binding for a JSF input:</p>
<p>• When a non-faces (GET) request for the view id occurs, Seam sets the value of the named<br />
request parameter onto the model object, after performing appropriate type conversions.<br />
• Any &lt;s:link&gt; or &lt;s:button&gt; transparently includes the request parameter. The value of the<br />
parameter is determined by evaluating the value binding during the render phase (when the<br />
&lt;s:link&gt; is rendered).<br />
• Any navigation rule with a &lt;redirect/&gt; to the view id transparently includes the request<br />
parameter. The value of the parameter is determined by evaluating the value binding at the end<br />
of the invoke application phase.<br />
• The value is transparently propagated with any JSF form submission for the page with the given<br />
view id. This means that view parameters behave like PAGE-scoped context variables for faces<br />
requests.</p>
<p>The essential idea behind all this is that however we get from any other page to /hello.jsp (or from /hello.jsp back to<br />
/hello.jsp), the value of the model attribute referred to in the value binding is &#8220;remembered&#8221;, without the need for a<br />
conversation (or other server-side state).</p>
<p>Propagating request parameters: If just the name attribute is specified then the request parameter is propagated using the<br />
PAGE context (it isn&#8217;t mapped to model property).</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/hello.jsp&#8221; action=&#8221;#{helloWorld.sayHello}&#8221;&gt;<br />
&lt;param name=&#8221;firstName&#8221; /&gt;<br />
&lt;param name=&#8221;lastName&#8221; /&gt;<br />
&lt;/page&gt;<br />
&lt;/pages&gt;</p>
<p>Propagation of page parameters is especially useful if you want to build multi-layer master-detail CRUD pages. You can use<br />
it to &#8220;remember&#8221; which view you were previously on (e.g. when pressing the Save button), and which entity you were editing.</p>
<p>• Any &lt;s:link&gt; or &lt;s:button&gt; transparently propagates the request parameter if that parameter is listed as a page parameter<br />
for the view.<br />
• The value is transparently propagated with any JSF form submission for the page with the given view id. (This means that<br />
view parameters behave like PAGE-scoped context variables for faces requests.</p>
<p>Conversion and Validation:<br />
You can specify a JSF converter for complex model propreties:</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/calculator.jsp&#8221; action=&#8221;#{calculator.calculate}&#8221;&gt;<br />
&lt;param name=&#8221;x&#8221; value=&#8221;#{calculator.lhs}&#8221;/&gt;<br />
&lt;param name=&#8221;y&#8221; value=&#8221;#{calculator.rhs}&#8221;/&gt;<br />
&lt;param name=&#8221;op&#8221; converterId=&#8221;com.my.calculator.OperatorConverter&#8221; value=&#8221;#{calculator.op}&#8221;/&gt;<br />
&lt;/page&gt;<br />
&lt;/pages&gt;</p>
<p>Alternatively:</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/calculator.jsp&#8221; action=&#8221;#{calculator.calculate}&#8221;&gt;<br />
&lt;param name=&#8221;x&#8221; value=&#8221;#{calculator.lhs}&#8221;/&gt;<br />
&lt;param name=&#8221;y&#8221; value=&#8221;#{calculator.rhs}&#8221;/&gt;<br />
&lt;param name=&#8221;op&#8221; converter=&#8221;#{operatorConverter}&#8221; value=&#8221;#{calculator.op}&#8221;/&gt;<br />
&lt;/page&gt;<br />
&lt;/pages&gt;</p>
<p>JSF validators, and required=&#8221;true&#8221; may also be used:</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/blog.xhtml&#8221;&gt;<br />
&lt;param name=&#8221;date&#8221; value=&#8221;#{blog.date}&#8221;<br />
validatorId=&#8221;com.my.blog.PastDate&#8221; required=&#8221;true&#8221;/&gt;<br />
&lt;/page&gt;<br />
&lt;/pages&gt;</p>
<p>Alternatively:</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/blog.xhtml&#8221;&gt;<br />
&lt;param name=&#8221;date&#8221; value=&#8221;#{blog.date}&#8221;<br />
validator=&#8221;#{pastDateValidator}&#8221; required=&#8221;true&#8221;/&gt;<br />
&lt;/page&gt;<br />
&lt;/pages&gt;</p>
<p>Even better, model-based Hibernate validator annotations are automatically recognized and validated.<br />
When type conversion or validation fails, a global FacesMessage is added to the FacesContext.</p>
<p>Navigation: You can use standard JSF navigation rules defined in faces-config.xml in a Seam application.<br />
However, JSF navigation rules have a number of annoying limitations:</p>
<p>• It is not possible to specify request parameters to be used when redirecting.<br />
• It is not possible to begin or end conversations from a rule.<br />
• Rules work by evaluating the return value of the action method; it is not possible to evaluate an arbitrary EL expression.</p>
<p>A further problem is that &#8220;orchestration&#8221; logic gets scattered between pages.xml and facesconfig.xml. It&#8217;s better to unify<br />
this logic into pages.xml.</p>
<p>This JSF navigation rule:<br />
&lt;navigation-rule&gt;<br />
&lt;from-view-id&gt;/editDocument.xhtml&lt;/from-view-id&gt;<br />
&lt;navigation-case&gt;<br />
&lt;from-action&gt;#{documentEditor.update}&lt;/from-action&gt;<br />
&lt;from-outcome&gt;success&lt;/from-outcome&gt;<br />
&lt;to-view-id&gt;/viewDocument.xhtml&lt;/to-view-id&gt;<br />
&lt;redirect/&gt;<br />
&lt;/navigation-case&gt;<br />
&lt;/navigation-rule&gt;</p>
<p>Can be rewritten as follows:</p>
<p>&lt;page view-id=&#8221;/editDocument.xhtml&#8221;&gt;<br />
&lt;navigation from-action=&#8221;#{documentEditor.update}&#8221;&gt;<br />
&lt;rule if-outcome=&#8221;success&#8221;&gt;<br />
&lt;redirect view-id=&#8221;/viewDocument.xhtml&#8221;/&gt;<br />
&lt;/rule&gt;<br />
&lt;/navigation&gt;<br />
&lt;/page&gt;</p>
<p>But it would be even nicer if we didn&#8217;t have to pollute our DocumentEditor component with stringvalued<br />
return values (the JSF outcomes). So Seam lets us write:</p>
<p>&lt;page view-id=&#8221;/editDocument.xhtml&#8221;&gt;<br />
&lt;navigation from-action=&#8221;#{documentEditor.update}&#8221; evaluate=&#8221;#{documentEditor.errors.size}&#8221;&gt;<br />
&lt;rule if-outcome=&#8221;0&#8243;&gt;<br />
&lt;redirect view-id=&#8221;/viewDocument.xhtml&#8221;/&gt;<br />
&lt;/rule&gt;<br />
&lt;/navigation&gt;<br />
&lt;/page&gt;</p>
<p>Or even:</p>
<p>&lt;page view-id=&#8221;/editDocument.xhtml&#8221;&gt;<br />
&lt;navigation from-action=&#8221;#{documentEditor.update}&#8221;&gt;<br />
&lt;rule if=&#8221;#{documentEditor.errors.empty}&#8221;&gt;<br />
&lt;redirect view-id=&#8221;/viewDocument.xhtml&#8221;/&gt;<br />
&lt;/rule&gt;<br />
&lt;/navigation&gt;<br />
&lt;/page&gt;</p>
<p>The first form evaluates a value binding to determine the outcome value to be used by the subsequent rules. The second<br />
approach ignores the outcome and evaluates a value binding for each possible rule.<br />
Of course, when an update succeeds, we probably want to end the current conversation. We can do that like this:</p>
<p>&lt;page view-id=&#8221;/editDocument.xhtml&#8221;&gt;<br />
&lt;navigation from-action=&#8221;#{documentEditor.update}&#8221;&gt;<br />
&lt;rule if=&#8221;#{documentEditor.errors.empty}&#8221;&gt;<br />
&lt;end-conversation/&gt;<br />
&lt;redirect view-id=&#8221;/viewDocument.xhtml&#8221;/&gt;<br />
&lt;/rule&gt;<br />
&lt;/navigation&gt;<br />
&lt;/page&gt;</p>
<p>As we&#8217;ve ended conversation any subsequent requests won&#8217;t know which document we are interested in. We can pass the document<br />
id as a request parameter which also makes the view bookmarkable:</p>
<p>&lt;page view-id=&#8221;/editDocument.xhtml&#8221;&gt;<br />
&lt;navigation from-action=&#8221;#{documentEditor.update}&#8221;&gt;<br />
&lt;rule if=&#8221;#{documentEditor.errors.empty}&#8221;&gt;<br />
&lt;end-conversation/&gt;<br />
&lt;redirect view-id=&#8221;/viewDocument.xhtml&#8221;&gt;<br />
&lt;param name=&#8221;documentId&#8221; value=&#8221;#{documentEditor.documentId}&#8221;/&gt;<br />
&lt;/redirect&gt;<br />
&lt;/rule&gt;<br />
&lt;/navigation&gt;<br />
&lt;/page&gt;</p>
<p>Null outcomes are a special case in JSF. The null outcome is interpreted to mean &#8220;redisplay the<br />
page&#8221;. The following navigation rule matches any non-null outcome, but not the null outcome:</p>
<p>&lt;page view-id=&#8221;/editDocument.xhtml&#8221;&gt;<br />
&lt;navigation from-action=&#8221;#{documentEditor.update}&#8221;&gt;<br />
&lt;rule&gt;<br />
&lt;render view-id=&#8221;/viewDocument.xhtml&#8221;/&gt;<br />
&lt;/rule&gt;<br />
&lt;/navigation&gt;<br />
&lt;/page&gt;</p>
<p>If you want to perform navigation when a null outcome occurs, use the following form instead:</p>
<p>&lt;page view-id=&#8221;/editDocument.xhtml&#8221;&gt;<br />
&lt;navigation from-action=&#8221;#{documentEditor.update}&#8221;&gt;<br />
&lt;render view-id=&#8221;/viewDocument.xhtml&#8221;/&gt;<br />
&lt;/navigation&gt;<br />
&lt;/page&gt;</p>
<p>The view-id may be given as a JSF EL expression:</p>
<p>&lt;page view-id=&#8221;/editDocument.xhtml&#8221;&gt;<br />
&lt;navigation&gt;<br />
&lt;rule if-outcome=&#8221;success&#8221;&gt;<br />
&lt;redirect view-id=&#8221;/#{userAgent}/displayDocument.xhtml&#8221;/&gt;<br />
&lt;/rule&gt;<br />
&lt;/navigation&gt;<br />
&lt;/page&gt;</p>
<p>Fine-grained files for definition of navigation, page actions and parameters:<br />
If you have a lot of different page actions and page parameters, or even just a lot of navigation rules, you will almost<br />
certainly want to split the declarations up over multiple files. You can define actions and parameters for a page with the<br />
view id /calc/calculator.jsp in a resource named calc/calculator.page.xml. The root element in this case is the &lt;page&gt;<br />
element, and the view id is implied:</p>
<p>&lt;page action=&#8221;#{calculator.calculate}&#8221;&gt;<br />
&lt;param name=&#8221;x&#8221; value=&#8221;#{calculator.lhs}&#8221;/&gt;<br />
&lt;param name=&#8221;y&#8221; value=&#8221;#{calculator.rhs}&#8221;/&gt;<br />
&lt;param name=&#8221;op&#8221; converter=&#8221;#{operatorConverter}&#8221; value=&#8221;#{calculator.op}&#8221;/&gt;<br />
&lt;/page&gt;</p>
<p>Component-driven events: Seam components can interact by simply calling each others methods. Stateful components may<br />
even implement the observer/observable pattern. But to enable components to interact in a more loosely-coupled fashion than<br />
is possible when the components call each others methods directly, Seam provides component-driven events.<br />
We specify event listeners (observers) in components.xml.</p>
<p>&lt;components&gt;<br />
&lt;event type=&#8221;hello&#8221;&gt;<br />
&lt;action execute=&#8221;#{helloListener.sayHelloBack}&#8221;/&gt;<br />
&lt;action execute=&#8221;#{logger.logHello}&#8221;/&gt;<br />
&lt;/event&gt;<br />
&lt;/components&gt;</p>
<p>Where the event type is just an arbitrary string.</p>
<p>When an event occurs, the actions registered for that event will be called in the order they appear in components.xml. How<br />
does a component raise an event? Seam provides a built-in component for this.</p>
<p>@Name(&#8220;helloWorld&#8221;)<br />
public class HelloWorld {<br />
public void sayHello() {<br />
FacesMessages.instance().add(&#8220;Hello World!&#8221;);<br />
Events.instance().raiseEvent(&#8220;hello&#8221;);<br />
}<br />
}</p>
<p>Or you can use an annotation.</p>
<p>@Name(&#8220;helloWorld&#8221;)<br />
public class HelloWorld {<br />
@RaiseEvent(&#8220;hello&#8221;)<br />
public void sayHello() {<br />
FacesMessages.instance().add(&#8220;Hello World!&#8221;);<br />
}<br />
}</p>
<p>Notice that this event producer has no dependency upon event consumers. The event listener<br />
may now be implemented with absolutely no dependency upon the producer:</p>
<p>@Name(&#8220;helloListener&#8221;)<br />
public class HelloListener {<br />
public void sayHelloBack() {<br />
FacesMessages.instance().add(&#8220;Hello to you too!&#8221;);<br />
}<br />
}</p>
<p>The method binding defined in components.xml above takes care of mapping the event to the<br />
consumer. If you don&#8217;t like futzing about in the components.xml file, you can use an annotation instead:</p>
<p>@Name(&#8220;helloListener&#8221;)<br />
public class HelloListener {<br />
@Observer(&#8220;hello&#8221;)<br />
public void sayHelloBack() {<br />
FacesMessages.instance().add(&#8220;Hello to you too!&#8221;);<br />
}<br />
}</p>
<p>You might wonder why I&#8217;ve not mentioned anything about event objects in this discussion. In<br />
Seam, there is no need for an event object to propagate state between event producer and listener. State is held in the Seam<br />
contexts, and is shared between components. However, if you really want to pass an event object, you can:</p>
<p>@Name(&#8220;helloWorld&#8221;)<br />
public class HelloWorld {<br />
private String name;<br />
public void sayHello() {<br />
FacesMessages.instance().add(&#8220;Hello World, my name is #0.&#8221;, name);<br />
Events.instance().raiseEvent(&#8220;hello&#8221;, name);<br />
}<br />
}</p>
<p>@Name(&#8220;helloListener&#8221;)<br />
public class HelloListener {<br />
@Observer(&#8220;hello&#8221;)<br />
public void sayHelloBack(String name) {<br />
FacesMessages.instance().add(&#8220;Hello #0!&#8221;, name);<br />
}<br />
}</p>
<p>Contextual events: Seam defines a number of built-in events that the application can use to perform special kinds of<br />
framework integration. The events are:</p>
<p>• org.jboss.seam.validationFailed — called when JSF validation fails<br />
• org.jboss.seam.noConversation — called when there is no long running conversation and a long running conversation is<br />
required<br />
• org.jboss.seam.preSetVariable.&lt;name&gt; — called when the context variable &lt;name&gt; is set<br />
• org.jboss.seam.postSetVariable.&lt;name&gt; — called when the context variable &lt;name&gt; is set<br />
• org.jboss.seam.preRemoveVariable.&lt;name&gt; — called when the context variable &lt;name&gt; is unset<br />
• org.jboss.seam.postRemoveVariable.&lt;name&gt; — called when the context variable &lt;name&gt; is unset<br />
• org.jboss.seam.preDestroyContext.&lt;SCOPE&gt; — called before the &lt;SCOPE&gt; context is destroyed<br />
• org.jboss.seam.postDestroyContext.&lt;SCOPE&gt; — called after the &lt;SCOPE&gt; context is destroyed<br />
• org.jboss.seam.beginConversation — called whenever a long-running conversation begins<br />
• org.jboss.seam.endConversation — called whenever a long-running conversation ends<br />
• org.jboss.seam.conversationTimeout— called when a conversation timeout occurs. The conversation id is passed as a parameter.<br />
• org.jboss.seam.beginPageflow — called when a pageflow begins<br />
• org.jboss.seam.beginPageflow.&lt;name&gt; — called when the pageflow &lt;name&gt; begins<br />
• org.jboss.seam.endPageflow — called when a pageflow ends<br />
• org.jboss.seam.endPageflow.&lt;name&gt; — called when the pageflow &lt;name&gt; ends<br />
• org.jboss.seam.createProcess.&lt;name&gt; — called when the process &lt;name&gt; is created<br />
• org.jboss.seam.endProcess.&lt;name&gt; — called when the process &lt;name&gt; ends<br />
• org.jboss.seam.initProcess.&lt;name&gt; — called when the process &lt;name&gt; is associated with the conversation<br />
• org.jboss.seam.initTask.&lt;name&gt; — called when the task &lt;name&gt; is associated with the conversation<br />
• org.jboss.seam.startTask.&lt;name&gt; — called when the task &lt;name&gt; is started<br />
• org.jboss.seam.endTask.&lt;name&gt; — called when the task &lt;name&gt; is ended<br />
• org.jboss.seam.postCreate.&lt;name&gt; — called when the component &lt;name&gt; is created<br />
• org.jboss.seam.preDestroy.&lt;name&gt; — called when the component &lt;name&gt; is destroyed<br />
• org.jboss.seam.beforePhase — called before the start of a JSF phase<br />
• org.jboss.seam.afterPhase — called after the end of a JSF phase<br />
• org.jboss.seam.postInitialization — called when Seam has initialized and started up all components<br />
• org.jboss.seam.postAuthenticate.&lt;name&gt; — called after a user is authenticated<br />
• org.jboss.seam.preAuthenticate.&lt;name&gt; — called before attempting to authenticate a user<br />
• org.jboss.seam.notLoggedIn — called there is no authenticated user and authentication is required<br />
• org.jboss.seam.rememberMe — occurs when Seam security detects the username in a cookie<br />
• org.jboss.seam.exceptionHandled.&lt;type&gt; — called when an uncaught exception is handled by Seam<br />
• org.jboss.seam.exceptionHandled — called when an uncaught exception is handled by Seam<br />
• org.jboss.seam.exceptionNotHandled — called when there was no handler for an uncaught exception<br />
• org.jboss.seam.afterTransactionSuccess — called when a transaction succeeds in the Seam Application Framework<br />
• org.jboss.seam.afterTransactionSuccess.&lt;name&gt; — called when a transaction succeeds in the Seam Application Framework which<br />
manages an entity called &lt;name&gt;.</p>
<p>Seam components may observe any of these events in just the same way they observe any other component-driven events.</p>
<p>Seam interceptors: EJB 3.0 introduced a standard interceptor model for session bean components. To add an interceptor to a<br />
bean, you need to write a class with a method annotated @AroundInvoke and annotate the bean with an @Interceptors annotation<br />
that specifies the name of the interceptor class. For example, the following interceptor checks that the user is logged in<br />
before allowing invoking an action listener method:</p>
<p>public class LoggedInInterceptor {<br />
@AroundInvoke<br />
public Object checkLoggedIn(InvocationContext invocation) throws Exception {<br />
boolean isLoggedIn = Contexts.getSessionContext().get(&#8220;loggedIn&#8221;)!=null;<br />
if (isLoggedIn) {<br />
//the user is already logged in<br />
return invocation.proceed();<br />
}<br />
else {<br />
//the user is not logged in, fwd to login page<br />
return &#8220;login&#8221;;<br />
}<br />
}<br />
}</p>
<p>To apply this interceptor to a session bean which acts as an action listener, we must annotate the session bean<br />
@Interceptors(LoggedInInterceptor.class). This is a somewhat ugly annotation. Seam builds upon the interceptor framework in<br />
EJB3 by allowing you to use @Interceptors as a meta-annotation for class level interceptors (those annotated @Target(TYPE)).<br />
In our example, we would create an @LoggedIn annotation, as follows:</p>
<p>@Target(TYPE)<br />
@Retention(RUNTIME)<br />
@Interceptors(LoggedInInterceptor.class)<br />
public @interface LoggedIn {}</p>
<p>We can now simply annotate our action listener bean with @LoggedIn to apply the interceptor.</p>
<p>@Stateless<br />
@Name(&#8220;changePasswordAction&#8221;)<br />
@LoggedIn<br />
@Interceptors(SeamInterceptor.class)<br />
public class ChangePasswordAction implements ChangePassword {<br />
&#8230;<br />
public String changePassword() { &#8230; }<br />
}</p>
<p>If interceptor ordering is important (it usually is), you can add @Interceptor annotations to your<br />
interceptor classes to specify a partial order of interceptors.</p>
<p>@Interceptor(around={BijectionInterceptor.class,<br />
ValidationInterceptor.class,<br />
ConversationInterceptor.class},<br />
within=RemoveInterceptor.class)<br />
public class LoggedInInterceptor<br />
{<br />
&#8230;<br />
}</p>
<p>You can even have a &#8220;client-side&#8221; interceptor, that runs around any of the built-in functionality of EJB3:</p>
<p>@Interceptor(type=CLIENT)<br />
public class LoggedInInterceptor<br />
{<br />
&#8230;<br />
}</p>
<p>EJB interceptors are stateful, with a lifecycle that is the same as the component they intercept. For interceptors which do<br />
not need to maintain state, Seam lets you get a performance optimization by specifying @Interceptor(stateless=true).</p>
<p>Much of the functionality of Seam is implemented as a set of built-in Seam interceptors, including<br />
the interceptors named in the previous example. You don&#8217;t have to explicitly specify these<br />
interceptors by annotating your components; they exist for all interceptable Seam components.</p>
<p>You can even use Seam interceptors with JavaBean components, not just EJB3 beans!</p>
<p>EJB defines interception not only for business methods (using @AroundInvoke), but also for the lifecycle methods<br />
@PostConstruct, @PreDestroy, @PrePassivate and @PostActive. Seam supports all these lifecycle methods on both component and<br />
interceptor not only for EJB3 beans, but also for JavaBean components (except @PreDestroy which is not meaningful for<br />
JavaBean components).</p>
<p>Managing exceptions: JSF is surprisingly limited when it comes to exception handling. As a partial workaround for this<br />
problem, Seam lets you define how a particular class of exception is to be treated by annotating the exception class, or<br />
declaring the exception class in an XML file. This facility is meant to be combined with the EJB 3.0-standard<br />
@ApplicationException annotation which specifies whether the exception should cause a transaction rollback.</p>
<p>Exceptions and transactions: EJB specifies well-defined rules that let us control whether an exception immediately marks the<br />
current transaction for rollback when it is thrown by a business method of the bean: system exceptions always cause a<br />
transaction rollback, application exceptions do not cause a rollback by default, but they do if<br />
@ApplicationException(rollback=true) is specified. (An application exception is any checked exception, or any unchecked<br />
exception annotated @ApplicationException. A system exception is any unchecked exception without an @ApplicationException<br />
annotation).</p>
<p>Note that there is a difference between marking a transaction for rollback, and actually rolling it back. The exception rules<br />
say that the transaction should be marked rollback only, but it may still be active after the exception is thrown.</p>
<p>Seam applies the EJB 3.0 exception rollback rules also to Seam JavaBean components.</p>
<p>But these rules only apply in the Seam component layer. What about an exception that is uncaught and propagates out of the<br />
Seam component layer, and out of the JSF layer? Well, it is always wrong to leave a dangling transaction open, so Seam rolls<br />
back any active transaction when an exception occurs and is uncaught in the Seam component layer.</p>
<p>Enabling Seam exception handling: To enable Seam&#8217;s exception handling, we need to make sure we have the master servlet filter<br />
declared in web.xml:</p>
<p>&lt;filter&gt;<br />
&lt;filter-name&gt;Seam Filter&lt;/filter-name&gt;<br />
&lt;filter-class&gt;org.jboss.seam.servlet.SeamFilter&lt;/filter-class&gt;<br />
&lt;/filter&gt;<br />
&lt;filter-mapping&gt;<br />
&lt;filter-name&gt;Seam Filter&lt;/filter-name&gt;<br />
&lt;url-pattern&gt;*.seam&lt;/url-pattern&gt;<br />
&lt;/filter-mapping&gt;</p>
<p>You may also need to disable Facelets development mode in web.xml and Seam debug mode in components.xml if you want your<br />
exception handlers to fire.</p>
<p>Using annotations for exception handling: The following exception results in a HTTP 404 error whenever it propagates out of<br />
the Seam component layer. It does not roll back the current transaction immediately when thrown, but the transaction will be<br />
rolled back if it the exception is not caught by another Seam component.</p>
<p>@HttpError(errorCode=404)<br />
public class ApplicationException extends Exception { &#8230; }</p>
<p>This exception results in a browser redirect whenever it propagates out of the Seam component layer. It also ends the current<br />
conversation. It causes an immediate rollback of the current transaction.</p>
<p>@Redirect(viewId=&#8221;/failure.xhtml&#8221;, end=true)<br />
@ApplicationException(rollback=true)<br />
public class UnrecoverableApplicationException extends RuntimeException { &#8230; }</p>
<p>Note that @Redirect does not work for exceptions which occur during the render phase of the JSF lifecycle.<br />
You can also use EL to specify the viewId to redirect to.</p>
<p>This exception results in a redirect, along with a message to the user, when it propagates out of<br />
the Seam component layer. It also immediately rolls back the current transaction.</p>
<p>@Redirect(viewId=&#8221;/error.xhtml&#8221;, message=&#8221;Unexpected error&#8221;)<br />
public class SystemException extends RuntimeException { &#8230; }</p>
<p>Using XML for exception handling: Since we can&#8217;t add annotations to all the exception classes we are interested in, Seam also<br />
lets us specify this functionality in pages.xml.</p>
<p>&lt;pages&gt;<br />
&lt;exception&gt;<br />
&lt;http-error error-code=&#8221;404&#8243;/&gt;<br />
&lt;/exception&gt;<br />
&lt;exception&gt;<br />
&lt;end-conversation/&gt;<br />
&lt;redirect view-id=&#8221;/error.xhtml&#8221;&gt;<br />
&lt;message&gt;Database access failed&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;<br />
&lt;exception&gt;<br />
&lt;end-conversation/&gt;<br />
&lt;redirect view-id=&#8221;/error.xhtml&#8221;&gt;<br />
&lt;message&gt;Unexpected failure&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;<br />
&lt;/pages&gt;</p>
<p>The last &lt;exception&gt; declaration does not specify a class, and is a catch-all for any exception<br />
for which handling is not otherwise specified via annotations or in pages.xml.</p>
<p>You can also use EL to specify the view-id to redirect to.</p>
<p>You can also access the handled exception instance through EL, Seam places it in the conversation context, e.g. to access the<br />
message of the exception:</p>
<p>&#8230;<br />
throw new AuthorizationException(&#8220;You are not allowed to do this!&#8221;);<br />
&lt;pages&gt;<br />
&lt;exception&gt;<br />
&lt;end-conversation/&gt;<br />
&lt;redirect view-id=&#8221;/error.xhtml&#8221;&gt;<br />
&lt;message severity=&#8221;WARN&#8221;&gt;#{org.jboss.seam.handledException.message}&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;<br />
&lt;/pages&gt;</p>
<p>org.jboss.seam.handledException holds the nested exception that was actually handled by an exception handler. The outermost<br />
(wrapper) exception is also available, as org.jboss.seam.exception.</p>
<p>Suppressing exception logging: For the exception handlers defined in pages.xml, it is possible to declare the logging level<br />
at which the exception will be logged, or to even suppress the exception being logged altogether. The attributes log and<br />
logLevel can be used to control exception logging. By setting log=&#8221;false&#8221; as per the following example, then no log message<br />
will be generated when the specified exception occurs:</p>
<p>&lt;exception log=&#8221;false&#8221;&gt;<br />
&lt;redirect view-id=&#8221;/register.xhtml&#8221;&gt;<br />
&lt;message severity=&#8221;warn&#8221;&gt;You must be a member to use this feature&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;</p>
<p>If the log attribute is not specified, then it defaults to true (i.e. the exception will be logged).<br />
Alternatively, you can specify the logLevel to control at which log level the exception will be logged:</p>
<p>&lt;exception logLevel=&#8221;info&#8221;&gt;<br />
&lt;redirect view-id=&#8221;/register.xhtml&#8221;&gt;<br />
&lt;message severity=&#8221;warn&#8221;&gt;You must be a member to use this feature&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;</p>
<p>The acceptable values for logLevel are: fatal, error, warn, info, debug or trace. If the logLevel is not specified, or if an<br />
invalid value is configured, then it will default to error.</p>
<p>Some common exceptions:<br />
If you are using JPA:</p>
<p>&lt;exception&gt;<br />
&lt;redirect view-id=&#8221;/error.xhtml&#8221;&gt;<br />
&lt;message&gt;Not found&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;</p>
<p>&lt;exception&gt;<br />
&lt;end-conversation/&gt;<br />
&lt;redirect view-id=&#8221;/error.xhtml&#8221;&gt;<br />
&lt;message&gt;Another user changed the same data, please try again&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;</p>
<p>If you are using the Seam Application Framework:</p>
<p>&lt;exception&gt;<br />
&lt;redirect view-id=&#8221;/error.xhtml&#8221;&gt;<br />
&lt;message&gt;Not found&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;</p>
<p>If you are using Seam Security:</p>
<p>&lt;exception&gt;<br />
&lt;redirect&gt;<br />
&lt;message&gt;You don&#8217;t have permission to do this&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;</p>
<p>&lt;exception&gt;<br />
&lt;redirect view-id=&#8221;/login.xhtml&#8221;&gt;<br />
&lt;message&gt;Please log in first&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;</p>
<p>And, for JSF:</p>
<p>&lt;exception&gt;<br />
&lt;redirect view-id=&#8221;/error.xhtml&#8221;&gt;<br />
&lt;message&gt;Your session has timed out, please try again&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;</p>
<p>A ViewExpiredException occurs if the user posts back to a page once their session has expired. no-conversation-view-id and<br />
conversation-required give you finer grained control over session expiration if you are inside a conversation.</p>
<p>Conversations and workspace management:<br />
Seam&#8217;s conversation model: The examples we have seen so far make use of a very simple conversation model that follows<br />
these rules:</p>
<p>• There is always a conversation context active during the apply request values, process validations, update model values,<br />
invoke application and render response phases of the JSF request lifecycle.<br />
• At the end of the restore view phase of the JSF request lifecycle, Seam attempts to restore any previous long-running<br />
conversation context. If none exists, Seam creates a new temporary conversation context.<br />
• When an @Begin method is encountered, the temporary conversation context is promoted to a long running conversation.<br />
• When an @End method is encountered, any long-running conversation context is demoted to a temporary conversation.<br />
• At the end of the render response phase of the JSF request lifecycle, Seam stores the contents<br />
of a long running conversation context or destroys the contents of a temporary conversation context.<br />
• Any faces request (a JSF postback) will propagate the conversation context. By default, nonfaces requests<br />
(GET requests, for example) do not propagate the conversation context, but see below for more information on this.<br />
• If the JSF request lifecycle is foreshortened by a redirect, Seam transparently stores and restores the current<br />
conversation context—unless the conversation was already ended via @End(beforeRedirect=true).</p>
<p>Seam transparently propagates the conversation context (including the temporary conversation context) across JSF postbacks<br />
and redirects. If you don&#8217;t do anything special, a non-faces request (a GET request for example) will not propagate the<br />
conversation context and will be processed in a new temporary conversation. It&#8217;s usually the desired behavior.</p>
<p>If you want to propagate a Seam conversation across a non-faces request, you need to explicitly<br />
code the Seam conversation id as a request parameter:</p>
<p>&lt;a href=&#8221;main.jsf?conversationId=#{conversation.id}&#8221;&gt;Continue&lt;/a&gt;</p>
<p>Or, the more JSF-ish:</p>
<p>&lt;h:outputLink value=&#8221;main.jsf&#8221;&gt;<br />
&lt;f:param name=&#8221;conversationId&#8221; value=&#8221;#{conversation.id}&#8221;/&gt;<br />
&lt;h:outputText value=&#8221;Continue&#8221;/&gt;<br />
&lt;/h:outputLink&gt;</p>
<p>If you use the Seam tag library, this is equivalent:</p>
<p>&lt;h:outputLink value=&#8221;main.jsf&#8221;&gt;<br />
&lt;s:conversationId/&gt;<br />
&lt;h:outputText value=&#8221;Continue&#8221;/&gt;<br />
&lt;/h:outputLink&gt;</p>
<p>If you wish to disable propagation of the conversation context for a postback, a similar trick is used:</p>
<p>&lt;h:commandLink action=&#8221;main&#8221; value=&#8221;Exit&#8221;&gt;<br />
&lt;f:param name=&#8221;conversationPropagation&#8221; value=&#8221;none&#8221;/&gt;<br />
&lt;/h:commandLink&gt;</p>
<p>If you use the Seam tag library, this is equivalent:</p>
<p>&lt;h:commandLink action=&#8221;main&#8221; value=&#8221;Exit&#8221;&gt;<br />
&lt;s:conversationPropagation type=&#8221;none&#8221;/&gt;<br />
&lt;/h:commandLink&gt;</p>
<p>Note that disabling conversation context propagation is absolutely not the same thing as ending the conversation.</p>
<p>The conversationPropagation request parameter, or the &lt;s:conversationPropagation&gt; tag<br />
may even be used to begin and end conversation, or begin a nested conversation.</p>
<p>&lt;h:commandLink action=&#8221;main&#8221; value=&#8221;Exit&#8221;&gt;<br />
&lt;s:conversationPropagation type=&#8221;end&#8221;/&gt;<br />
&lt;/h:commandLink&gt;<br />
&lt;h:commandLink action=&#8221;main&#8221; value=&#8221;Select Child&#8221;&gt;<br />
&lt;s:conversationPropagation type=&#8221;nested&#8221;/&gt;<br />
&lt;/h:commandLink&gt;<br />
&lt;h:commandLink action=&#8221;main&#8221; value=&#8221;Select Hotel&#8221;&gt;<br />
&lt;s:conversationPropagation type=&#8221;begin&#8221;/&gt;<br />
&lt;/h:commandLink&gt;<br />
&lt;h:commandLink action=&#8221;main&#8221; value=&#8221;Select Hotel&#8221;&gt;<br />
&lt;s:conversationPropagation type=&#8221;join&#8221;/&gt;<br />
&lt;/h:commandLink&gt;</p>
<p>This conversation model makes it easy to build applications which behave correctly with respect<br />
to multi-window operation. For many applications, this is all that is needed. Some complex<br />
applications have either or both of the following additional requirements:</p>
<p>• A conversation spans many smaller units of user interaction, which execute serially or even<br />
concurrently. The smaller nested conversations have their own isolated set of conversation<br />
state, and also have access to the state of the outer conversation.</p>
<p>• The user is able to switch between many conversations within the same browser window. This<br />
feature is called workspace management.</p>
<p>Nested conversations: A nested conversation is created by invoking a method marked @Begin(nested=true) inside the scope of an<br />
existing conversation. A nested conversation has its own conversation context, and also has read-only access to the context<br />
of the outer conversation. (It can read the outer conversation&#8217;s context variables, but not write to them.) When an @End is<br />
subsequently encountered, the nested conversation will be destroyed, and the outer conversation will resume, by &#8220;popping&#8221;<br />
the conversation stack. Conversations may be nested to any arbitrary depth. Certain user activity (workspace management, or<br />
the back button) can cause the outer conversation to be resumed before the inner conversation is ended. In this case it is<br />
possible to have multiple concurrent nested conversations belonging to the same outer conversation.<br />
If the outer conversation ends before a nested conversation ends, Seam destroys all nested conversation contexts along with<br />
the outer context. A conversation may be thought of as a continuable state. Nested conversations allow the application to<br />
capture a consistent continuable state at various points in a user interaction, thus insuring truly correct behavior in the<br />
face of backbuttoning and workspace management. TODO: an example to show how a nested conversation prevents bad stuff<br />
happening when you backbutton. Usually, if a component exists in a parent conversation of the current nested conversation,<br />
the nested conversation will use the same instance. Occasionally, it is useful to have a different instance in each nested<br />
conversation, so that the component instance that exists in the parent conversation is invisible to its child conversations.<br />
You can achieve this behavior by annotating the component @PerNestedConversation.</p>
<p>Starting conversations with GET requests:<br />
JSF does not define any kind of action listener that is triggered when a page is accessed via a non-faces request<br />
(for example, a HTTP GET request). This can occur if the user bookmarks the page, or if we navigate to the page via an<br />
&lt;h:outputLink&gt;. Sometimes we want to begin a conversation immediately the page is accessed. Since there is no JSF action<br />
method, we can&#8217;t solve the problem in the usual way, by annotating the action with @Begin. A further problem arises if the<br />
page needs some state to be fetched into a context variable. We&#8217;ve already seen two ways to solve this problem. If that<br />
state is held in a Seam component, we can fetch the state in a @Create method. If not, we can define a @Factory method for<br />
the context variable. If none of these options works for you, Seam lets you define a page action in the pages.xml file.</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/messageList.jsp&#8221; action=&#8221;#{messageManager.list}&#8221;/&gt;<br />
&#8230;<br />
&lt;/pages&gt;</p>
<p>This action method is called at the beginning of the render response phase, any time the page is about to be rendered. If a<br />
page action returns a non-null outcome, Seam will process any appropriate JSF and Seam navigation rules, possibly resulting<br />
in a completely different page being rendered.<br />
If all you want to do before rendering the page is begin a conversation, you could use a built-in action method that does<br />
just that:</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/messageList.jsp&#8221; action=&#8221;#{conversation.begin}&#8221;/&gt;<br />
&#8230;<br />
&lt;/pages&gt;<br />
Note that you can also call this built-in action from a JSF control, and, similarly, you can use<br />
#{conversation.end} to end conversations.<br />
If you want more control, to join existing conversations or begin a nested conversion, to begin a<br />
pageflow or an atomic conversation, you should use the &lt;begin-conversation&gt; element.<br />
&lt;pages&gt;<br />
&lt;page view-id=&#8221;/messageList.jsp&#8221;&gt;<br />
&lt;begin-conversation nested=&#8221;true&#8221; pageflow=&#8221;AddItem&#8221;/&gt;<br />
&lt;page&gt;<br />
&#8230;<br />
&lt;/pages&gt;</p>
<p>There is also an &lt;end-conversation&gt; element.</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/home.jsp&#8221;&gt;<br />
&lt;end-conversation/&gt;<br />
&lt;page&gt;<br />
&#8230;<br />
&lt;/pages&gt;</p>
<p>To solve the first problem, we now have five options:<br />
• Annotate the @Create method with @Begin<br />
• Annotate the @Factory method with @Begin<br />
• Annotate the Seam page action method with @Begin<br />
• Use &lt;begin-conversation&gt; in pages.xml.<br />
• Use #{conversation.begin} as the Seam page action method</p>
<p>Using &lt;s:link&gt; and &lt;s:button&gt;:<br />
JSF command links always perform a form submission via JavaScript, which breaks the web browser&#8217;s &#8220;open in new window&#8221; or<br />
&#8220;open in new tab&#8221; feature. In plain JSF, you need to use an &lt;h:outputLink&gt; if you need this functionality. But there are two<br />
major limitations to &lt;h:outputLink&gt;.<br />
• JSF provides no way to attach an action listener to an &lt;h:outputLink&gt;.<br />
• JSF does not propagate the selected row of a DataModel since there is no actual form submission.</p>
<p>Seam provides the notion of a page action to help solve the first problem, but this does nothing to help us with the second<br />
problem. We could work around this by using the RESTful approach of passing a request parameter and requerying for the<br />
selected object on the server side. In some cases—such as the Seam blog example application—this is indeed the best approach.<br />
The RESTful style supports bookmarking, since it does not require server-side state. In other cases, where we don&#8217;t care<br />
about bookmarks, the use of @DataModel and @DataModelSelection is just so convenient and transparent!<br />
To fill in this missing functionality, and to make conversation propagation even simpler to manage, Seam provides the<br />
&lt;s:link&gt; JSF tag. The link may specify just the JSF view id:</p>
<p>&lt;s:link view=&#8221;/login.xhtml&#8221; value=&#8221;Login&#8221;/&gt;</p>
<p>Or, it may specify an action method (in which case the action outcome determines the page that results):</p>
<p>&lt;s:link action=&#8221;#{login.logout}&#8221; value=&#8221;Logout&#8221;/&gt;</p>
<p>If you specify both a JSF view id and an action method, the &#8216;view&#8217; will be used unless the action method returns a non-null<br />
outcome:<br />
&lt;s:link view=&#8221;/loggedOut.xhtml&#8221; action=&#8221;#{login.logout}&#8221; value=&#8221;Logout&#8221;/&gt;</p>
<p>The link automatically propagates the selected row of a DataModel using inside &lt;h:dataTable&gt;:</p>
<p>&lt;s:link view=&#8221;/hotel.xhtml&#8221; action=&#8221;#{hotelSearch.selectHotel}&#8221; value=&#8221;#{hotel.name}&#8221;/&gt;</p>
<p>You can leave the scope of an existing conversation:</p>
<p>&lt;s:link view=&#8221;/main.xhtml&#8221; propagation=&#8221;none&#8221;/&gt;</p>
<p>You can begin, end, or nest conversations:</p>
<p>&lt;s:link action=&#8221;#{issueEditor.viewComment}&#8221; propagation=&#8221;nest&#8221;/&gt;</p>
<p>If the link begins a conversation, you can even specify a pageflow to be used:</p>
<p>&lt;s:link action=&#8221;#{documentEditor.getDocument}&#8221; propagation=&#8221;begin&#8221; pageflow=&#8221;EditDocument&#8221;/&gt;</p>
<p>The taskInstance attribute if for use in jBPM task lists:</p>
<p>&lt;s:link action=&#8221;#{documentApproval.approveOrReject}&#8221; taskInstance=&#8221;#{task}&#8221;/&gt;<br />
(See the DVD Store demo application for examples of this.)</p>
<p>Finally, if you need the &#8220;link&#8221; to be rendered as a button, use &lt;s:button&gt;:</p>
<p>&lt;s:button action=&#8221;#{login.logout}&#8221; value=&#8221;Logout&#8221;/&gt;</p>
<p>Success messages: It is quite common to display a message to the user indicating success or failure of an action. It is<br />
convenient to use a JSF FacesMessage for this. Unfortunately, a successful action often requires a browser redirect, and JSF<br />
does not propagate faces messages across redirects. This makes it quite difficult to display success messages in plain JSF.<br />
The built in conversation-scoped Seam component named facesMessages solves this problem.<br />
(You must have the Seam redirect filter installed).</p>
<p>@Name(&#8220;editDocumentAction&#8221;)<br />
@Stateless<br />
public class EditDocumentBean implements EditDocument {<br />
@In EntityManager em;<br />
@In Document document;<br />
@In FacesMessages facesMessages;<br />
public String update() {<br />
em.merge(document);<br />
facesMessages.add(&#8220;Document updated&#8221;);<br />
}<br />
}</p>
<p>Any message added to facesMessages is used in the very next render response phase for the current conversation. This even<br />
works when there is no long-running conversation since Seam preserves even temporary conversation contexts across redirects.<br />
You can even include JSF EL expressions in a faces message summary:</p>
<p>facesMessages.add(&#8220;Document #{document.title} was updated&#8221;);</p>
<p>You may display the messages in the usual way, for example:</p>
<p>&lt;h:messages globalOnly=&#8221;true&#8221;/&gt;</p>
<p>Natural conversation ids:<br />
When working with conversations that deal with persistent objects, it may be desirable to use the<br />
natural business key of the object instead of the standard, &#8220;surrogate&#8221; conversation id:<br />
Easy redirect to existing conversation<br />
It can be useful to redirect to an existing conversation if the user requests the same operation<br />
twice. Take this example: “ You are on ebay, half way through paying for an item you just won as<br />
a Christmas present for your parents. Lets say you&#8217;re sending it straight to them &#8211; you enter your<br />
payment details but you can&#8217;t remember their address. You accidentally reuse the same browser<br />
window finding out their address. Now you need to return to the payment for the item. ”<br />
With a natural conversation its really easy to have the user rejoin the existing conversation, and<br />
pick up where they left off &#8211; just have them to rejoin the payForItem conversation with the itemId<br />
as the conversation id.</p>
<p>User friendly URLs<br />
For me this consists of a navigable hierarchy (I can navigate by editing the url) and a meaningful<br />
URL (like this Wiki uses &#8211; so don&#8217;t identify things by random ids). For some applications user<br />
friendly URLs are less important, of course.<br />
With a natural conversations, when you are building your hotel booking system (or,<br />
of course, whatever your app is) you can generate a URL like http://seam-hotels/<br />
book.seam?hotel=BestWesternAntwerpen (of course, whatever parameter hotel maps to on<br />
your domain model must be unique) and with URLRewrite easily transform this to http://seamhotels/<br />
book/BestWesternAntwerpen.</p>
<p>Creating a natural conversation: Natural conversations are defined in pages.xml:</p>
<p>&lt;conversation name=&#8221;PlaceBid&#8221; parameter-name=&#8221;auctionId&#8221; parameter-value=&#8221;#{auction.auctionId}&#8221;/&gt;</p>
<p>The first thing to note from the above definition is that the conversation has a name, in this case<br />
PlaceBid. This name uniquely identifies this particular named conversation, and is used by the<br />
page definition to identify a named conversation to participate in.</p>
<p>The next attribute, parameter-name defines the request parameter that will contain the natural<br />
conversation id, in place of the default conversation id parameter. In this example, the parametername<br />
is auctionId. This means that instead of a conversation parameter like cid=123 appearing<br />
in the URL for your page, it will contain auctionId=765432 instead.</p>
<p>The last attribute in the above configuration, parameter-value, defines an EL expression used<br />
to evaluate the value of the natural business key to use as the conversation id. In this example,<br />
the conversation id will be the primary key value of the auction instance currently in scope.</p>
<p>Next, we define which pages will participate in the named conversation. This is done by specifying<br />
the conversation attribute for a page definition:</p>
<p>&lt;page view-id=&#8221;/bid.xhtml&#8221; conversation=&#8221;PlaceBid&#8221; login-required=&#8221;true&#8221;&gt;<br />
&lt;navigation from-action=&#8221;#{bidAction.confirmBid}&#8221;&gt;<br />
&lt;rule if-outcome=&#8221;success&#8221;&gt;<br />
&lt;redirect view-id=&#8221;/auction.xhtml&#8221;&gt;<br />
&lt;param name=&#8221;id&#8221; value=&#8221;#{bidAction.bid.auction.auctionId}&#8221;/&gt;<br />
&lt;/redirect&gt;<br />
&lt;/rule&gt;<br />
&lt;/navigation&gt;<br />
&lt;/page&gt;</p>
<p>Redirecting to a natural conversation: When starting, or redirecting to, a natural conversation there are a number of<br />
options for specifying the natural conversation name. Let&#8217;s start by looking at the following page definition:</p>
<p>&lt;page view-id=&#8221;/auction.xhtml&#8221;&gt;<br />
&lt;param name=&#8221;id&#8221; value=&#8221;#{auctionDetail.selectedAuctionId}&#8221;/&gt;<br />
&lt;navigation from-action=&#8221;#{bidAction.placeBid}&#8221;&gt;<br />
&lt;redirect view-id=&#8221;/bid.xhtml&#8221;/&gt;<br />
&lt;/navigation&gt;<br />
&lt;/page&gt;</p>
<p>From here, we can see that invoking the action #{bidAction.placeBid} from our auction view (by the way, all these examples<br />
are taken from the seamBay example in Seam), that we will be redirected to /bid.xhtml, which, as we saw previously, is<br />
configured with the natural conversation PlaceBid. The declaration for our action method looks like this:</p>
<p>@Begin(join = true)<br />
public void placeBid()</p>
<p>When named conversations are specified in the &lt;page/&gt; element, redirection to the named conversation occurs as part of<br />
navigation rules, after the action method has already been invoked. This is a problem when redirecting to an existing<br />
conversation, as redirection needs to be occur before the action method is invoked. Therefore it is necessary to specify the<br />
conversation name when the action is invoked. One way of doing this is by using the s:conversationName tag:</p>
<p>&lt;h:commandButton id=&#8221;placeBidWithAmount&#8221; styleClass=&#8221;placeBid&#8221; action=&#8221;#{bidAction.placeBid}&#8221;&gt;<br />
&lt;s:conversationName value=&#8221;PlaceBid&#8221;/&gt;<br />
&lt;/h:commandButton&gt;</p>
<p>Another alternative is to specify the conversationName attribute when using either s:link or s:button:</p>
<p>&lt;s:link value=&#8221;Place Bid&#8221; action=&#8221;#{bidAction.placeBid}&#8221; conversationName=&#8221;PlaceBid&#8221;/&gt;</p>
<p>Workspace management: Workspace management is the ability to &#8220;switch&#8221; conversations in a single window. Seam makes workspace<br />
management completely transparent at the level of the Java code. To enable workspace management, all you need to do is:</p>
<p>• Provide description text for each view id (when using JSF or Seam navigation rules) or page node (when using jPDL<br />
pageflows). This description text is displayed to the user by the workspace switchers.</p>
<p>• Include one or more of the standard workspace switcher JSP or facelets fragments in your pages. The standard fragments<br />
support workspace management via a drop down menu, a list of conversations, or breadcrumbs.</p>
<p>Workspace management and JSF navigation: When you use JSF or Seam navigation rules, Seam switches to a conversation by<br />
restoring the current view-id for that conversation. The descriptive text for the workspace is defined in<br />
a file called pages.xml that Seam expects to find in the WEB-INF directory, right next to facesconfig.xml:</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/main.xhtml&#8221;&gt;<br />
&lt;description&gt;Search hotels: #{hotelBooking.searchString}&lt;/description&gt;<br />
&lt;/page&gt;<br />
&lt;page view-id=&#8221;/hotel.xhtml&#8221;&gt;<br />
&lt;description&gt;View hotel: #{hotel.name}&lt;/description&gt;<br />
&lt;/page&gt;<br />
&lt;page view-id=&#8221;/book.xhtml&#8221;&gt;<br />
&lt;description&gt;Book hotel: #{hotel.name}&lt;/description&gt;<br />
&lt;/page&gt;<br />
&lt;page view-id=&#8221;/confirm.xhtml&#8221;&gt;<br />
&lt;description&gt;Confirm: #{booking.description}&lt;/description&gt;<br />
&lt;/page&gt;<br />
&lt;/pages&gt;</p>
<p>Note that if this file is missing, the Seam application will continue to work perfectly! The only<br />
missing functionality will be the ability to switch workspaces.</p>
<p>Workspace management and jPDL pageflow: When you use a jPDL pageflow definition, Seam switches to a conversation by restoring<br />
the current jBPM process state. This is a more flexible model since it allows the same view-id to have<br />
different descriptions depending upon the current &lt;page&gt; node. The description text is defined by the &lt;page&gt; node:</p>
<p>&lt;pageflow-definition name=&#8221;shopping&#8221;&gt;<br />
&lt;start-state name=&#8221;start&#8221;&gt;<br />
&lt;transition to=&#8221;browse&#8221;/&gt;<br />
&lt;/start-state&gt;<br />
&lt;page name=&#8221;browse&#8221; view-id=&#8221;/browse.xhtml&#8221;&gt;<br />
&lt;description&gt;DVD Search: #{search.searchPattern}&lt;/description&gt;<br />
&lt;transition to=&#8221;browse&#8221;/&gt;<br />
&lt;transition name=&#8221;checkout&#8221; to=&#8221;checkout&#8221;/&gt;<br />
&lt;/page&gt;<br />
&lt;page name=&#8221;checkout&#8221; view-id=&#8221;/checkout.xhtml&#8221;&gt;<br />
&lt;description&gt;Purchase: $#{cart.total}&lt;/description&gt;<br />
&lt;transition to=&#8221;checkout&#8221;/&gt;<br />
&lt;transition name=&#8221;complete&#8221; to=&#8221;complete&#8221;/&gt;<br />
&lt;/page&gt;<br />
&lt;page name=&#8221;complete&#8221; view-id=&#8221;/complete.xhtml&#8221;&gt;<br />
&lt;end-conversation /&gt;<br />
&lt;/page&gt;<br />
&lt;/pageflow-definition&gt;</p>
<p>The conversation switcher: Include the following fragment in your JSP or facelets page to get a drop-down menu that lets you<br />
switch to any current conversation, or to any other page of the application:</p>
<p>&lt;h:selectOneMenu value=&#8221;#{switcher.conversationIdOrOutcome}&#8221;&gt;<br />
&lt;f:selectItem itemLabel=&#8221;Find Issues&#8221; itemValue=&#8221;findIssue&#8221;/&gt;<br />
&lt;f:selectItem itemLabel=&#8221;Create Issue&#8221; itemValue=&#8221;editIssue&#8221;/&gt;<br />
&lt;f:selectItems value=&#8221;#{switcher.selectItems}&#8221;/&gt;<br />
&lt;/h:selectOneMenu&gt;<br />
&lt;h:commandButton action=&#8221;#{switcher.select}&#8221; value=&#8221;Switch&#8221;/&gt;</p>
<p>In this example, we have a menu that includes an item for each conversation, together with two<br />
additional items that let the user begin a new conversation.<br />
Only conversations with a description (specified in pages.xml) will be included in the drop-down menu.</p>
<p>The conversation list: The conversation list is very similar to the conversation switcher, except that it is displayed as<br />
a table:</p>
<p>&lt;h:dataTable value=&#8221;#{conversationList}&#8221; var=&#8221;entry&#8221;<br />
rendered=&#8221;#{not empty conversationList}&#8221;&gt;<br />
&lt;h:column&gt;<br />
&lt;f:facet name=&#8221;header&#8221;&gt;Workspace&lt;/f:facet&gt;<br />
&lt;h:commandLink action=&#8221;#{entry.select}&#8221; value=&#8221;#{entry.description}&#8221;/&gt;<br />
&lt;h:outputText value=&#8221;[current]&#8221; rendered=&#8221;#{entry.current}&#8221;/&gt;<br />
&lt;/h:column&gt;<br />
&lt;h:column&gt;<br />
&lt;f:facet name=&#8221;header&#8221;&gt;Activity&lt;/f:facet&gt;<br />
&lt;h:outputText value=&#8221;#{entry.startDatetime}&#8221;&gt;<br />
&lt;f:convertDateTime type=&#8221;time&#8221; pattern=&#8221;hh:mm a&#8221;/&gt;<br />
&lt;/h:outputText&gt;<br />
&lt;h:outputText value=&#8221; &#8211; &#8220;/&gt;<br />
&lt;h:outputText value=&#8221;#{entry.lastDatetime}&#8221;&gt;<br />
&lt;f:convertDateTime type=&#8221;time&#8221; pattern=&#8221;hh:mm a&#8221;/&gt;<br />
&lt;/h:outputText&gt;<br />
&lt;/h:column&gt;<br />
&lt;h:column&gt;<br />
&lt;f:facet name=&#8221;header&#8221;&gt;Action&lt;/f:facet&gt;<br />
&lt;h:commandButton action=&#8221;#{entry.select}&#8221; value=&#8221;#{msg.Switch}&#8221;/&gt;<br />
&lt;h:commandButton action=&#8221;#{entry.destroy}&#8221; value=&#8221;#{msg.Destroy}&#8221;/&gt;<br />
&lt;/h:column&gt;<br />
&lt;/h:dataTable&gt;</p>
<p>We imagine that you will want to customize this for your own application.</p>
<p>Only conversations with a description will be included in the list. Notice that the conversation list lets the user destroy<br />
workspaces.</p>
<p>Breadcrumbs: Breadcrumbs are useful in applications which use a nested conversation model. The breadcrumbs<br />
are a list of links to conversations in the current conversation stack:</p>
<p>&lt;ui:repeat value=&#8221;#{conversationStack}&#8221; var=&#8221;entry&#8221;&gt;<br />
&lt;h:outputText value=&#8221; | &#8220;/&gt;<br />
&lt;h:commandLink value=&#8221;#{entry.description}&#8221; action=&#8221;#{entry.select}&#8221;/&gt;<br />
&lt;/ui:repeat&gt;</p>
<p>Conversational components and JSF component bindings: Conversational components have one minor limitation: they cannot be<br />
used to hold bindings to JSF components. (We generally prefer not to use this feature of JSF unless absolutely necessary,<br />
since it creates a hard dependency from application logic to the view.) On a postback request, component bindings are<br />
updated during the Restore View phase, before the Seam conversation context has been restored. To work around this use an<br />
event scoped component to store the component bindings and inject it into the conversation scoped component that requires it.</p>
<p>@Name(&#8220;grid&#8221;)<br />
@Scope(ScopeType.EVENT)<br />
public class Grid<br />
{<br />
private HtmlPanelGrid htmlPanelGrid;<br />
// getters and setters<br />
&#8230;<br />
}</p>
<p>@Name(&#8220;gridEditor&#8221;)<br />
@Scope(ScopeType.CONVERSATION)<br />
public class GridEditor<br />
{<br />
@In(required=false)<br />
private Grid grid;<br />
&#8230;<br />
}</p>
<p>Also, you can&#8217;t inject a conversation scoped component into an event scoped component which you bind a JSF control to. This<br />
includes Seam built in components like facesMessages. Alternatively, you can access the JSF component tree through the<br />
implicit uiComponent handle. The following example accesses getRowIndex()of the UIData component which backs the data<br />
table during iteration, it prints the current row number:</p>
<p>&lt;h:dataTable id=&#8221;lineItemTable&#8221; var=&#8221;lineItem&#8221; value=&#8221;#{orderHome.lineItems}&#8221;&gt;<br />
&lt;h:column&gt;<br />
Row: #{uiComponent['lineItemTable'].rowIndex}<br />
&lt;/h:column&gt;<br />
&#8230;<br />
&lt;/h:dataTable&gt;</p>
<p>JSF UI components are available with their client identifier in this map.</p>
<p>Concurrent calls to conversational components: We can encounter concurrency — accessing conversational components from AJAX<br />
requests. We&#8217;re going to discuss the options that a Ajax client library should provide to control events originating at the<br />
client — and we&#8217;ll look at the options RichFaces gives us.</p>
<p>Conversational components don&#8217;t allow real concurrent access therefore Seam queues each request to process them serially.<br />
This allows each request to be executed in a deterministic fashion. However, a simple queue isn&#8217;t that great — firstly, if a<br />
method is, for some reason, taking a very long time to complete, running it over and over again whenever the client generates<br />
a request is bad idea (potential for Denial of Service attacks), and, secondly, AJAX is often to used to provide<br />
a quick status update to the user, so continuing to run the action after a long time isn&#8217;t useful.<br />
Therefore Seam queues the action event for a period of time (the concurrent request timeout); if<br />
it can&#8217;t process the event in time, it creates a temporary conversation and prints out a message<br />
to the user to let them know what&#8217;s going on. It&#8217;s therefore very important not to flood the server with AJAX events!<br />
We can set a sensible default for the concurrent request timeout (in ms) in components.xml:</p>
<p>&lt;core:manager concurrent-request-timeout=&#8221;500&#8243; /&gt;</p>
<p>So far we&#8217;ve discussed &#8220;synchronous&#8221; AJAX requests &#8211; the client tells the server that an event has<br />
occur, and then rerenders part of the page based on the result. This approach is great when the<br />
AJAX request is lightweight (the methods called are simple e.g. calculating the sum of a column<br />
of numbers). But what if we need to do a complex computation?<br />
For heavy computation we should use a truly asynchronous (poll based) approach — the client<br />
sends an AJAX request to the server, which causes action to be executed asynchronously on<br />
the server (so the the response to the client is immediate); the client then polls the server for<br />
updates. This is useful when you have a long-running action for which it is important that every<br />
action executes (you don&#8217;t want some to be dropped as duplicates, or to timeout).</p>
<p>How should we design our conversational AJAX application?<br />
Well first, you need to decide whether you want to use the simpler &#8220;synchronous&#8221; request or whether you want to add using a<br />
poll-style approach.</p>
<p>If you go for a &#8220;synchronous&#8221; approach, then you need to make an estimate of how long your<br />
AJAX request will take to complete &#8211; is it much shorter than the concurrent request timeout? If not,<br />
you probably want to alter the concurrent request timeout for this method (as discussed above).<br />
Next you probably want a queue on the client side to prevent flooding the server with requests. If the event occurs often<br />
(e.g. a keypress, onblur of input fields) and immediate update of the client is not a priority you should set a request delay<br />
on the client side. When working out your request delay, factor in that the event may also be queued on the server side.</p>
<p>Finally, the client library may provide an option to abort unfinished duplicate requests in favor of the most recent. You<br />
need to be careful with this option as it can lead to flooding of the server with requests if the server is not able to abort<br />
the unfinished request.</p>
<p>Using a poll-style design requires less fine-tuning. You just mark your action method @Asynchronous and decide on a polling<br />
interval:</p>
<p>int total;<br />
// This method is called when an event occurs on the client<br />
// It takes a really long time to execute<br />
@Asynchronous<br />
public void calculateTotal() {<br />
total = someReallyComplicatedCalculation();<br />
}<br />
// This method is called as the result of the poll<br />
// It&#8217;s very quick to execute<br />
public int getTotal() {<br />
return total;<br />
}</p>
<p>RichFaces Ajax:<br />
RichFaces Ajax is the AJAX library most commonly used with Seam, and provides all the controls discussed above:</p>
<p>eventsQueue — provide a queue in which events are placed. All events are queued and requests are sent to the server serially.<br />
This is useful if the request to the server can take some time to execute (e.g. heavy computation, retrieving<br />
information from a slow source) as the server isn&#8217;t flooded.<br />
• ignoreDupResponses — ignore the response produced by the request if a more recent &#8216;similar&#8217; request is already in the<br />
queue. ignoreDupResponses=&#8221;true&#8221; does not cancel the the processing of the request on the server side — just prevents<br />
unnecessary updates on the client side. This option should be used with care with Seam&#8217;s conversations as it allows multiple<br />
concurrent requests to be made.<br />
• requestDelay — defines the time (in ms.) that the request will be remain on the queue. If the request has not been<br />
processed by after this time the request will be sent (regardless of whether a response has been received) or discarded (if<br />
there is a more recent similar event on the queue).<br />
This option should be used with care with Seam&#8217;s conversations as it allows multiple concurrent requests to be made. You need<br />
to be sure that the delay you set (in combination with the concurrent request timeout) is longer than the action will take<br />
to execute.<br />
• &lt;a:poll reRender=&#8221;total&#8221; interval=&#8221;1000&#8243; /&gt; — Polls the server, and rerenders an area as needed.</p>
<p>Pageflows and business processes: JBoss jBPM is a business process management engine for any Java SE or EE environment. jBPM<br />
lets you represent a business process or user interaction as a graph of nodes representing wait states, decisions, tasks,<br />
web pages, etc. The graph is defined using a simple, very readable, XML dialect called jPDL, and may be edited and visualised<br />
graphically using an eclipse plugin. jPDL is an extensible language, and is suitable for a range of problems, from defining<br />
web application page flow, to traditional workflow management, all the way up to orchestration of services in a SOA<br />
environment.</p>
<p>Seam applications use jBPM for two different problems:</p>
<p>• Defining the pageflow involved in complex user interactions. A jPDL process definition defines<br />
the page flow for a single conversation. A Seam conversation is considered to be a relatively<br />
short-running interaction with a single user.<br />
• Defining the overarching business process. The business process may span multiple<br />
conversations with multiple users. Its state is persistent in the jBPM database, so it is considered<br />
long-running. Coordination of the activities of multiple users is a much more complex problem<br />
than scripting an interaction with a single user, so jBPM offers sophisticated facilities for task<br />
management and dealing with multiple concurrent paths of execution.</p>
<p>Don&#8217;t get these two things confused ! They operate at very different levels or granularity. Pageflow, conversation and task<br />
all refer to a single interaction with a single user. A business process spans many tasks. Futhermore, the two applications<br />
of jBPM are totally orthogonal. You can use them together or independently or not at all.<br />
You don&#8217;t have to know jDPL to use Seam. If you&#8217;re perfectly happy defining pageflow using JSF or Seam navigation rules, and<br />
if your application is more data-driven that process-driven, you probably don&#8217;t need jBPM. But we&#8217;re finding that thinking of<br />
user interaction in terms of a well-defined graphical representation is helping us build more robust applications.</p>
<p>Pageflow in Seam:<br />
There are two ways to define pageflow in Seam:<br />
• Using JSF or Seam navigation rules &#8211; the stateless navigation model<br />
• Using jPDL &#8211; the stateful navigation model<br />
Very simple applications will only need the stateless navigation model. Very complex applications<br />
will use both models in different places. Each model has its strengths and weaknesses!</p>
<p>The two navigation models: The stateless model defines a mapping from a set of named, logical outcomes of an event directly<br />
to the resulting page of the view. The navigation rules are entirely oblivious to any state held by the application other<br />
than what page was the source of the event. This means that your action listener methods must sometimes make decisions about<br />
the page flow, since only they have access to the current state of the application.<br />
Here is an example page flow definition using JSF navigation rules:</p>
<p>&lt;navigation-rule&gt;<br />
&lt;from-view-id&gt;/numberGuess.jsp&lt;/from-view-id&gt;<br />
&lt;navigation-case&gt;<br />
&lt;from-outcome&gt;guess&lt;/from-outcome&gt;<br />
&lt;to-view-id&gt;/numberGuess.jsp&lt;/to-view-id&gt;<br />
&lt;redirect/&gt;<br />
&lt;/navigation-case&gt;<br />
&lt;navigation-case&gt;<br />
&lt;from-outcome&gt;win&lt;/from-outcome&gt;<br />
&lt;to-view-id&gt;/win.jsp&lt;/to-view-id&gt;<br />
&lt;redirect/&gt;<br />
&lt;/navigation-case&gt;<br />
&lt;navigation-case&gt;<br />
&lt;from-outcome&gt;lose&lt;/from-outcome&gt;<br />
&lt;to-view-id&gt;/lose.jsp&lt;/to-view-id&gt;<br />
&lt;redirect/&gt;<br />
&lt;/navigation-case&gt;<br />
&lt;/navigation-rule&gt;</p>
<p>Here is the same example page flow definition using Seam navigation rules:</p>
<p>&lt;page view-id=&#8221;/numberGuess.jsp&#8221;&gt;<br />
&lt;navigation&gt;<br />
&lt;rule if-outcome=&#8221;guess&#8221;&gt;<br />
&lt;redirect view-id=&#8221;/numberGuess.jsp&#8221;/&gt;<br />
&lt;/rule&gt;<br />
&lt;rule if-outcome=&#8221;win&#8221;&gt;<br />
&lt;redirect view-id=&#8221;/win.jsp&#8221;/&gt;<br />
&lt;/rule&gt;<br />
&lt;rule if-outcome=&#8221;lose&#8221;&gt;<br />
&lt;redirect view-id=&#8221;/lose.jsp&#8221;/&gt;<br />
&lt;/rule&gt;<br />
&lt;/navigation&gt;<br />
&lt;/page&gt;</p>
<p>If you find navigation rules overly verbose, you can return view ids directly from your action listener methods:</p>
<p>public String guess() {<br />
if (guess==randomNumber) return &#8220;/win.jsp&#8221;;<br />
if (++guessCount==maxGuesses) return &#8220;/lose.jsp&#8221;;<br />
return null;<br />
}</p>
<p>Note that this results in a redirect. You can even specify parameters to be used in the redirect:</p>
<p>public String search() {<br />
return &#8220;/searchResults.jsp?searchPattern=#{searchAction.searchPattern}&#8221;;<br />
}</p>
<p>The stateful model defines a set of transitions between a set of named, logical application states.<br />
In this model, it is possible to express the flow of any user interaction entirely in the jPDL<br />
pageflow definition, and write action listener methods that are completely unaware of the flow of the interaction.<br />
Here is an example page flow definition using jPDL:</p>
<p>&lt;pageflow-definition name=&#8221;numberGuess&#8221;&gt;<br />
&lt;start-page name=&#8221;displayGuess&#8221; view-id=&#8221;/numberGuess.jsp&#8221;&gt;<br />
&lt;redirect/&gt;<br />
&lt;transition name=&#8221;guess&#8221; to=&#8221;evaluateGuess&#8221;&gt;<br />
&lt;action expression=&#8221;#{numberGuess.guess}&#8221; /&gt;<br />
&lt;/transition&gt;<br />
&lt;/start-page&gt;<br />
&lt;decision name=&#8221;evaluateGuess&#8221; expression=&#8221;#{numberGuess.correctGuess}&#8221;&gt;<br />
&lt;transition name=&#8221;true&#8221; to=&#8221;win&#8221;/&gt;<br />
&lt;transition name=&#8221;false&#8221; to=&#8221;evaluateRemainingGuesses&#8221;/&gt;<br />
&lt;/decision&gt;<br />
&lt;decision name=&#8221;evaluateRemainingGuesses&#8221; expression=&#8221;#{numberGuess.lastGuess}&#8221;&gt;<br />
&lt;transition name=&#8221;true&#8221; to=&#8221;lose&#8221;/&gt;<br />
&lt;transition name=&#8221;false&#8221; to=&#8221;displayGuess&#8221;/&gt;<br />
&lt;/decision&gt;<br />
&lt;page name=&#8221;win&#8221; view-id=&#8221;/win.jsp&#8221;&gt;<br />
&lt;redirect/&gt;<br />
&lt;end-conversation /&gt;<br />
&lt;/page&gt;<br />
&lt;page name=&#8221;lose&#8221; view-id=&#8221;/lose.jsp&#8221;&gt;<br />
&lt;redirect/&gt;<br />
&lt;end-conversation /&gt;<br />
&lt;/page&gt;<br />
&lt;/pageflow-definition&gt;</p>
<p>There are two things we notice immediately here:<br />
• The JSF/Seam navigation rules are much simpler. (However, this obscures the fact that the underlying Java code is more<br />
complex.)<br />
• The jPDL makes the user interaction immediately understandable, without us needing to even look at the JSP or Java code.</p>
<p>In addition, the stateful model is more constrained. For each logical state (each step in the page flow), there are a<br />
constrained set of possible transitions to other states. The stateless model is an ad hoc model which is suitable to<br />
relatively unconstrained, freeform navigation where the user decides where he/she wants to go next, not the application.</p>
<p>The biggest contrast between the two models is the back-button behavior.</p>
<p>Seam and the back button: When JSF or Seam navigation rules are used, Seam lets the user freely navigate via the back,<br />
forward and refresh buttons. It is the responsibility of the application to ensure that conversational state remains<br />
internally consistent when this occurs. Experience with the combination of web application frameworks like Struts or<br />
WebWork &#8211; that do not support a conversational model &#8211; and stateless component models like EJB stateless session beans or<br />
the Spring framework has taught many developers that this is close to impossible to do! However, our experience is that<br />
in the context of Seam, where there is a well-defined conversational model, backed by stateful session beans, it is actually<br />
quite straightforward. Usually it is as simple as combining the use of no-conversation-view-id with null checks at the<br />
beginning of action listener methods. We consider support for freeform navigation to be almost always desirable.<br />
In this case, the no-conversation-view-id declaration goes in pages.xml. It tells Seam to redirect to a different page if a<br />
request originates from a page rendered during a conversation, and that conversation no longer exists:</p>
<p>&lt;page view-id=&#8221;/checkout.xhtml&#8221;<br />
no-conversation-view-id=&#8221;/main.xhtml&#8221;/&gt;</p>
<p>On the other hand, in the stateful model, backbuttoning is interpreted as an undefined transition back to a previous state.<br />
Since the stateful model enforces a defined set of transitions from the current state, back buttoning is by default<br />
disallowed in the stateful model! Seam transparently detects the use of the back button, and blocks any attempt to perform<br />
an action from a previous, &#8220;stale&#8221; page, and simply redirects the user to the &#8220;current&#8221; page (and displays a faces message).<br />
Whether you consider this a feature or a limitation of the stateful model depends upon your point of view: as an application<br />
developer, it is a feature; as a user, it might be frustrating! You can enable backbutton navigation from a particular page<br />
node by setting back=&#8221;enabled&#8221;.</p>
<p>&lt;page name=&#8221;checkout&#8221;<br />
view-id=&#8221;/checkout.xhtml&#8221;<br />
back=&#8221;enabled&#8221;&gt;<br />
&lt;redirect/&gt;<br />
&lt;transition to=&#8221;checkout&#8221;/&gt;<br />
&lt;transition name=&#8221;complete&#8221; to=&#8221;complete&#8221;/&gt;<br />
&lt;/page&gt;</p>
<p>This allows backbuttoning from the checkout state to any previous state! Of course, we still need to define what happens if a<br />
request originates from a page rendered during a pageflow, and the conversation with the pageflow no longer exists. In this<br />
case, the no-conversation-view-id declaration goes into the pageflow definition:</p>
<p>&lt;page name=&#8221;checkout&#8221;<br />
view-id=&#8221;/checkout.xhtml&#8221;<br />
back=&#8221;enabled&#8221;<br />
no-conversation-view-id=&#8221;/main.xhtml&#8221;&gt;<br />
&lt;redirect/&gt;<br />
&lt;transition to=&#8221;checkout&#8221;/&gt;<br />
&lt;transition name=&#8221;complete&#8221; to=&#8221;complete&#8221;/&gt;<br />
&lt;/page&gt;</p>
<p>In practice, both navigation models have their place, and you&#8217;ll quickly learn to recognize when to prefer one model over<br />
the other.</p>
<p>Seam and Object/Relational Mapping: Seam provides extensive support for the two most popular persistence architectures for<br />
Java: Hibernate3, and the Java Persistence API introduced with EJB 3.0. Seam&#8217;s unique statemanagement architecture allows<br />
the most sophisticated ORM integration of any web application framework.</p>
<p>Introduction: The state management architecture of Seam was originally designed to solve problems relating to persistence—in<br />
particular problems associated with optimistic transaction processing. Scalable online applications always use optimistic<br />
transactions. Almost all interesting work involves first displaying data to a user, and then, slightly later, updating the<br />
same data. So Hibernate was designed to support the idea of a persistence context which spanned an optimistic transaction.</p>
<p>Unfortunately, the so-called &#8220;stateless&#8221; architectures that preceded Seam and EJB 3.0 had no construct for representing an<br />
optimistic transaction. So, instead, these architectures provided persistence contexts scoped to the atomic transaction. Of<br />
course, this resulted in many problems for users, and is the cause of the number one user complaint about Hibernate: the<br />
dreaded LazyInitializationException. What we need is a construct for representing an optimistic transaction in the<br />
application tier.</p>
<p>EJB 3.0 recognizes this problem, and introduces the idea of a stateful component (a stateful session bean) with an extended<br />
persistence context scoped to the lifetime of the component. This is a partial solution to the problem however there are<br />
two problems:</p>
<p>• The lifecycle of the stateful session bean must be managed manually via code in the web tier<br />
(it turns out that this is a subtle problem and much more difficult in practice than it sounds).<br />
• Propagation of the persistence context between stateful components in the same optimistic transaction is possible, but<br />
tricky.</p>
<p>Seam solves the first problem by providing conversations, and stateful session bean components scoped to the conversation.<br />
(Most conversations actually represent optimistic transactions in the data layer.) This is sufficient for many simple<br />
applications (such as the Seam booking demo) where persistence context propagation is not needed. For more complex<br />
applications, with many loosly-interacting components in each conversation, propagation of the persistence context across<br />
components becomes an important issue. So Seam extends the persistence context management model of EJB 3.0, to provide<br />
conversation-scoped extended persistence contexts.</p>
<p>Seam managed transactions: EJB session beans feature declarative transaction management. The EJB container is able to start<br />
a transaction transparently when the bean is invoked, and end it when the invocation ends. If we write a session bean method<br />
that acts as a JSF action listener, we can do all the work associated with that action in one transaction, and be sure that<br />
it is committed or rolled back when we finish processing the action. This is a great feature, and all that is needed by some<br />
Seam applications. However, there is a problem with this approach. A Seam application may not perform all data access for a<br />
request from a single method call to a session bean.</p>
<p>• The request might require processing by several loosly-coupled components, each of which is called independently from the<br />
web layer. It is common to see several or even many calls per request from the web layer to EJB components in Seam.<br />
• Rendering of the view might require lazy fetching of associations. The more transactions per request, the more likely we<br />
are to encounter atomicity and isolation problems when our application is processing many concurrent requests. Certainly, all<br />
write operations should occur in the same transaction! Hibernate users developed the &#8220;open session in view&#8221; pattern to work<br />
around this problem. In the Hibernate community, &#8220;open session in view&#8221; was historically even more important because<br />
frameworks like Spring use transaction-scoped persistence contexts. So rendering the view would cause<br />
LazyInitializationExceptions when unfetched associations were accessed. This pattern is usually implemented as a single<br />
transaction which spans the entire request. There are several problems with this implementation, the most serious being that<br />
we can never be sure that a transaction is successful until we commit it—but by the time the &#8220;open session in view&#8221;<br />
transaction is committed, the view is fully rendered, and the rendered response may already have been flushed to the client.<br />
How can we notify the user that their transaction was unsuccessful? Seam solves both the transaction isolation problem and<br />
the association fetching problem, while working around the problems with &#8220;open session in view&#8221;.<br />
The solution comes in two parts:</p>
<p>• use an extended persistence context that is scoped to the conversation, instead of to the transaction.<br />
• use two transactions per request; the first spans the beginning of the restore view phase (some transaction managers begin<br />
the transaction later at the beginning of the apply request vaues phase) until the end of the invoke application phase; the<br />
second spans the render response phase.</p>
<p>In the next section, we&#8217;ll tell you how to set up a conversation-scope persistence context. But first we need to tell you how<br />
to enable Seam transaction management. Note that you can use conversation-scoped persistence contexts without Seam<br />
transaction management, and there are good reasons to use Seam transaction management even when you&#8217;re not using<br />
Seam-managed persistence contexts. However, the two facilities were designed to work together, and work best when used<br />
together.</p>
<p>Seam transaction management is useful even if you&#8217;re using EJB 3.0 container-managed persistence contexts. But it is<br />
especially useful if you use Seam outside a Java EE 5 environment, or in any other case where you would use a Seam-managed<br />
persistence context.</p>
<p>Disabling Seam-managed transactions:<br />
Seam transaction management is enabled by default for all JSF requests. If you want to disable this feature, you can do it in<br />
components.xml:</p>
<p>&lt;core:init transaction-management-enabled=&#8221;false&#8221;/&gt;<br />
&lt;transaction:no-transaction /&gt;</p>
<p>Configuring a Seam transaction manager: Seam provides a transaction management abstraction for beginning, committing,<br />
rolling back, and synchronizing with a transaction. By default Seam uses a JTA transaction component that integrates with<br />
Container Managed and programmatic EJB transactions. If you are working in a Java EE 5 environment, you should install the<br />
EJB synchronization component in components.xml:</p>
<p>&lt;transaction:ejb-transaction /&gt;</p>
<p>However, if you are working in a non EE 5 container, Seam will try auto detect the transaction synchronization mechanism to<br />
use. However, if Seam is unable to detect the correct transaction synchronization to use, you may find you need configure<br />
one of the following:</p>
<p>• JPA RESOURCE_LOCAL transactions with the javax.persistence.EntityTransaction interface. EntityTransaction begins the<br />
transaction at the beginning of the apply request values phase.<br />
• Hibernate managed transactions with the org.hibernate.Transaction interface. HibernateTransaction begins the transaction<br />
at the beginning of the apply request values phase.<br />
• Spring managed transactions with the org.springframework.transaction.PlatformTransactionManager interface. The Spring<br />
PlatformTransactionManagement manager may begin the transaction at the beginning of the apply request values phase if the<br />
userConversationContext attribute is set.<br />
• Explicitly disable Seam managed transactions.</p>
<p>Configure JPA RESOURCE_LOCAL transaction management by adding the following to your components.xml where #{em} is the name<br />
of the persistence:managed-persistence-context component. If your managed persistence context is named entityManager, you can<br />
opt to leave out the entity-manager attribute.</p>
<p>&lt;transaction:entity-transaction entity-manager=&#8221;#{em}&#8221;/&gt;</p>
<p>To configure Hibernate managed transactions declare the following in your components.xml where #{hibernateSession} is the<br />
name of the project&#8217;s persistence:managed-hibernate-session component. If your managed hibernate session is named session,<br />
you can opt to leave out the session attribute.</p>
<p>&lt;transaction:hibernate-transaction session=&#8221;#{hibernateSession}&#8221;/&gt;</p>
<p>To explicitly disable Seam managed transactions declare the following in your components.xml:</p>
<p>&lt;transaction:no-transaction /&gt;</p>
<p>Transaction synchronization: Transaction synchronization provides callbacks for transaction related events such as<br />
beforeCompletion() and afterCompletion(). By default, Seam uses it&#8217;s own transaction synchronization component which requires<br />
explicit use of the Seam transaction component when committing a transaction to ensure synchronization callbacks are<br />
correctly executed. If in a Java EE 5 environment the &lt;transaction:ejb-transaction/&gt; component should be be declared in<br />
components.xml to ensure that Seam synchronization callbacks are correctly called if the container commits a transaction<br />
outside of Seam&#8217;s knowledge.</p>
<p>Seam-managed persistence contexts: If you&#8217;re using Seam outside of a Java EE 5 environment, you can&#8217;t rely upon the container<br />
to manage the persistence context lifecycle for you. Even if you are in an EE 5 environment, you might have a complex<br />
application with many loosly coupled components that collaborate together in the scope of a single conversation, and in this<br />
case you might find that propagation of the persistence context between component is tricky and error-prone.<br />
In either case, you&#8217;ll need to use a managed persistence context (for JPA) or a managed session (for Hibernate) in your<br />
components. A Seam-managed persistence context is just a built-in Seam component that manages an instance of EntityManager or<br />
Session in the conversation context. You can inject it with @In.<br />
Seam-managed persistence contexts are extremely efficient in a clustered environment. Seam is able to perform an optimization<br />
that EJB 3.0 specification does not allow containers to use for container-managed extended persistence contexts. Seam<br />
supports transparent failover of extended persisence contexts, without the need to replicate any persistence context state<br />
between nodes. (We hope to fix this oversight in the next revision of the EJB spec).</p>
<p>Using a Seam-managed persistence context with JPA:<br />
Configuring a managed persistence context is easy. In components.xml, we can write:</p>
<p>&lt;persistence:managed-persistence-context name=&#8221;bookingDatabase&#8221; auto-create=&#8221;true&#8221;<br />
persistence-unit-jndi-name=&#8221;java:/EntityManagerFactories/bookingData&#8221;/&gt;</p>
<p>This configuration creates a conversation-scoped Seam component named bookingDatabase that manages the lifecycle of<br />
EntityManager instances for the persistence unit (EntityManagerFactory instance) with JNDI name<br />
java:/EntityManagerFactories/bookingData.<br />
Of course, you need to make sure that you have bound the EntityManagerFactory into JNDI. In JBoss, you can do this by adding<br />
the following property setting to persistence.xml.</p>
<p>&lt;property name=&#8221;jboss.entity.manager.factory.jndi.name&#8221; value=&#8221;java:/EntityManagerFactories/bookingData&#8221;/&gt;</p>
<p>Now we can have our EntityManager injected using:<br />
@In EntityManager bookingDatabase;</p>
<p>If you are using EJB3 and mark your class or method @TransactionAttribute(REQUIRES_NEW) then the transaction and persistence<br />
context shouldn&#8217;t be propagated to method calls on this object. However as the Seam-managed persistence context is<br />
propagated to any component within the conversation, it will be propagated to methods marked REQUIRES_NEW. Therefore,<br />
if you mark a method REQUIRES_NEW then you should access the entity manager using @PersistenceContext.</p>
<p>Using a Seam-managed Hibernate session:<br />
Seam-managed Hibernate sessions are similar. In components.xml:</p>
<p>&lt;persistence:hibernate-session-factory name=&#8221;hibernateSessionFactory&#8221;/&gt;<br />
&lt;persistence:managed-hibernate-session name=&#8221;bookingDatabase&#8221; auto-create=&#8221;true&#8221;<br />
session-factory-jndi-name=&#8221;java:/bookingSessionFactory&#8221;/&gt;</p>
<p>Where java:/bookingSessionFactory is the name of the session factory specified in hibernate.cfg.xml.</p>
<p>&lt;session-factory name=&#8221;java:/bookingSessionFactory&#8221;&gt;<br />
&lt;property name=&#8221;transaction.flush_before_completion&#8221;&gt;true&lt;/property&gt;<br />
&lt;property name=&#8221;connection.release_mode&#8221;&gt;after_statement&lt;/property&gt;<br />
&lt;property<br />
property&gt;<br />
&lt;property<br />
property&gt;<br />
&lt;property name=&#8221;connection.datasource&#8221;&gt;java:/bookingDatasource&lt;/property&gt;<br />
&#8230;<br />
&lt;/session-factory&gt;</p>
<p>Note that Seam does not flush the session, so you should always enable hibernate.transaction.flush_before_completion to<br />
ensure that the session is automatically flushed before the JTA transaction commits.<br />
We can now have a managed Hibernate Session injected into our JavaBean components using the following code:</p>
<p>@In Session bookingDatabase;</p>
<p>Seam-managed persistence contexts and atomic conversations: Persistence contexts scoped to the conversation allows you to<br />
program optimistic transactions that span multiple requests to the server without the need to use the merge() operation ,<br />
without the need to re-load data at the beginning of each request, and without the need to wrestle with the<br />
LazyInitializationException or NonUniqueObjectException. As with any optimistic transaction management, transaction isolation<br />
and consistency can be achieved via use of optimistic locking. Fortunately, both Hibernate and EJB 3.0 make it very easy<br />
to use optimistic locking, by providing the @Version annotation.</p>
<p>By default, the persistence context is flushed (synchronized with the database) at the end of each transaction. This is<br />
sometimes the desired behavior. But very often, we would prefer that all changes are held in memory and only written to the<br />
database when the conversation ends successfully. This allows for truly atomic conversations. As the result of a truly<br />
stupid and shortsighted decision by certain non-JBoss, non-Sun and non-Sybase members of the EJB 3.0 expert group, there is<br />
currently no simple, usable and portable way to implement atomic conversations using EJB 3.0 persistence. However, Hibernate<br />
provides this feature as a vendor extension to the FlushModeTypes defined by the specification, and it is our expectation<br />
that other vendors will soon provide a similar extension.<br />
Seam lets you specify FlushModeType.MANUAL when beginning a conversation. Currently, this works only when Hibernate is the<br />
underlying persistence provider, but we plan to support other equivalent vendor extensions.</p>
<p>@In EntityManager em; //a Seam-managed persistence context<br />
@Begin(flushMode=MANUAL)<br />
public void beginClaimWizard() {<br />
claim = em.find(Claim.class, claimId);<br />
}</p>
<p>Now, the claim object remains managed by the persistence context for the rest ot the conversation. We can make changes to<br />
the claim:</p>
<p>public void addPartyToClaim() {<br />
Party party = &#8230;.;<br />
claim.addParty(party);<br />
}</p>
<p>But these changes will not be flushed to the database until we explicitly force the flush to occur:</p>
<p>@End<br />
public void commitClaim() {<br />
em.flush();<br />
}</p>
<p>Of course, you could set the flushMode to MANUAL from pages.xml, for example in a navigation rule:</p>
<p>&lt;begin-conversation flush-mode=&#8221;MANUAL&#8221; /&gt;</p>
<p>Using the JPA &#8220;delegate&#8221;: The EntityManager interface lets you access a vendor-specific API via the getDelegate()<br />
method. Naturally, the most interesting vendor is Hibernate, and the most powerful delegate interface is<br />
org.hibernate.Session.<br />
But regardless of whether you&#8217;re using Hibernate or something else, you&#8217;ll almost certainly want to use the delegate in your<br />
Seam components from time to time. One approach would be the following:</p>
<p>@In EntityManager entityManager;<br />
@Create<br />
public void init() {<br />
( (Session) entityManager.getDelegate() ).enableFilter(&#8220;currentVersions&#8221;);<br />
}</p>
<p>But typecasts are unquestionably the ugliest syntax in the Java language, so most people avoid them whenever possible.<br />
Here&#8217;s a different way to get at the delegate. First, add the following line to components.xml:</p>
<p>&lt;factory name=&#8221;session&#8221; scope=&#8221;STATELESS&#8221; auto-create=&#8221;true&#8221; value=&#8221;#{entityManager.delegate}&#8221;/&gt;</p>
<p>Now we can inject the session directly:</p>
<p>@In Session session;<br />
@Create<br />
public void init() {<br />
session.enableFilter(&#8220;currentVersions&#8221;);<br />
}</p>
<p>Using EL in EJB-QL/HQL: Seam proxies the EntityManager or Session object whenever you use a Seam-managed persistence context<br />
or inject a container managed persistence context using @PersistenceContext. This lets you use EL expressions in your query<br />
strings, safely and efficiently. For example, this:</p>
<p>User user = em.createQuery(&#8220;from User where username=#{user.username}&#8221;).getSingleResult();</p>
<p>is equivalent to:</p>
<p>User user = em.createQuery(&#8220;from User where username=:username&#8221;).setParameter(&#8220;username&#8221;, user.getUsername())<br />
.getSingleResult();</p>
<p>Of course, you should never, ever write it like this:</p>
<p>User user = em.createQuery(&#8220;from User where username=&#8221; + user.getUsername()).getSingleResult(); //BAD!<br />
(It is inefficient and vulnerable to SQL injection attacks).</p>
<p>Using Hibernate filters: The coolest, and most unique, feature of Hibernate is filters. Filters let you provide a restricted<br />
view of the data in the database. You can find out more about filters in the Hibernate documentation. But we thought we&#8217;d<br />
mention an easy way to incorporate filters into a Seam application, one that works especially well with the Seam Application<br />
Framework.<br />
Seam-managed persistence contexts may have a list of filters defined, which will be enabled whenever an EntityManager or<br />
Hibernate Session is first created. (Of course, they may only be used when Hibernate is the underlying persistence provider).</p>
<p>&lt;persistence:filter name=&#8221;regionFilter&#8221;&gt;<br />
&lt;persistence:name&gt;region&lt;/persistence:name&gt;<br />
&lt;persistence:parameters&gt;<br />
&lt;key&gt;regionCode&lt;/key&gt;<br />
&lt;value&gt;#{region.code}&lt;/value&gt;<br />
&lt;/persistence:parameters&gt;<br />
&lt;/persistence:filter&gt;</p>
<p>&lt;persistence:filter name=&#8221;currentFilter&#8221;&gt;<br />
&lt;persistence:name&gt;current&lt;/persistence:name&gt;<br />
&lt;persistence:parameters&gt;<br />
&lt;key&gt;date&lt;/key&gt;<br />
&lt;value&gt;#{currentDate}&lt;/value&gt;<br />
&lt;/persistence:parameters&gt;<br />
&lt;/persistence:filter&gt;</p>
<p>&lt;persistence:managed-persistence-context name=&#8221;personDatabase&#8221;<br />
persistence-unit-jndi-name=&#8221;java:/EntityManagerFactories/personDatabase&#8221;&gt;<br />
&lt;core:filters&gt;<br />
&lt;value&gt;#{regionFilter}&lt;/value&gt;<br />
&lt;value&gt;#{currentFilter}&lt;/value&gt;<br />
&lt;/core:filters&gt;<br />
&lt;/persistence:managed-persistence-context&gt;</p>
<p>JSF form validation in Seam: In plain JSF, validation is defined in the view:</p>
<p>&lt;h:form&gt;<br />
&lt;h:messages/&gt;<br />
&lt;div&gt;<br />
Country:<br />
&lt;h:inputText value=&#8221;#{location.country}&#8221; required=&#8221;true&#8221;&gt;<br />
&lt;my:validateCountry/&gt;<br />
&lt;/h:inputText&gt;<br />
&lt;/div&gt;<br />
&lt;div&gt;<br />
Zip code:<br />
&lt;h:inputText value=&#8221;#{location.zip}&#8221; required=&#8221;true&#8221;&gt;<br />
&lt;my:validateZip/&gt;<br />
&lt;/h:inputText&gt;<br />
&lt;/div&gt;<br />
&lt;h:commandButton/&gt;<br />
&lt;/h:form&gt;</p>
<p>In practice, this approach usually violates DRY, since most &#8220;validation&#8221; actually enforces constraints that are part of the<br />
data model, and exist all the way down to the database schema definition. Seam provides support for model-based constraints<br />
defined using Hibernate Validator.<br />
Let&#8217;s start by defining our constraints, on our Location class:</p>
<p>public class Location {<br />
private String country;<br />
private String zip;<br />
@NotNull<br />
@Length(max=30)<br />
public String getCountry() { return country; }<br />
public void setCountry(String c) { country = c; }<br />
@NotNull<br />
@Length(max=6)<br />
@Pattern(&#8220;^\d*$&#8221;)<br />
public String getZip() { return zip; }<br />
public void setZip(String z) { zip = z; }<br />
}</p>
<p>Well, that&#8217;s a decent first cut, but in practice it might be more elegant to use custom constraints<br />
instead of the ones built into Hibernate Validator:</p>
<p>public class Location {<br />
private String country;<br />
private String zip;</p>
<p>@NotNull<br />
@Country<br />
public String getCountry() { return country; }<br />
public void setCountry(String c) { country = c; }</p>
<p>@NotNull<br />
@ZipCode<br />
public String getZip() { return zip; }<br />
public void setZip(String z) { zip = z; }<br />
}</p>
<p>Whichever route we take, we no longer need to specify the type of validation to be used in the JSF page. Instead, we can use<br />
&lt;s:validate&gt; to validate against the constraint defined on the model object.</p>
<p>&lt;h:form&gt;<br />
&lt;h:messages/&gt;<br />
&lt;div&gt;<br />
Country:<br />
&lt;h:inputText value=&#8221;#{location.country}&#8221; required=&#8221;true&#8221;&gt;<br />
&lt;s:validate/&gt;<br />
&lt;/h:inputText&gt;<br />
&lt;/div&gt;<br />
&lt;div&gt;<br />
Zip code:<br />
&lt;h:inputText value=&#8221;#{location.zip}&#8221; required=&#8221;true&#8221;&gt;<br />
&lt;s:validate/&gt;<br />
&lt;/h:inputText&gt;<br />
&lt;/div&gt;<br />
&lt;h:commandButton/&gt;<br />
&lt;/h:form&gt;</p>
<p>Note: specifying @NotNull on the model does not eliminate the requirement for required=&#8221;true&#8221; to appear on the control! This<br />
is due to a limitation of the JSF validation architecture. This approach defines constraints on the model, and presents<br />
constraint violations in the view—a significantly better design.<br />
However, it is not much less verbose than what we started with, so let&#8217;s try &lt;s:validateAll&gt;:</p>
<p>&lt;h:form&gt;<br />
&lt;h:messages/&gt;<br />
&lt;s:validateAll&gt;<br />
&lt;div&gt;<br />
Country:<br />
&lt;h:inputText value=&#8221;#{location.country}&#8221; required=&#8221;true&#8221;/&gt;<br />
&lt;/div&gt;<br />
&lt;div&gt;<br />
Zip code:<br />
&lt;h:inputText value=&#8221;#{location.zip}&#8221; required=&#8221;true&#8221;/&gt;<br />
&lt;/div&gt;<br />
&lt;h:commandButton/&gt;<br />
&lt;/s:validateAll&gt;<br />
&lt;/h:form&gt;</p>
<p>This tag simply adds an &lt;s:validate&gt; to every input in the form. For a large form, it can save a lot of typing!</p>
<p>Now we need to do something about displaying feedback to the user when validation fails.<br />
Currently we are displaying all messages at the top of the form. What we would really like to do is<br />
display the message next to the field with the error (this is possible in plain JSF), highlight the field<br />
and label (this is not possible) and, for good measure, display some image next to the field (also<br />
not possible). We also want to display a little colored asterisk next to the label for each required form field.</p>
<p>That&#8217;s quite a lot of functionality we need for each field of our form. We wouldn&#8217;t want to have to<br />
specify higlighting and the layout of the image, message and input field for every field on the form.<br />
So, instead, we&#8217;ll specify the common layout in a facelets template:</p>
<p>&lt;ui:composition xmlns=&#8221;http://www.w3.org/1999/xhtml&#8221;<br />
xmlns:ui=&#8221;http://java.sun.com/jsf/facelets&#8221;<br />
xmlns:h=&#8221;http://java.sun.com/jsf/html&#8221;<br />
xmlns:f=&#8221;http://java.sun.com/jsf/core&#8221;<br />
xmlns:s=&#8221;http://jboss.com/products/seam/taglib&#8221;&gt;<br />
&lt;div&gt;<br />
&lt;s:label styleClass=&#8221;#{invalid?&#8217;error&#8217;:&#8221;}&#8221;&gt;<br />
&lt;ui:insert name=&#8221;label&#8221;/&gt;<br />
&lt;s:span styleClass=&#8221;required&#8221; rendered=&#8221;#{required}&#8221;&gt;*&lt;/s:span&gt;<br />
&lt;/s:label&gt;<br />
&lt;span&gt;<br />
&lt;h:graphicImage value=&#8221;/img/error.gif&#8221; rendered=&#8221;#{invalid}&#8221;/&gt;<br />
&lt;s:validateAll&gt;<br />
&lt;ui:insert/&gt;<br />
&lt;/s:validateAll&gt;<br />
&lt;/span&gt;<br />
&lt;s:message styleClass=&#8221;error&#8221;/&gt;<br />
&lt;/div&gt;<br />
&lt;/ui:composition&gt;</p>
<p>We can include this template for each of our form fields using &lt;s:decorate&gt;.</p>
<p>&lt;h:form&gt;<br />
&lt;h:messages globalOnly=&#8221;true&#8221;/&gt;<br />
&lt;s:decorate template=&#8221;edit.xhtml&#8221;&gt;<br />
&lt;ui:define name=&#8221;label&#8221;&gt;Country:&lt;/ui:define&gt;<br />
&lt;h:inputText value=&#8221;#{location.country}&#8221; required=&#8221;true&#8221;/&gt;<br />
&lt;/s:decorate&gt;<br />
&lt;s:decorate template=&#8221;edit.xhtml&#8221;&gt;<br />
&lt;ui:define name=&#8221;label&#8221;&gt;Zip code:&lt;/ui:define&gt;<br />
&lt;h:inputText value=&#8221;#{location.zip}&#8221; required=&#8221;true&#8221;/&gt;<br />
&lt;/s:decorate&gt;<br />
&lt;h:commandButton/&gt;<br />
&lt;/h:form&gt;</p>
<p>Finally, we can use RichFaces Ajax to display validation messages as the user is navigating around the form:</p>
<p>&lt;h:form&gt;<br />
&lt;h:messages globalOnly=&#8221;true&#8221;/&gt;<br />
&lt;s:decorate id=&#8221;countryDecoration&#8221; template=&#8221;edit.xhtml&#8221;&gt;<br />
&lt;ui:define name=&#8221;label&#8221;&gt;Country:&lt;/ui:define&gt;<br />
&lt;h:inputText value=&#8221;#{location.country}&#8221; required=&#8221;true&#8221;&gt;<br />
&lt;a:support event=&#8221;onblur&#8221; reRender=&#8221;countryDecoration&#8221; bypassUpdates=&#8221;true&#8221;/&gt;<br />
&lt;/h:inputText&gt;<br />
&lt;/s:decorate&gt;<br />
&lt;s:decorate id=&#8221;zipDecoration&#8221; template=&#8221;edit.xhtml&#8221;&gt;<br />
&lt;ui:define name=&#8221;label&#8221;&gt;Zip code:&lt;/ui:define&gt;<br />
&lt;h:inputText value=&#8221;#{location.zip}&#8221; required=&#8221;true&#8221;&gt;<br />
&lt;a:support event=&#8221;onblur&#8221; reRender=&#8221;zipDecoration&#8221; bypassUpdates=&#8221;true&#8221;/&gt;<br />
&lt;/h:inputText&gt;<br />
&lt;/s:decorate&gt;<br />
&lt;h:commandButton/&gt;<br />
&lt;/h:form&gt;</p>
<p>It&#8217;s better style to define explicit ids for important controls on the page, especially if you want to<br />
do automated testing for the UI, using some toolkit like Selenium. If you don&#8217;t provide explicit ids,<br />
JSF will generate them, but the generated values will change if you change anything on the page.</p>
<p>&lt;h:form id=&#8221;form&#8221;&gt;<br />
&lt;h:messages globalOnly=&#8221;true&#8221;/&gt;<br />
&lt;s:decorate id=&#8221;countryDecoration&#8221; template=&#8221;edit.xhtml&#8221;&gt;<br />
&lt;ui:define name=&#8221;label&#8221;&gt;Country:&lt;/ui:define&gt;<br />
&lt;h:inputText id=&#8221;country&#8221; value=&#8221;#{location.country}&#8221; required=&#8221;true&#8221;&gt;<br />
&lt;a:support event=&#8221;onblur&#8221; reRender=&#8221;countryDecoration&#8221; bypassUpdates=&#8221;true&#8221;/&gt;<br />
&lt;/h:inputText&gt;<br />
&lt;/s:decorate&gt;<br />
&lt;s:decorate id=&#8221;zipDecoration&#8221; template=&#8221;edit.xhtml&#8221;&gt;<br />
&lt;ui:define name=&#8221;label&#8221;&gt;Zip code:&lt;/ui:define&gt;<br />
&lt;h:inputText id=&#8221;zip&#8221; value=&#8221;#{location.zip}&#8221; required=&#8221;true&#8221;&gt;<br />
&lt;a:support event=&#8221;onblur&#8221; reRender=&#8221;zipDecoration&#8221; bypassUpdates=&#8221;true&#8221;/&gt;<br />
&lt;/h:inputText&gt;<br />
&lt;/s:decorate&gt;<br />
&lt;h:commandButton/&gt;<br />
&lt;/h:form&gt;</p>
<p>And what if you want to specify a different message to be displayed when validation fails? You<br />
can use the Seam message bundle (and all it&#8217;s goodies like el expressions inside the message,<br />
and per-view message bundles) with the Hibernate Validator:</p>
<p>public class Location {<br />
private String name;<br />
private String zip;<br />
// Getters and setters for name<br />
@NotNull<br />
@Length(max=6)<br />
@ZipCode(message=&#8221;#{messages['location.zipCode.invalid']}&#8221;)<br />
public String getZip() { return zip; }<br />
public void setZip(String z) { zip = z; }<br />
}</p>
<p>location.zipCode.invalid = The zip code is not valid for #{location.name}</p>
<p>The Seam Application Framework: Seam makes it really easy to create applications by writing plain Java classes with<br />
annotations, which don&#8217;t need to extend any special interfaces or superclasses. But we can simplify some common programming<br />
tasks even further, by providing a set of pre-built components which can be re-used either by configuration in components.xml<br />
(for very simple cases) or extension. The Seam Application Framework can reduce the amount of code you need to write when<br />
doing basic database access in a web application, using either Hibernate or JPA. We should emphasize that the framework is<br />
extremely simple, just a handful of simple classes that are easy to understand and extend.</p>
<p>Introduction: The components provided by the Seam application framework may be used in one of two different approaches. The<br />
first way is to install and configure an instance of the component in components.xml, just like we have done with other kinds<br />
of built-in Seam components. For example, the following fragment from components.xml installs a component which can perform<br />
basic CRUD operations for a Person entity:</p>
<p>&lt;framework:entity-home name=&#8221;personHome&#8221;<br />
entity-class=&#8221;eg.Person&#8221;<br />
entity-manager=&#8221;#{personDatabase}&#8221;&gt;<br />
&lt;framework:id&gt;#{param.personId}&lt;/framework:id&gt;<br />
&lt;/framework:entity-home&gt;</p>
<p>If that looks a bit too much like &#8220;programming in XML&#8221; for your taste, you can use extension instead:</p>
<p>@Name(&#8220;personHome&#8221;)<br />
public class PersonHome extends EntityHome&lt;Person&gt; {<br />
@In EntityManager personDatabase;<br />
public EntityManager getEntityManager() {<br />
return personDatabase;<br />
}<br />
}</p>
<p>The second approach has one huge advantage: you can easily add extra functionality, and<br />
override the built-in functionality (the framework classes were carefully designed for extension and customization).</p>
<p>A second advantage is that your classes may be EJB stateful session beans, if you like. (They do not have to be, they can be<br />
plain JavaBean components if you prefer). If you are using JBoss AS, you&#8217;ll need 4.2.2.GA or later:</p>
<p>@Stateful<br />
@Name(&#8220;personHome&#8221;)<br />
public class PersonHome extends EntityHome&lt;Person&gt; implements LocalPersonHome {<br />
}</p>
<p>You can also make your classes stateless session beans. In this case you must use injection to<br />
provide the persistence context, even if it is called entityManager:</p>
<p>@Stateless<br />
@Name(&#8220;personHome&#8221;)<br />
public class PersonHome extends EntityHome&lt;Person&gt; implements LocalPersonHome {<br />
@In EntityManager entityManager;<br />
public EntityManager getPersistenceContext() {<br />
entityManager;<br />
}<br />
}</p>
<p>At this time, the Seam Application Framework provides four main built-in components:<br />
EntityHome and HibernateEntityHome for CRUD, along with EntityQuery and HibernateEntityQuery for queries.</p>
<p>The Home and Query components are written so that they can function with a scope of session, event or conversation. Which<br />
scope you use depends upon the state model you wish to use in your application.</p>
<p>The Seam Application Framework only works with Seam-managed persistence contexts. By<br />
default, the components will look for a persistence context named entityManager.</p>
<p>Home objects: A Home object provides persistence operations for a particular entity class. Suppose we have our<br />
trusty Person class:</p>
<p>@Entity<br />
public class Person {<br />
@Id private Long id;<br />
private String firstName;<br />
private String lastName;<br />
private Country nationality;<br />
//getters and setters&#8230;<br />
}</p>
<p>We can define a personHome component either via configuration:</p>
<p>&lt;framework:entity-home name=&#8221;personHome&#8221; entity-class=&#8221;eg.Person&#8221; /&gt;</p>
<p>Or via extension:</p>
<p>@Name(&#8220;personHome&#8221;)<br />
public class PersonHome extends EntityHome&lt;Person&gt; {}</p>
<p>A Home object provides the following operations: persist(), remove(), update() and getInstance(). Before you can call the<br />
remove(), or update() operations, you must first set the identifier of the object you are interested in, using the setId()<br />
method.</p>
<p>We can use a Home directly from a JSF page, for example:</p>
<p>&lt;h1&gt;Create Person&lt;/h1&gt;<br />
&lt;h:form&gt;<br />
&lt;div&gt;First name: &lt;h:inputText value=&#8221;#{personHome.instance.firstName}&#8221;/&gt;&lt;/div&gt;<br />
&lt;div&gt;Last name: &lt;h:inputText value=&#8221;#{personHome.instance.lastName}&#8221;/&gt;&lt;/div&gt;<br />
&lt;div&gt;<br />
&lt;h:commandButton value=&#8221;Create Person&#8221; action=&#8221;#{personHome.persist}&#8221;/&gt;<br />
&lt;/div&gt;<br />
&lt;/h:form&gt;</p>
<p>Usually, it is much nicer to be able to refer to the Person merely as person, so let&#8217;s make that possible by adding a line to<br />
components.xml:</p>
<p>&lt;factory name=&#8221;person&#8221; value=&#8221;#{personHome.instance}&#8221;/&gt;<br />
&lt;framework:entity-home name=&#8221;personHome&#8221; entity-class=&#8221;eg.Person&#8221; /&gt;</p>
<p>(If we are using configuration).</p>
<p>Or by adding a @Factory method to PersonHome:</p>
<p>@Name(&#8220;personHome&#8221;)<br />
public class PersonHome extends EntityHome&lt;Person&gt; {<br />
@Factory(&#8220;person&#8221;)<br />
public Person initPerson() { return getInstance(); }<br />
}</p>
<p>(If we are using extension).</p>
<p>This change simplifies our JSF page to the following:</p>
<p>&lt;h1&gt;Create Person&lt;/h1&gt;<br />
&lt;h:form&gt;<br />
&lt;div&gt;First name: &lt;h:inputText value=&#8221;#{person.firstName}&#8221;/&gt;&lt;/div&gt;<br />
&lt;div&gt;Last name: &lt;h:inputText value=&#8221;#{person.lastName}&#8221;/&gt;&lt;/div&gt;<br />
&lt;div&gt;<br />
&lt;h:commandButton value=&#8221;Create Person&#8221; action=&#8221;#{personHome.persist}&#8221;/&gt;<br />
&lt;/div&gt;<br />
&lt;/h:form&gt;</p>
<p>Well, that lets us create new Person entries. Yes, that is all the code that is required! Now, if we<br />
want to be able to display, update and delete pre-existing Person entries in the database, we<br />
need to be able to pass the entry identifier to the PersonHome. Page parameters are a great way to do that:</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/editPerson.jsp&#8221;&gt;<br />
&lt;param name=&#8221;personId&#8221; value=&#8221;#{personHome.id}&#8221;/&gt;<br />
&lt;/page&gt;<br />
&lt;/pages&gt;</p>
<p>Now we can add the extra operations to our JSF page:</p>
<p>&lt;h1&gt;<br />
&lt;h:outputText rendered=&#8221;#{!personHome.managed}&#8221; value=&#8221;Create Person&#8221;/&gt;<br />
&lt;h:outputText rendered=&#8221;#{personHome.managed}&#8221; value=&#8221;Edit Person&#8221;/&gt;<br />
&lt;/h1&gt;<br />
&lt;h:form&gt;<br />
&lt;div&gt;First name: &lt;h:inputText value=&#8221;#{person.firstName}&#8221;/&gt;&lt;/div&gt;<br />
&lt;div&gt;Last name: &lt;h:inputText value=&#8221;#{person.lastName}&#8221;/&gt;&lt;/div&gt;<br />
&lt;div&gt;<br />
&lt;h:commandButton value=&#8221;Create Person&#8221; action=&#8221;#{personHome.persist}&#8221;<br />
rendered=&#8221;#{!personHome.managed}&#8221;/&gt;<br />
&lt;h:commandButton value=&#8221;Update Person&#8221; action=&#8221;#{personHome.update}&#8221;<br />
rendered=&#8221;#{personHome.managed}&#8221;/&gt;<br />
&lt;h:commandButton value=&#8221;Delete Person&#8221; action=&#8221;#{personHome.remove}&#8221;<br />
rendered=&#8221;#{personHome.managed}&#8221;/&gt;<br />
&lt;/div&gt;<br />
&lt;/h:form&gt;</p>
<p>When we link to the page with no request parameters, the page will be displayed as a &#8220;Create<br />
Person&#8221; page. When we provide a value for the personId request parameter, it will be an &#8220;Edit<br />
Person&#8221; page.<br />
Suppose we need to create Person entries with their nationality initialized. We can do that easily,<br />
via configuration:</p>
<p>&lt;factory name=&#8221;person&#8221;<br />
value=&#8221;#{personHome.instance}&#8221;/&gt;<br />
&lt;framework:entity-home name=&#8221;personHome&#8221;<br />
entity-class=&#8221;eg.Person&#8221;<br />
new-instance=&#8221;#{newPerson}&#8221;/&gt;<br />
&lt;component name=&#8221;newPerson&#8221;<br />
class=&#8221;eg.Person&#8221;&gt;<br />
&lt;property name=&#8221;nationality&#8221;&gt;#{country}&lt;/property&gt;<br />
&lt;/component&gt;</p>
<p>Or by extension:</p>
<p>@Name(&#8220;personHome&#8221;)<br />
public class PersonHome extends EntityHome&lt;Person&gt; {<br />
@In Country country;<br />
@Factory(&#8220;person&#8221;)<br />
public Person initPerson() { return getInstance(); }<br />
protected Person createInstance() {<br />
return new Person(country);<br />
}<br />
}</p>
<p>Of course, the Country could be an object managed by another Home object, for example, CountryHome.<br />
To add more sophisticated operations (association management, etc), we can just add methods to PersonHome.</p>
<p>@Name(&#8220;personHome&#8221;)<br />
public class PersonHome extends EntityHome&lt;Person&gt; {<br />
@In Country country;<br />
@Factory(&#8220;person&#8221;)<br />
public Person initPerson() { return getInstance(); }<br />
protected Person createInstance() {<br />
return new Person(country);<br />
}<br />
public void migrate()<br />
{<br />
getInstance().setCountry(country);<br />
update();<br />
}<br />
}</p>
<p>The Home object raises an org.jboss.seam.afterTransactionSuccess event when a transaction succeeds (a call to persist(),<br />
update() or remove() succeeds). By observing this event we can refresh our queries when the underlying entities are changed.<br />
If we only want to refresh certain queries when a particular entity is persited, updated or removed we can observe<br />
the org.jboss.seam.afterTransactionSuccess.&lt;name&gt; event (where &lt;name&gt; is the name of the entity).</p>
<p>The Home object automatically displays faces messages when an operation is successful. To customize these messages we can,<br />
again, use configuration:</p>
<p>&lt;factory name=&#8221;person&#8221;<br />
value=&#8221;#{personHome.instance}&#8221;/&gt;<br />
&lt;framework:entity-home name=&#8221;personHome&#8221;<br />
entity-class=&#8221;eg.Person&#8221;<br />
new-instance=&#8221;#{newPerson}&#8221;&gt;<br />
&lt;framework:created-message&gt;New person #{person.firstName} #{person.lastName} created&lt;/<br />
framework:created-message&gt;<br />
&lt;framework:deleted-message&gt;Person #{person.firstName} #{person.lastName} deleted&lt;/<br />
framework:deleted-message&gt;<br />
&lt;framework:updated-message&gt;Person #{person.firstName} #{person.lastName} updated&lt;/<br />
framework:updated-message&gt;<br />
&lt;/framework:entity-home&gt;<br />
&lt;component name=&#8221;newPerson&#8221;<br />
class=&#8221;eg.Person&#8221;&gt;<br />
&lt;property name=&#8221;nationality&#8221;&gt;#{country}&lt;/property&gt;<br />
&lt;/component&gt;</p>
<p>Or extension:<br />
@Name(&#8220;personHome&#8221;)<br />
public class PersonHome extends EntityHome&lt;Person&gt; {<br />
@In Country country;<br />
@Factory(&#8220;person&#8221;)<br />
public Person initPerson() { return getInstance(); }<br />
protected Person createInstance() {<br />
return new Person(country);<br />
}<br />
protected String getCreatedMessage() { return &#8220;New person #{person.firstName}<br />
#{person.lastName} created&#8221;; }<br />
protected String getUpdatedMessage() { return &#8220;Person #{person.firstName}<br />
#{person.lastName} updated&#8221;; }<br />
protected String getDeletedMessage() { return &#8220;Person #{person.firstName}<br />
#{person.lastName} deleted&#8221;; }<br />
}</p>
<p>But the best way to specify the messages is to put them in a resource bundle known to Seam (the bundle named messages, by<br />
default).</p>
<p>Person_created=New person #{person.firstName} #{person.lastName} created<br />
Person_deleted=Person #{person.firstName} #{person.lastName} deleted<br />
Person_updated=Person #{person.firstName} #{person.lastName} updated</p>
<p>This enables internationalization, and keeps your code and configuration clean of presentation concerns.<br />
The final step is to add validation functionality to the page, using &lt;s:validateAll&gt; and &lt;s:decorate&gt;.</p>
<p>Query objects: If we need a list of all Person instance in the database, we can use a Query object. For example:</p>
<p>&lt;framework:entity-query name=&#8221;people&#8221; ejbql=&#8221;select p from Person p&#8221;/&gt;</p>
<p>We can use it from a JSF page:</p>
<p>&lt;h1&gt;List of people&lt;/h1&gt;<br />
&lt;h:dataTable value=&#8221;#{people.resultList}&#8221; var=&#8221;person&#8221;&gt;<br />
&lt;h:column&gt;<br />
&lt;s:link view=&#8221;/editPerson.jsp&#8221; value=&#8221;#{person.firstName} #{person.lastName}&#8221;&gt;<br />
&lt;f:param name=&#8221;personId&#8221; value=&#8221;#{person.id}&#8221;/&gt;<br />
&lt;/s:link&gt;<br />
&lt;/h:column&gt;<br />
&lt;/h:dataTable&gt;</p>
<p>We probably need to support pagination:</p>
<p>&lt;framework:entity-query name=&#8221;people&#8221; ejbql=&#8221;select p from Person p&#8221; order=&#8221;lastName&#8221; max-results=&#8221;20&#8243;/&gt;</p>
<p>We&#8217;ll use a page parameter to determine the page to display:</p>
<p>&lt;pages&gt;<br />
&lt;page view-id=&#8221;/searchPerson.jsp&#8221;&gt;<br />
&lt;param name=&#8221;firstResult&#8221; value=&#8221;#{people.firstResult}&#8221;/&gt;<br />
&lt;/page&gt;<br />
&lt;/pages&gt;</p>
<p>The JSF code for a pagination control is a bit verbose, but manageable:</p>
<p>&lt;h1&gt;Search for people&lt;/h1&gt;<br />
&lt;h:dataTable value=&#8221;#{people.resultList}&#8221; var=&#8221;person&#8221;&gt;<br />
&lt;h:column&gt;<br />
&lt;s:link view=&#8221;/editPerson.jsp&#8221; value=&#8221;#{person.firstName} #{person.lastName}&#8221;&gt;<br />
&lt;f:param name=&#8221;personId&#8221; value=&#8221;#{person.id}&#8221;/&gt;<br />
&lt;/s:link&gt;<br />
&lt;/h:column&gt;<br />
&lt;/h:dataTable&gt;<br />
&lt;s:link view=&#8221;/search.xhtml&#8221; rendered=&#8221;#{people.previousExists}&#8221; value=&#8221;First Page&#8221;&gt;<br />
&lt;f:param name=&#8221;firstResult&#8221; value=&#8221;0&#8243;/&gt;<br />
&lt;/s:link&gt;<br />
&lt;s:link view=&#8221;/search.xhtml&#8221; rendered=&#8221;#{people.previousExists}&#8221; value=&#8221;Previous Page&#8221;&gt;<br />
&lt;f:param name=&#8221;firstResult&#8221; value=&#8221;#{people.previousFirstResult}&#8221;/&gt;<br />
&lt;/s:link&gt;<br />
&lt;s:link view=&#8221;/search.xhtml&#8221; rendered=&#8221;#{people.nextExists}&#8221; value=&#8221;Next Page&#8221;&gt;<br />
&lt;f:param name=&#8221;firstResult&#8221; value=&#8221;#{people.nextFirstResult}&#8221;/&gt;<br />
&lt;/s:link&gt;<br />
&lt;s:link view=&#8221;/search.xhtml&#8221; rendered=&#8221;#{people.nextExists}&#8221; value=&#8221;Last Page&#8221;&gt;<br />
&lt;f:param name=&#8221;firstResult&#8221; value=&#8221;#{people.lastFirstResult}&#8221;/&gt;<br />
&lt;/s:link&gt;</p>
<p>Real search screens let the user enter a bunch of optional search criteria to narrow the list of<br />
results returned. The Query object lets you specify optional &#8220;restrictions&#8221; to support this important usecase:</p>
<p>&lt;component name=&#8221;examplePerson&#8221;/&gt;<br />
&lt;framework:entity-query name=&#8221;people&#8221;<br />
ejbql=&#8221;select p from Person p&#8221;<br />
order=&#8221;lastName&#8221;<br />
max-results=&#8221;20&#8243;&gt;<br />
&lt;framework:restrictions&gt;<br />
&lt;value&gt;lower(firstName) like lower( concat(#{examplePerson.firstName},&#8217;%') )&lt;/value&gt;<br />
&lt;value&gt;lower(lastName) like lower( concat(#{examplePerson.lastName},&#8217;%') )&lt;/value&gt;<br />
&lt;/framework:restrictions&gt;<br />
&lt;/framework:entity-query&gt;</p>
<p>Notice the use of an &#8220;example&#8221; object.</p>
<p>&lt;h1&gt;Search for people&lt;/h1&gt;<br />
&lt;h:form&gt;<br />
&lt;div&gt;First name: &lt;h:inputText value=&#8221;#{examplePerson.firstName}&#8221;/&gt;&lt;/div&gt;<br />
&lt;div&gt;Last name: &lt;h:inputText value=&#8221;#{examplePerson.lastName}&#8221;/&gt;&lt;/div&gt;<br />
&lt;div&gt;&lt;h:commandButton value=&#8221;Search&#8221; action=&#8221;/search.jsp&#8221;/&gt;&lt;/div&gt;<br />
&lt;/h:form&gt;<br />
&lt;h:dataTable value=&#8221;#{people.resultList}&#8221; var=&#8221;person&#8221;&gt;<br />
&lt;h:column&gt;<br />
&lt;s:link view=&#8221;/editPerson.jsp&#8221; value=&#8221;#{person.firstName} #{person.lastName}&#8221;&gt;<br />
&lt;f:param name=&#8221;personId&#8221; value=&#8221;#{person.id}&#8221;/&gt;<br />
&lt;/s:link&gt;<br />
&lt;/h:column&gt;<br />
&lt;/h:dataTable&gt;</p>
<p>To refresh the query when the underlying entities change we observe the org.jboss.seam.afterTransactionSuccess event:</p>
<p>&lt;event type=&#8221;org.jboss.seam.afterTransactionSuccess&#8221;&gt;<br />
&lt;action execute=&#8221;#{people.refresh}&#8221; /&gt;<br />
&lt;/event&gt;</p>
<p>Or, to just refresh the query when the person entity is persisted, updated or removed through PersonHome:</p>
<p>&lt;event type=&#8221;org.jboss.seam.afterTransactionSuccess.Person&#8221;&gt;<br />
&lt;action execute=&#8221;#{people.refresh}&#8221; /&gt;<br />
&lt;/event&gt;</p>
<p>Unfortunately Query objects don&#8217;t work well with join fetch queries &#8211; the use of pagination with these queries is not<br />
recomended, and you&#8217;ll have to implement your own method of calculating the total number of results (by overriding<br />
getCountEjbql(). The examples in this section have all shown reuse by configuration. However, reuse by extension<br />
is equally possible for Query objects.</p>
<p>Controller objects: A totally optional part of the Seam Application Framework is the classController and its subclasses<br />
EntityController, HibernateEntityController and BusinessProcessController. These classes provide nothing more than some<br />
convenience methods for access to commonly used built-in components and methods of built-in components.<br />
They help save a few keystrokes (characters can add up!) and provide a great launchpad for new users to explore the rich<br />
functionality built in to Seam.</p>
<p>For example, here is what RegisterAction from the Seam registration example would look like:</p>
<p>@Stateless<br />
@Name(&#8220;register&#8221;)<br />
public class RegisterAction extends EntityController implements Register<br />
{<br />
@In private User user;<br />
public String register()<br />
{<br />
List existing = createQuery(&#8220;select u.username from User u where u.username=:username&#8221;)<br />
.setParameter(&#8220;username&#8221;, user.getUsername())<br />
.getResultList();<br />
if ( existing.size()==0 )<br />
{<br />
persist(user);<br />
info(&#8220;Registered new user #{user.username}&#8221;);<br />
return &#8220;/registered.jspx&#8221;;<br />
}<br />
else<br />
{<br />
addFacesMessage(&#8220;User #{user.username} already exists&#8221;);<br />
return null;<br />
}<br />
}<br />
}<br />
As you can see, its not an earthshattering improvement&#8230;</p>
<p>Seam and JBoss Rules: Seam makes it easy to call JBoss Rules (Drools) rulebases from Seam components or jBPM<br />
process definitions.</p>
<p>Security: The Seam Security API is an optional Seam feature that provides authentication and authorization<br />
features for securing both domain and page resources within your Seam project.<br />
Overview:<br />
Seam Security provides two different modes of operation:<br />
• simplified mode &#8211; this mode supports authentication services and simple role-based security checks.<br />
• advanced mode &#8211; this mode supports all the same features as the simplified mode, plus it offers rule-based security checks<br />
using JBoss Rules.</p>
<p>Which mode is right for my application? That all depends on the requirements of your application. If you have minimal<br />
security requirements, for example if you only wish to restrict certain pages and actions to users who are logged in, or who<br />
belong to a certain role, then the simplified mode will probably be sufficient. The advantages of this is a more simplified<br />
configuration, significantly less libraries to include, and a smaller memory footprint.<br />
If on the other hand, your application requires security checks based on contextual state or<br />
complex business rules, then you will require the features provided by the advanced mode.</p>
<p>Requirements: If using the advanced mode features of Seam Security, the following jar files are required to be configured as<br />
modules in application.xml. If you are using Seam Security in simplified mode, these are not required:</p>
<p>• drools-compiler.jar<br />
• drools-core.jar<br />
• janino.jar<br />
• antlr-runtime.jar<br />
• mvel14.jar</p>
<p>For web-based security, jboss-seam-ui.jar must also be included in the application&#8217;s war file.</p>
<p>Disabling Security: In some situations it may be necessary to disable Seam Security, for example during unit tests.<br />
This can be done by calling the static method Identity.setSecurityEnabled(false) to disable security checks. Doing this<br />
prevents any security checks being performed for the following:<br />
• Entity Security<br />
• Hibernate Security Interceptor<br />
• Seam Security Interceptor<br />
• Page restrictions</p>
<p>Authentication: The authentication features provided by Seam Security are built upon JAAS (Java Authentication and<br />
Authorization Service), and as such provide a robust and highly configurable API for handling user authentication. However,<br />
for less complex authentication requirements Seam offers a much more simplified method of authentication that hides the<br />
complexity of JAAS.</p>
<p>Configuration: The simplified authentication method uses a built-in JAAS login module, SeamLoginModule, which delegates<br />
authentication to one of your own Seam components. This login module is already configured inside Seam as part of a default<br />
application policy and as such does not require any additional configuration files. It allows you to write an authentication<br />
method using the entity classes that are provided by your own application. Configuring this simplified form of authentication<br />
requires the identity component to be configured in components.xml:</p>
<p>&lt;components xmlns=&#8221;http://jboss.com/products/seam/components&#8221;<br />
xmlns:core=&#8221;http://jboss.com/products/seam/core&#8221;<br />
xmlns:security=&#8221;http://jboss.com/products/seam/security&#8221;<br />
xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221;<br />
xsi:schemaLocation=<br />
&#8220;http://jboss.com/products/seam/components http://jboss.com/products/seam/<br />
components-2.1.xsd<br />
http://jboss.com/products/seam/security http://jboss.com/products/seam/security-<br />
2.1.xsd&#8221;&gt;<br />
&lt;security:identity authenticate-method=&#8221;#{authenticator.authenticate}&#8221;/&gt;<br />
&lt;/components&gt;</p>
<p>If you wish to use the advanced security features such as rule-based permission checks, all you need to do is include the<br />
Drools (JBoss Rules) jars in your classpath, and add some additional configuration, described later.<br />
The EL expression #{authenticator.authenticate} is a method binding indicating that the<br />
authenticate method of the authenticator component will be used to authenticate the user.</p>
<p>Writing an authentication method: The authenticate-method property specified for identity in components.xml specifies<br />
which method will be used by SeamLoginModule to authenticate users. This method takes no parameters, and is expected to<br />
return a boolean indicating whether authentication is successful or not. The user&#8217;s username and password can be obtained<br />
from Identity.instance().getUsername() and Identity.instance().getPassword(), respectively. Any roles that the user is a<br />
member of should be assigned using Identity.instance().addRole(). Here&#8217;s a complete example of an authentication method<br />
inside a JavaBean component:</p>
<p>@Name(&#8220;authenticator&#8221;)<br />
public class Authenticator {<br />
@In EntityManager entityManager;<br />
public boolean authenticate() {<br />
try<br />
{<br />
User user = (User) entityManager.createQuery(<br />
&#8220;from User where username = :username and password = :password&#8221;)<br />
.setParameter(&#8220;username&#8221;, Identity.instance().getUsername())<br />
.setParameter(&#8220;password&#8221;, Identity.instance().getPassword())<br />
.getSingleResult();<br />
if (user.getRoles() != null)<br />
{<br />
for (UserRole mr : user.getRoles())<br />
Identity.instance().addRole(mr.getName());<br />
}<br />
return true;<br />
}<br />
catch (NoResultException ex)<br />
{<br />
return false;<br />
}<br />
}<br />
}</p>
<p>In the above example, both User and UserRole are application-specific entity beans. The roles parameter is populated with<br />
the roles that the user is a member of, which should be added to the Set as literal string values, e.g. &#8220;admin&#8221;, &#8220;user&#8221;. In<br />
this case, if the user record is not found and a NoResultException thrown, the authentication method returns false to<br />
indicate the authentication failed.</p>
<p>Identity.addRole(): The Identity.addRole() method behaves differently depending on whether the current session is<br />
authenticated or not. If the session is not authenticated, then addRole() should only be called during the authentication<br />
process. When called here, the role name is placed into a temporary list of pre-authenticated roles. Once authentication is<br />
successful, the pre-authenticated roles then become &#8220;real&#8221; roles, and calling Identity.hasRole() for those roles will then<br />
return true. The following sequence diagram represents the list of pre-authenticated roles as a first class object to<br />
show more clearly how it fits in to the authentication process.</p>
<p>Special Considerations: When writing an authenticator method, it is important that it is kept minimal and free from any<br />
side-effects. This is because there is no guarantee as to how many times the authenticator method will be called by the<br />
security API, and as such it may be invoked multiple times during a single request. Because of this, any special code that<br />
should execute upon a successful or failed authentication should be written by implementing an event observer. See the<br />
section on Security Events for more information about which events are raised by Seam Security.</p>
<p>To give an example, let&#8217;s say that upon a successful login that some user statistics must be updated. We would do this by<br />
writing an event observer for the org.jboss.seam.security.loginSuccessful event, like this:</p>
<p>@In UserStats userStats;<br />
@Observer(&#8220;org.jboss.seam.security.loginSuccessful&#8221;)<br />
public void updateUserStats()<br />
{<br />
userStats.setLastLoginDate(new Date());<br />
userStats.incrementLoginCount();<br />
}</p>
<p>Writing a login form: The Identity component provides both username and password properties, catering for the most<br />
common authentication scenario. These properties can be bound directly to the username and password fields on a login form.<br />
Once these properties are set, calling the identity.login() method will authenticate the user using the provided credentials.<br />
Here&#8217;s an example of a simple login form:</p>
<p>&lt;div&gt;<br />
&lt;h:outputLabel for=&#8221;name&#8221; value=&#8221;Username&#8221;/&gt;<br />
&lt;h:inputText id=&#8221;name&#8221; value=&#8221;#{identity.username}&#8221;/&gt;<br />
&lt;/div&gt;<br />
&lt;div&gt;<br />
&lt;h:outputLabel for=&#8221;password&#8221; value=&#8221;Password&#8221;/&gt;<br />
&lt;h:inputSecret id=&#8221;password&#8221; value=&#8221;#{identity.password}&#8221;/&gt;<br />
&lt;/div&gt;<br />
&lt;div&gt;<br />
&lt;h:commandButton value=&#8221;Login&#8221; action=&#8221;#{identity.login}&#8221;/&gt;<br />
&lt;/div&gt;</p>
<p>Similarly, logging out the user is done by calling #{identity.logout}. Calling this action will<br />
clear the security state of the currently authenticated user.</p>
<p>Handling Security Exceptions: To prevent users from receiving the default error page in response to a security error, it&#8217;s<br />
recommended that pages.xml is configured to redirect security errors to a more &#8220;pretty&#8221; page. The two main types of<br />
exceptions thrown by the security API are:</p>
<p>• NotLoggedInException &#8211; This exception is thrown if the user attempts to access a restricted<br />
action or page when they are not logged in.</p>
<p>• AuthorizationException &#8211; This exception is only thrown if the user is already logged in, and<br />
they have attempted to access a restricted action or page for which they do not have the necessary privileges.</p>
<p>In the case of a NotLoggedInException, it is recommended that the user is redirected to either a login or registration page<br />
so that they can log in. For an AuthorizationException, it may be useful to redirect the user to an error page. Here&#8217;s an<br />
example of a pages.xml file that redirects both of these security exceptions:</p>
<p>&lt;pages&gt;<br />
&#8230;<br />
&lt;exception&gt;<br />
&lt;redirect view-id=&#8221;/login.xhtml&#8221;&gt;<br />
&lt;message&gt;You must be logged in to perform this action&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;</p>
<p>&lt;exception&gt;<br />
&lt;end-conversation/&gt;<br />
&lt;redirect view-id=&#8221;/security_error.xhtml&#8221;&gt;<br />
&lt;message&gt;You do not have the necessary security privileges to perform this action.&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;<br />
&lt;/pages&gt;</p>
<p>Most web applications require even more sophisticated handling of login redirection, so Seam<br />
includes some special functionality for handling this problem.</p>
<p>Login Redirection: You can ask Seam to redirect the user to a login screen when an unauthenticated user tries to<br />
access a particular view (or wildcarded view id) as follows:</p>
<p>&lt;pages login-view-id=&#8221;/login.xhtml&#8221;&gt;<br />
&lt;page view-id=&#8221;/members/*&#8221; login-required=&#8221;true&#8221;/&gt;<br />
&#8230;<br />
&lt;/pages&gt;</p>
<p>(This is less of a blunt instrument than the exception handler shown above, but should probably<br />
be used in conjunction with it).</p>
<p>After the user logs in, we want to automatically send them back where they came from, so they can retry the action that<br />
required logging in. If you add the following event listeners to components.xml, attempts to access a restricted view while<br />
not logged in will be remembered, so that upon the user successfully logging in they will be redirected to the originally<br />
requested view, with any page parameters that existed in the original request.</p>
<p>&lt;event type=&#8221;org.jboss.seam.security.notLoggedIn&#8221;&gt;<br />
&lt;action execute=&#8221;#{redirect.captureCurrentView}&#8221;/&gt;<br />
&lt;/event&gt;<br />
&lt;event type=&#8221;org.jboss.seam.security.postAuthenticate&#8221;&gt;<br />
&lt;action execute=&#8221;#{redirect.returnToCapturedView}&#8221;/&gt;<br />
&lt;/event&gt;</p>
<p>Note that login redirection is implemented as a conversation-scoped mechanism, so don&#8217;t end the conversation in your<br />
authenticate() method.</p>
<p>HTTP Authentication: Although not recommended for use unless absolutely necessary, Seam provides means for authenticating<br />
using either HTTP Basic or HTTP Digest (RFC 2617) methods. To use either form of authentication, the authentication-filter<br />
component must be enabled in components.xml:</p>
<p>&lt;web:authentication-filter url-pattern=&#8221;*.seam&#8221; auth-type=&#8221;basic&#8221;/&gt;</p>
<p>To enable the filter for basic authentication, set auth-type to basic, or for digest authentication,<br />
set it to digest. If using digest authentication, the key and realm must also be set:</p>
<p>&lt;web:authentication-filter url-pattern=&#8221;*.seam&#8221; auth-type=&#8221;digest&#8221; key=&#8221;AA3JK34aSDlkj&#8221; realm=&#8221;My App&#8221;/&gt;</p>
<p>The key can be any String value. The realm is the name of the authentication realm that is presented to the user when they<br />
authenticate.</p>
<p>Writing a Digest Authenticator: If using digest authentication, your authenticator class should extend the abstract class<br />
org.jboss.seam.security.digest.DigestAuthenticator, and use the validatePassword()<br />
method to validate the user&#8217;s plain text password against the digest request. Here is an example:</p>
<p>public boolean authenticate()<br />
{<br />
try<br />
{<br />
User user = (User) entityManager.createQuery(<br />
&#8220;from User where username = :username&#8221;)<br />
.setParameter(&#8220;username&#8221;, identity.getUsername())<br />
.getSingleResult();<br />
return validatePassword(user.getPassword());<br />
}<br />
catch (NoResultException ex)<br />
{<br />
return false;<br />
}<br />
}</p>
<p>Advanced Authentication Features:<br />
This section explores some of the advanced features provided by the security API for addressing more complex security<br />
requirements.</p>
<p>Using your container&#8217;s JAAS configuration: If you would rather not use the simplified JAAS configuration provided by the Seam<br />
Security API, you may instead delegate to the default system JAAS configuration by providing a jaas-configname<br />
property in components.xml. For example, if you are using JBoss AS and wish to use the other policy (which uses the<br />
UsersRolesLoginModule login module provided by JBoss AS), then the entry in components.xml would look like this:</p>
<p>&lt;security:identity jaas-config-name=&#8221;other&#8221;/&gt;</p>
<p>Please keep in mind that doing this does not mean that your user will be authenticated in whichever container your Seam<br />
application is deployed in. It merely instructs Seam Security to authenticate itself using the configured JAAS security<br />
policy.</p>
<p>Error Messages: The security API produces a number of default faces messages for various security-related events.<br />
The following table lists the message keys that can be used to override these messages by specifying them in a<br />
message.properties resource file. To suppress the message, just put the key with an empty value in the resource file.</p>
<p>Security Message Keys:</p>
<p>Message Key                                              Description<br />
&#8212;&#8212;&#8212;&#8212;-                                          &#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
org.jboss.seam.loginSuccessful                This message is produced when a user successfully logs in via the security API.</p>
<p>org.jboss.seam.loginFailed                    This message is produced when the login process fails,either because the user<br />
provided an incorrect username or password, or because authentication failed in<br />
some other way.</p>
<p>org.jboss.seam.NotLoggedIn                    This message is produced when a user attempts to perform an action or access a<br />
page that requires a security check, and the user is not currently<br />
authenticated.</p>
<p>org.jboss.seam.AlreadyLoggedIn                This message is produced when a user that is already authenticated attempts to<br />
log in again.</p>
<p>Authorization:</p>
<p>SSL Security:<br />
Seam includes basic support for serving sensitive pages via the HTTPS protocol. This is easily configured by specifying a<br />
scheme for the page in pages.xml. The following example shows how the view /login.xhtml is configured to use HTTPS:</p>
<p>&lt;page view-id=&#8221;/login.xhtml&#8221; scheme=&#8221;https&#8221;/&gt;</p>
<p>This configuration is automatically extended to both s:link and s:button JSF controls, which (when specifying the view) will<br />
also render the link using the correct protocol. Based on the previous example, the following link will use the HTTPS<br />
protocol because /login.xhtml is configured to use it:</p>
<p>&lt;s:link view=&#8221;/login.xhtml&#8221; value=&#8221;Login&#8221;/&gt;</p>
<p>Browsing directly to a view when using the incorrect protocol will cause a redirect to the same<br />
view using the correct protocol. For example, browsing to a page that has scheme=&#8221;https&#8221; using<br />
HTTP will cause a redirect to the same page using HTTPS.</p>
<p>It is also possible to configure a default scheme for all pages. This is useful if you wish to use HTTPS for a only few<br />
pages. If no default scheme is specified then the normal behavior is to continue use the current scheme. So once the user<br />
accessed a page that required HTTPS, then HTTPS would continue to be used after the user navigated away to other non-HTTPS<br />
pages. (While this is good for security, it is not so great for performance!). To define HTTP as the default scheme, add<br />
this line to pages.xml:</p>
<p>&lt;page view-id=&#8221;*&#8221; scheme=&#8221;http&#8221; /&gt;</p>
<p>Of course, if none of the pages in your application use HTTPS then it is not required to specify a default scheme.</p>
<p>You may configure Seam to automatically invalidate the current HTTP session each time the<br />
scheme changes. Just add this line to components.xml:</p>
<p>&lt;core:servlet-session invalidate-on-scheme-change=&#8221;true&#8221;/&gt;</p>
<p>This option helps make your system less vulnerable to sniffing of the session id or leakage of<br />
sensitive data from pages using HTTPS to other pages using HTTP.</p>
<p>CAPTCHA: Though strictly not part of the security API, Seam provides a built-in CAPTCHA (Completely<br />
Automated Public Turing test to tell Computers and Humans Apart) algorithm to prevent<br />
automated processes from interacting with your application.</p>
<p>Configuring the CAPTCHA Servlet: To get up and running, it is necessary to configure the Seam Resource Servlet, which will<br />
provide the Captcha challenge images to your pages. This requires the following entry in web.xml:</p>
<p>&lt;servlet&gt;<br />
&lt;servlet-name&gt;Seam Resource Servlet&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;org.jboss.seam.servlet.SeamResourceServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;Seam Resource Servlet&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/seam/resource/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;</p>
<p>Adding a CAPTCHA to a form: Adding a CAPTCHA challenge to a form is extremely easy. Here&#8217;s an example:</p>
<p>&lt;h:graphicImage value=&#8221;/seam/resource/captcha&#8221;/&gt;<br />
&lt;h:inputText id=&#8221;verifyCaptcha&#8221; value=&#8221;#{captcha.response}&#8221; required=&#8221;true&#8221;&gt;<br />
&lt;s:validate /&gt;<br />
&lt;/h:inputText&gt;<br />
&lt;h:message for=&#8221;verifyCaptcha&#8221;/&gt;</p>
<p>That&#8217;s all there is to it. The graphicImage control displays the CAPTCHA challenge, and the inputText receives the user&#8217;s<br />
response. The response is automatically validated against the CAPTCHA when the form is submitted.</p>
<p>Customising the CAPTCHA algorithm:<br />
You may customize the CAPTCHA algorithm by overriding the built-in component:</p>
<p>@Name(&#8220;org.jboss.seam.captcha&#8221;)<br />
@Scope(SESSION)<br />
public class HitchhikersCaptcha extends Captcha<br />
{<br />
@Override @Create<br />
public void init()<br />
{<br />
setChallenge(&#8220;What is the answer to life, the universe and everything?&#8221;);<br />
setCorrectResponse(&#8220;42&#8243;);<br />
}<br />
@Override<br />
public BufferedImage renderChallenge()<br />
{<br />
BufferedImage img = super.renderChallenge();<br />
img.getGraphics().drawOval(5, 3, 60, 14); //add an obscuring decoration<br />
return img;<br />
}<br />
}</p>
<p>Security Events:<br />
Event Key                                                Description<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;                                   &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
org.jboss.seam.security.loginSuccessful            Raised when a login attempt issuccessful.</p>
<p>org.jboss.seam.security.loginFailed                Raised when a login attempt fails.</p>
<p>org.jboss.seam.security.alreadyLoggedIn            Raised when a user that is already authenticated attempts to log in<br />
again.<br />
org.jboss.seam.security.notLoggedIn                Raised when a security check fails when the user is not logged in.</p>
<p>org.jboss.seam.security.notAuthorized              Raised when a security check fails when the user is logged in however<br />
doesn&#8217;t have sufficient privileges.</p>
<p>org.jboss.seam.security.preAuthenticate            Raised just prior to user authentication.</p>
<p>org.jboss.seam.security.postAuthenticate           Raised just after user authentication.</p>
<p>org.jboss.seam.security.loggedOut                  Raised after the user has logged out.</p>
<p>org.jboss.seam.security.credentialsUpdated         Raised when the user&#8217;s credentials have been changed.</p>
<p>org.jboss.seam.security.rememberMe                 Raised when the Identity&#8217;s rememberMe property is changed.</p>
<p>Run As: Sometimes it may be necessary to perform certain operations with elevated privileges, such<br />
as creating a new user account as an unauthenticated user. Seam Security supports such a<br />
mechanism via the RunAsOperation class. This class allows either the Principal or Subject,<br />
or the user&#8217;s roles to be overridden for a single set of operations.<br />
The following code example demonstrates how RunAsOperation is used, by overriding its<br />
getRoles() method to specify a set of roles to masquerade as for the duration of the operation.<br />
The execute() method contains the code that will be executed with the elevated privileges.</p>
<p>new RunAsOperation() {<br />
@Override<br />
public String[] getRoles() {<br />
return new String[] { &#8220;admin&#8221; };<br />
}<br />
public void execute() {<br />
executePrivilegedOperation();<br />
}<br />
}.run();</p>
<p>In a similar way, the getPrincipal() or getSubject() methods can also be overriden to specify<br />
the Principal and Subject instances to use for the duration of the operation. Finally, the run()<br />
method is used to carry out the RunAsOperation.</p>
<p>Extending the Identity component: Sometimes it might be necessary to extend the Identity component if your application has<br />
special security requirements. For example, users might be required to authenticate using a Company or Department ID, along<br />
with their usual username and password. If permission-based security is required then RuleBasedIdentity should be extended,<br />
otherwise Identity should be extended.<br />
The following example shows an extended Identity component with an additional companyCode field. The install precendence of<br />
APPLICATION ensures that this extended Identity gets installed in preference to the built-in Identity.</p>
<p>@Name(&#8220;org.jboss.seam.security.identity&#8221;)<br />
@Scope(SESSION)<br />
@Install(precedence = APPLICATION)<br />
@BypassInterceptors<br />
@Startup<br />
public class CustomIdentity extends Identity<br />
{<br />
private static final LogProvider log = Logging.getLogProvider(CustomIdentity.class);<br />
private String companyCode;<br />
public String getCompanyCode()<br />
{</p>
<p>return companyCode;<br />
}<br />
public void setCompanyCode(String companyCode)<br />
{<br />
this.companyCode = companyCode;<br />
}<br />
@Override<br />
public String login()<br />
{<br />
log.info(&#8220;###### CUSTOM LOGIN CALLED ######&#8221;);<br />
return super.login();<br />
}<br />
}</p>
<p>Internationalization, localization and themes: Seam makes it easy to build internationalized applications. First, let&#8217;s walk<br />
through all the stages needed to internationalize and localize your app. Then we&#8217;ll take a look at the components Seam<br />
bundles.</p>
<p>Asynchronicity and messaging: Seam makes it very easy to perform work asynchronously from a web request. When most people<br />
think of asynchronicity in Java EE, they think of using JMS. This is certainly one way to approach the problem in Seam, and<br />
is the right way when you have strict and well-defined quality of service requirements. Seam makes it easy to send and<br />
recieve JMS messages using Seam components. But for many usecases, JMS is overkill. Seam layers a simple asynchronous method<br />
and event facility over your choice of dispatchers:</p>
<p>• java.util.concurrent.ScheduledThreadPoolExecutor (by default)<br />
• the EJB timer service (for EJB 3.0 environments)<br />
• Quartz</p>
<p>Asynchronicity: Asynchronous events and method calls have the same quality of service expectations as the underlying<br />
dispatcher mechanism. The default dispatcher, based upon a ScheduledThreadPoolExecutor performs efficiently but provides no<br />
support for persistent asynchronous tasks, and hence no guarantee that a task will ever actually be executed. If you&#8217;re<br />
working in an environment that supports EJB 3.0, and add the following line to components.xml:</p>
<p>&lt;async:timer-service-dispatcher/&gt;</p>
<p>then your asynchronous tasks will be processed by the container&#8217;s EJB timer service. If you&#8217;re not familiar with the Timer<br />
service, don&#8217;t worry, you don&#8217;t need to interact with it directly if you want to use asynchronous methods in Seam. The<br />
important thing to know is that any good EJB 3.0 implementation will have the option of using persistent timers, which gives<br />
some guarantee that the tasks will eventually be processed.<br />
Another alternative is to use the open source Quartz library to manage asynchronous method. You need to bundle the Quartz<br />
library JAR (found in the lib directory) in your EAR and declare it as a Java module in application.xml. In addition, you<br />
need to add the following line to components.xml to install the Quartz dispatcher.</p>
<p>&lt;async:quartz-dispatcher/&gt;</p>
<p>The Seam API for the default ScheduledThreadPoolExecutor, the EJB3 Timer, and the Quartz Scheduler are largely the same. They<br />
can just &#8220;plug and play&#8221; by adding a line to components.xml.</p>
<p>Asynchronous methods: In simplest form, an asynchronous call just lets a method call be processed asynchronously (in a<br />
different thread) from the caller. We usually use an asynchronous call when we want to return an immediate response to the<br />
client, and let some expensive work be processed in the background.<br />
This pattern works very well in applications which use AJAX, where the client can automatically poll the server for the<br />
result of the work.<br />
For EJB components, we annotate the local interface to specify that a method is processed asynchronously.</p>
<p>@Local<br />
public interface PaymentHandler<br />
{<br />
@Asynchronous<br />
public void processPayment(Payment payment);<br />
}</p>
<p>(For JavaBean components we can annotate the component implementation class if we like).</p>
<p>The use of asynchronicity is transparent to the bean class:</p>
<p>@Stateless<br />
@Name(&#8220;paymentHandler&#8221;)<br />
public class PaymentHandlerBean implements PaymentHandler<br />
{<br />
public void processPayment(Payment payment)<br />
{<br />
//do some work!<br />
}<br />
}</p>
<p>And also transparent to the client:</p>
<p>@Stateful<br />
@Name(&#8220;paymentAction&#8221;)<br />
public class CreatePaymentAction<br />
{<br />
@In(create=true) PaymentHandler paymentHandler;<br />
@In Bill bill;<br />
public String pay()<br />
{<br />
paymentHandler.processPayment( new Payment(bill) );<br />
return &#8220;success&#8221;;<br />
}<br />
}</p>
<p>The asynchronous method is processed in a completely new event context and does not have access to the session or<br />
conversation context state of the caller. However, the business process context is propagated. Asynchronous method calls may<br />
be scheduled for later execution using the @Duration, @Expiration and @IntervalDuration annotations.</p>
<p>@Local<br />
public interface PaymentHandler<br />
{<br />
@Asynchronous<br />
public void processScheduledPayment(Payment payment, @Expiration Date date);<br />
@Asynchronous<br />
public void processRecurringPayment(Payment payment,<br />
@Expiration Date date,<br />
@IntervalDuration Long interval)&#8217;<br />
}</p>
<p>@Stateful<br />
@Name(&#8220;paymentAction&#8221;)<br />
public class CreatePaymentAction<br />
{<br />
@In(create=true) PaymentHandler paymentHandler;<br />
@In Bill bill;<br />
public String schedulePayment()<br />
{<br />
paymentHandler.processScheduledPayment( new Payment(bill), bill.getDueDate());<br />
return &#8220;success&#8221;;<br />
}<br />
public String scheduleRecurringPayment()<br />
{<br />
paymentHandler.processRecurringPayment( new Payment(bill), bill.getDueDate(),ONE_MONTH);<br />
return &#8220;success&#8221;;<br />
}<br />
}</p>
<p>Both client and server may access the Timer object associated with the invocation. The Timer object shown below is the EJB3<br />
timer when you use the EJB3 dispatcher. For the default ScheduledThreadPoolExecutor, the returned object is Future from the<br />
JDK. For the Quartz dispatcher, it returns QuartzTriggerHandle.</p>
<p>@Local<br />
public interface PaymentHandler<br />
{<br />
@Asynchronous<br />
public Timer processScheduledPayment(Payment payment, @Expiration Date date);<br />
}</p>
<p>@Stateless<br />
@Name(&#8220;paymentHandler&#8221;)<br />
public class PaymentHandlerBean implements PaymentHandler<br />
{<br />
@In Timer timer;<br />
public Timer processScheduledPayment(Payment payment, @Expiration Date date)<br />
{<br />
//do some work!<br />
return timer; //note that return value is completely ignored<br />
}<br />
}</p>
<p>@Stateful<br />
@Name(&#8220;paymentAction&#8221;)<br />
public class CreatePaymentAction<br />
{<br />
@In(create=true) PaymentHandler paymentHandler;<br />
@In Bill bill;<br />
public String schedulePayment()<br />
{<br />
Timer timer = paymentHandler.processScheduledPayment( new Payment(bill),<br />
bill.getDueDate() );<br />
return &#8220;success&#8221;;<br />
}<br />
}</p>
<p>Asynchronous methods cannot return any other value to the caller.</p>
<p>Asynchronous methods with the Quartz Dispatcher: The Quartz dispatcher allows you to use the @Asynchronous, @Duration,<br />
@Expiration, and @IntervalDuration annotations as above. But it has some powerful additional features. The Quartz dispatcher<br />
supports three new annotations. The @FinalExpiration annotation specifies an end date for the recurring task.</p>
<p>// Defines the method in the &#8220;processor&#8221; component<br />
@Asynchronous<br />
public QuartzTriggerHandle schedulePayment(@Expiration Date when,<br />
@IntervalDuration Long interval,<br />
@FinalExpiration Date endDate,<br />
Payment payment)<br />
{<br />
// do the repeating or long running task until endDate<br />
}</p>
<p>&#8230; &#8230;</p>
<p>// Schedule the task in the business logic processing code<br />
// Starts now, repeats every hour, and ends on May 10th, 2010<br />
Calendar cal = Calendar.getInstance ();<br />
cal.set (2010, Calendar.MAY, 10);<br />
processor.schedulePayment(new Date(), 60*60*1000, cal.getTime(), payment);</p>
<p>Note that the method returns the QuartzTriggerHandle object, which you can use later to stop, pause, and resume the<br />
scheduler. The QuartzTriggerHandle object is serializable, so you can save it into the database if you need to keep it<br />
around for extended period of time.</p>
<p>QuartzTriggerHandle handle = processor.schedulePayment(payment.getPaymentDate(), payment.getPaymentCron(), payment);<br />
payment.setQuartzTriggerHandle( handle );<br />
// Save payment to DB<br />
// later &#8230;<br />
// Retrieve payment from DB<br />
// Cancel the remaining scheduled tasks<br />
payment.getQuartzTriggerHandle().cancel();</p>
<p>The @IntervalCron annotation supports Unix cron job syntax for task scheduling. For instance, the following asynchronous<br />
method runs at 2:10pm and at 2:44pm every Wednesday in the month of March.</p>
<p>// Define the method<br />
@Asynchronous<br />
public QuartzTriggerHandle schedulePayment(@Expiration Date when,<br />
@IntervalCron String cron,<br />
Payment payment)<br />
{<br />
// do the repeating or long running task<br />
}<br />
&#8230; &#8230;<br />
// Schedule the task in the business logic processing code<br />
QuartzTriggerHandle handle =<br />
processor.schedulePayment(new Date(), &#8220;0 10,44 14 ? 3 WED&#8221;, payment);</p>
<p>The @IntervalBusinessDay annotation supports invocation on the &#8220;nth Business Day&#8221; scenario.<br />
For instance, the following asynchronous method runs at 14:00 on the 2nd business day of each<br />
month. By default, it excludes all weekends and US federal holidays until 2010 from the business days.</p>
<p>// Define the method<br />
@Asynchronous<br />
public QuartzTriggerHandle schedulePayment(@Expiration Date when,<br />
@IntervalBusinessDay NthBusinessDay nth,<br />
Payment payment)<br />
{<br />
// do the repeating or long running task<br />
}<br />
&#8230; &#8230;<br />
// Schedule the task in the business logic processing code<br />
QuartzTriggerHandle handle =<br />
processor.schedulePayment(new Date(),<br />
new NthBusinessDay(2, &#8220;14:00&#8243;, WEEKLY), payment);</p>
<p>The NthBusinessDay object contains the configuration of the invocation trigger. You can specify<br />
more holidays (e.g., company holidays, non-US holidays etc.) via the additionalHolidays property.</p>
<p>public class NthBusinessDay implements Serializable<br />
{<br />
int n;<br />
String fireAtTime;<br />
List &lt;Date&gt; additionalHolidays;<br />
BusinessDayIntervalType interval;<br />
boolean excludeWeekends;<br />
boolean excludeUsFederalHolidays;<br />
public enum BusinessDayIntervalType { WEEKLY, MONTHLY, YEARLY }<br />
public NthBusinessDay ()<br />
{<br />
n = 1;<br />
fireAtTime = &#8220;12:00&#8243;;<br />
additionalHolidays = new ArrayList &lt;Date&gt; ();<br />
interval = BusinessDayIntervalType.WEEKLY;<br />
excludeWeekends = true;<br />
excludeUsFederalHolidays = true;<br />
}<br />
&#8230; &#8230;<br />
}</p>
<p>The @IntervalDuration, @IntervalCron, and @IntervalNthBusinessDay annotations are<br />
mutually exclusive. If they are used in the same method, a RuntimeException will be thrown.</p>
<p>Asynchronous events: Component-driven events may also be asynchronous. To raise an event for asynchronous processing, simply<br />
call the raiseAsynchronousEvent() method of the Events class. To schedule a timed event, call the raiseTimedEvent() method,<br />
passing a schedule object (for the default dispatcher or timer service dispatcher, use TimerSchedule). Components may<br />
observe asynchronous events in the usual way, but remember that only the business process context is propagated to the<br />
asynchronous thread.</p>
<p>Messaging in Seam:<br />
Seam makes it easy to send and receive JMS messages to and from Seam components.</p>
<p>Configuration: To configure Seam&#8217;s infrastructure for sending JMS messages, you need to tell Seam about any topics and<br />
queues you want to send messages to, and also tell Seam where to find the QueueConnectionFactory and/or<br />
TopicConnectionFactory. Seam defaults to using UIL2ConnectionFactory which is the usual connection factory for use with<br />
JBossMQ. If you are using some other JMS provider, you need to set one or both of<br />
queueConnection.queueConnectionFactoryJndiName and topicConnection.topicConnectionFactoryJndiName in seam.properties,<br />
web.xml or components.xml.<br />
You also need to list topics and queues in components.xml to install Seam managed TopicPublishers and QueueSenders:</p>
<p>&lt;jms:managed-topic-publisher name=&#8221;stockTickerPublisher&#8221; auto-create=&#8221;true&#8221; topic-jndi-name=&#8221;topic/stockTickerTopic&#8221;/&gt;<br />
&lt;jms:managed-queue-sender name=&#8221;paymentQueueSender&#8221; auto-create=&#8221;true&#8221; queue-jndi-name=&#8221;queue/paymentQueue&#8221;/&gt;</p>
<p>Sending messages:<br />
Now, you can inject a JMS TopicPublisher and TopicSession into any component:</p>
<p>@In<br />
private TopicPublisher stockTickerPublisher;<br />
@In<br />
private TopicSession topicSession;<br />
public void publish(StockPrice price) {<br />
try<br />
{<br />
stockTickerPublisher.publish( topicSession.createObjectMessage(price) );<br />
}<br />
catch (Exception ex)<br />
{<br />
throw new RuntimeException(ex);<br />
}<br />
}</p>
<p>Or, for working with a queue:</p>
<p>@In<br />
private QueueSender paymentQueueSender;<br />
@In<br />
private QueueSession queueSession;<br />
public void publish(Payment payment) {<br />
try<br />
{<br />
paymentQueueSender.send( queueSession.createObjectMessage(payment) );<br />
}<br />
catch (Exception ex)<br />
{<br />
throw new RuntimeException(ex);<br />
}<br />
}</p>
<p>Receiving messages using a message-driven bean: You can process messages using any EJB3 message driven bean. Message-driven<br />
beans may even be Seam components, in which case it is possible to inject other event and application scoped Seam components.</p>
<p>Receiving messages in the client: Seam Remoting lets you subscribe to a JMS topic from client-side JavaScript.<br />
This is described in the Remoting section.</p>
<p>Caching: A well designed Seam application will feature a rich, multi-layered caching strategy that impacts every layer of<br />
the application:</p>
<p>• The database, of course, has its own cache. This is super-important, but can&#8217;t scale like a cache in the application tier.<br />
• Your ORM solution (Hibernate, or some other JPA implementation) has a second-level cache of data from the database. This is<br />
a very powerful capability, but is often misused. In a clustered environment, keeping the data in the cache transactionally<br />
consistent across the whole cluster, and with the database, is quite expensive. It makes most sense for data which is shared<br />
between many users, and is updated rarely. In traditional stateless architectures, people often try to use the second-level<br />
cache for conversational state. This is always bad, and is especially wrong in Seam.</p>
<p>• The Seam conversation context is a cache of conversational state. Components you put into the conversation context can hold<br />
and cache state relating to the current user interaction.</p>
<p>• In particular, the Seam-managed persistence context (or an extended EJB container-managed persistence context associated<br />
with a conversation-scoped stateful session bean) acts as a cache of data that has been read in the current conversation.<br />
This cache tends to have a pretty high hitrate! Seam optimizes the replication of Seam-managed persistence contexts in a<br />
clustered environment, and there is no requirement for transactional consistency with the database (optimistic locking is<br />
sufficient) so you don&#8217;t need to worry too much about the performance implications of this cache, unless you read thousands<br />
of objects into a single persistence context.</p>
<p>• The application can cache non-transactional state in the Seam application context. State kept in the application context<br />
is of course not visible to other nodes in the cluster.</p>
<p>• The application can cache transactional state using the Seam pojoCache component, which integrates JBossCache into the<br />
Seam environment. This state will be visible to other nodes if you run JBoss cache in a clustered mode.</p>
<p>• Finally, Seam lets you cache rendered fragments of a JSF page. Unlike the ORM second-level cache, this cache is not<br />
automatically invalidated when data changes, so you need to write application code to perform explicit invalidation, or set<br />
appropriate expiration policies.</p>
<p>For more information about the second-level cache, you&#8217;ll need to refer to the documentation of your ORM solution, since<br />
this is an extremely complex topic. In this section we&#8217;ll discuss the use of JBossCache directly, via the pojoCache<br />
component, or as the page fragment cache, via the &lt;s:cache&gt; control.</p>
<p>Using JBossCache in Seam: The built-in pojoCache component manages an instance of org.jboss.cache.aop.PojoCache.<br />
You can safely put any immutable Java object in the cache, and it will be replicated across the cluster (assuming that<br />
replication is enabled). If you want to keep mutable objects in the cache, you&#8217;ll need to run the JBossCache bytecode<br />
preprocessor to ensure that changes to the objects will be automatically detected and replicated.<br />
To use pojoCache, all you need to do is put the JBossCache jars in the classpath, and provide a resource named treecache.xml<br />
with an appropriate cache configuration. JBossCache has many scary and confusing configuration settings, so we won&#8217;t discuss<br />
them here. Please refer to the JBossCache documentation for more information.</p>
<p>You can find a sample treecache.xml in examples/blog/resources/treecache.xml. For an EAR depoyment of Seam, we recommend<br />
that the JBossCache jars and configuration go directly into the EAR. Make sure you place both jboss-cache.jar and<br />
jgroups.jar in your EAR&#8217;s lib folder. Now you can inject the cache into any Seam component:</p>
<p>@Name(&#8220;chatroom&#8221;)<br />
public class Chatroom {<br />
@In PojoCache pojoCache;<br />
public void join(String username) {<br />
try<br />
{<br />
Set&lt;String&gt; userList = (Set&lt;String&gt;) pojoCache.get(&#8220;chatroom&#8221;, &#8220;userList&#8221;);<br />
if (userList==null)<br />
{<br />
userList = new HashSet&lt;String&gt;();<br />
pojoCache.put(&#8220;chatroom&#8221;, &#8220;userList&#8221;, userList);<br />
}<br />
userList.put(username);<br />
}<br />
catch (CacheException ce)<br />
{<br />
throw new RuntimeException(ce);<br />
}<br />
}<br />
}</p>
<p>If you want to have multiple JBossCache configurations in your application, use components.xml:</p>
<p>&lt;core:pojo-cache name=&#8221;myCache&#8221; cfg-resource-name=&#8221;myown/cache.xml&#8221;/&gt;</p>
<p>Page fragment caching: The most interesting user of JBossCache is the &lt;s:cache&gt; tag, Seam&#8217;s solution to the problem<br />
of page fragment caching in JSF. &lt;s:cache&gt; uses pojoCache internally, so you need to follow the steps listed above before<br />
you can use it. (Put the jars in the EAR, wade through the scary configuration options, etc).</p>
<p>&lt;s:cache&gt; is used for caching some rendered content which changes rarely. For example, the welcome page of our blog displays<br />
the recent blog entries:</p>
<p>&lt;s:cache key=&#8221;recentEntries-#{blog.id}&#8221; region=&#8221;welcomePageFragments&#8221;&gt;<br />
&lt;h:dataTable value=&#8221;#{blog.recentEntries}&#8221; var=&#8221;blogEntry&#8221;&gt;<br />
&lt;h:column&gt;<br />
&lt;h3&gt;#{blogEntry.title}&lt;/h3&gt;<br />
&lt;div&gt;<br />
&lt;s:formattedText value=&#8221;#{blogEntry.body}&#8221;/&gt;<br />
&lt;/div&gt;<br />
&lt;/h:column&gt;<br />
&lt;/h:dataTable&gt;<br />
&lt;/s:cache&gt;</p>
<p>The key let&#8217;s you have multiple cached versions of each page fragment. In this case, there is one cached version per blog.<br />
The region determines the JBossCache node that all version will be stored in. Different nodes may have different expiry<br />
policies. (That&#8217;s the stuff you set up using the aforementioned scary configuration options).</p>
<p>Of course, the big problem with &lt;s:cache&gt; is that it is too stupid to know when the underlying data changes (for example,<br />
when the blogger posts a new entry). So you need to evict the cached fragment manually:</p>
<p>public void post() {<br />
&#8230;<br />
entityManager.persist(blogEntry);<br />
pojoCache.remove(&#8220;welcomePageFragments&#8221;, &#8220;recentEntries-&#8221; + blog.getId() );<br />
}</p>
<p>Alternatively, if it is not critical that changes are immediately visible to the user, you could set a short expiry time on<br />
the JbossCache node.</p>
<p>Web Services: Seam integrates with JBossWS to allow standard JEE web services to take full advantage of<br />
Seam&#8217;s contextual framework, including support for conversational web services. This chapter<br />
walks through the steps required to allow web services to run within a Seam environment.</p>
<p>Configuration and Packaging: To allow Seam to intercept web service requests so that the necessary Seam<br />
contexts can be created for the request, a special SOAP handler must be configured;<br />
org.jboss.seam.webservice.SOAPRequestHandler is a SOAPHandler implementation that<br />
does the work of managing Seam&#8217;s lifecycle during the scope of a web service request.</p>
<p>A special configuration file, standard-jaxws-endpoint-config.xml should be placed into the<br />
META-INF directory of the jar file that contains the web service classes. This file contains the<br />
following SOAP handler configuration:</p>
<p>&lt;jaxws-config xmlns=&#8221;urn:jboss:jaxws-config:2.0&#8243;<br />
xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221;<br />
xmlns:javaee=&#8221;http://java.sun.com/xml/ns/javaee&#8221;<br />
xsi:schemaLocation=&#8221;urn:jboss:jaxws-config:2.0 jaxws-config_2_0.xsd&#8221;&gt;<br />
&lt;endpoint-config&gt;<br />
&lt;config-name&gt;Seam WebService Endpoint&lt;/config-name&gt;<br />
&lt;pre-handler-chains&gt;<br />
&lt;javaee:handler-chain&gt;<br />
&lt;javaee:protocol-bindings&gt;##SOAP11_HTTP&lt;/javaee:protocol-bindings&gt;<br />
&lt;javaee:handler&gt;<br />
&lt;javaee:handler-name&gt;SOAP Request Handler&lt;/javaee:handler-name&gt;<br />
&lt;javaee:handler-class&gt;org.jboss.seam.webservice.SOAPRequestHandler&lt;/<br />
javaee:handler-class&gt;<br />
&lt;/javaee:handler&gt;<br />
&lt;/javaee:handler-chain&gt;<br />
&lt;/pre-handler-chains&gt;<br />
&lt;/endpoint-config&gt;<br />
&lt;/jaxws-config&gt;</p>
<p>Conversational Web Services: So how are conversations propagated between web service requests? Seam uses a SOAP header<br />
element present in both the SOAP request and response messages to carry the conversation ID<br />
from the consumer to the service, and back again. Here&#8217;s an example of a web service request<br />
that contains a conversation ID:</p>
<p>&lt;soapenv:Envelope xmlns:soapenv=&#8221;http://schemas.xmlsoap.org/soap/envelope/&#8221;<br />
xmlns:seam=&#8221;http://seambay.example.seam.jboss.org/&#8221;&gt;<br />
&lt;soapenv:Header&gt;<br />
&lt;seam:conversationId xmlns:seam=&#8217;http://www.jboss.org/seam/webservice&#8217;&gt;2&lt;/<br />
seam:conversationId&gt;<br />
&lt;/soapenv:Header&gt;<br />
&lt;soapenv:Body&gt;<br />
&lt;seam:confirmAuction/&gt;<br />
&lt;/soapenv:Body&gt;<br />
&lt;/soapenv:Envelope&gt;</p>
<p>As you can see in the above SOAP message, there is a conversationId element within the<br />
SOAP header that contains the conversation ID for the request, in this case 2. Unfortunately,<br />
because web services may be consumed by a variety of web service clients written in a variety of<br />
languages, it is up to the developer to implement conversation ID propagation between individual<br />
web services that are intended to be used within the scope of a single conversation.</p>
<p>An important thing to note is that the conversationId header element must be qualified with a<br />
namespace of http://www.jboss.org/seam/webservice, otherwise Seam will not be able to<br />
read the conversation ID from the request. Here&#8217;s an example of a response to the above request<br />
message:</p>
<p>&lt;env:Envelope xmlns:env=&#8217;http://schemas.xmlsoap.org/soap/envelope/&#8217;&gt;<br />
&lt;env:Header&gt;<br />
&lt;seam:conversationId xmlns:seam=&#8217;http://www.jboss.org/seam/webservice&#8217;&gt;2&lt;/<br />
seam:conversationId&gt;<br />
&lt;/env:Header&gt;<br />
&lt;env:Body&gt;<br />
&lt;confirmAuctionResponse xmlns=&#8221;http://seambay.example.seam.jboss.org/&#8221;/&gt;<br />
&lt;/env:Body&gt;<br />
&lt;/env:Envelope&gt;</p>
<p>As you can see, the response message contains the same conversationId element as the request.</p>
<p>A Recommended Strategy: As web services must be implemented as either a stateless session bean or POJO, it is recommended<br />
that for conversational web services, the web service acts as a facade to a conversational Seam component.</p>
<p>If the web service is written as a stateless session bean, then it is also possible to make it a Seam<br />
component by giving it a @Name. Doing this allows Seam&#8217;s bijection (and other) features to be used<br />
in the web service class itself.</p>
<p>An example web service: Let&#8217;s walk through an example web service. The code in this section all comes from the seamBay<br />
example application in Seam&#8217;s /examples directory, and follows the recommended strategy as<br />
described in the previous section. Let&#8217;s first take a look at the web service class and one of its<br />
web service methods:</p>
<p>@Stateless<br />
@WebService(name = &#8220;AuctionService&#8221;, serviceName = &#8220;AuctionService&#8221;)<br />
public class AuctionService implements AuctionServiceRemote<br />
{<br />
@WebMethod<br />
public boolean login(String username, String password)<br />
{<br />
Identity.instance().setUsername(username);<br />
Identity.instance().setPassword(password);<br />
Identity.instance().login();<br />
return Identity.instance().isLoggedIn();<br />
}<br />
// snip<br />
}</p>
<p>As you can see, our web service is a stateless session bean, and is annotated using the JWS<br />
annotations from the javax.jws package, as defined by JSR-181. The @WebService annotation<br />
tells the container that this class implements a web service, and the @WebMethod annotation on<br />
the login() method identifies the method as a web service method. The name and serviceName<br />
attributes in the @WebService annotation are optional.<br />
As is required by the specification, each method that is to be exposed as a web service method<br />
must also be declared in the remote interface of the web service class (when the web service<br />
is a stateless session bean). In the above example, the AuctionServiceRemote interface must<br />
declare the login() method as it is annotated as a @WebMethod.<br />
As you can see in the above code, the web service implements a login() method that delegates<br />
to Seam&#8217;s built-in Identity component. In keeping with our recommended strategy, the web<br />
service is written as a simple facade, passing off the real work to a Seam component. This allows<br />
for the greatest reuse of business logic between web services and other clients.<br />
Let&#8217;s look at another example. This web service method begins a new conversation by delegating<br />
to the AuctionAction.createAuction() method:</p>
<p>@WebMethod<br />
public void createAuction(String title, String description, int categoryId)<br />
{<br />
AuctionAction action = (AuctionAction) Component.getInstance(AuctionAction.class, true);<br />
action.createAuction();<br />
action.setDetails(title, description, categoryId);<br />
}</p>
<p>And here&#8217;s the code from AuctionAction:</p>
<p>@Begin<br />
public void createAuction()<br />
{<br />
auction = new Auction();<br />
auction.setAccount(authenticatedAccount);<br />
auction.setStatus(Auction.STATUS_UNLISTED);<br />
durationDays = DEFAULT_AUCTION_DURATION;<br />
}</p>
<p>From this we can see how web services can participate in long running conversations, by acting<br />
as a facade and delegating the real work to a conversational Seam component.</p>
<p>Remoting: Seam provides a convenient method of remotely accessing components from a web page, using<br />
AJAX (Asynchronous Javascript and XML). The framework for this functionality is provided with<br />
almost no up-front development effort &#8211; your components only require simple annotating to<br />
become accessible via AJAX. This chapter describes the steps required to build an AJAX-enabled<br />
web page, then goes on to explain the features of the Seam Remoting framework in more detail.</p>
<p>Configuration: To use remoting, the Seam Resource servlet must first be configured in your web.xml file:</p>
<p>&lt;servlet&gt;<br />
&lt;servlet-name&gt;Seam Resource Servlet&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;org.jboss.seam.servlet.SeamResourceServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;Seam Resource Servlet&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/seam/resource/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;</p>
<p>The next step is to import the necessary Javascript into your web page. There are a minimum of two scripts that must be<br />
imported. The first one contains all the client-side framework code that enables remoting functionality:</p>
<p>&lt;script type=&#8221;text/javascript&#8221; src=&#8221;seam/resource/remoting/resource/remote.js&#8221;&gt;&lt;/script&gt;</p>
<p>The second script contains the stubs and type definitions for the components you wish to call.<br />
It is generated dynamically based on the local interface of your components, and includes type<br />
definitions for all of the classes that can be used to call the remotable methods of the interface.<br />
The name of the script reflects the name of your component. For example, if you have a stateless<br />
session bean annotated with @Name(&#8220;customerAction&#8221;), then your script tag should look like this:</p>
<p>&lt;script type=&#8221;text/javascript&#8221;<br />
src=&#8221;seam/resource/remoting/interface.js?customerAction&#8221;&gt;&lt;/script&gt;</p>
<p>If you wish to access more than one component from the same page, then include them all as<br />
parameters of your script tag:</p>
<p>&lt;script type=&#8221;text/javascript&#8221;<br />
src=&#8221;seam/resource/remoting/interface.js?customerAction&amp;accountAction&#8221;&gt;&lt;/script&gt;</p>
<p>Alternatively, you may use the s:remote tag to import the required Javascript. Separate each<br />
component or class name you wish to import with a comma:</p>
<p>&lt;s:remote include=&#8221;customerAction,accountAction&#8221;/&gt;</p>
<p>The &#8220;Seam&#8221; object: Client-side interaction with your components is all performed via the Seam Javascript object.<br />
This object is defined in remote.js, and you&#8217;ll be using it to make asynchronous calls against<br />
your component. It is split into two areas of functionality; Seam.Component contains methods for<br />
working with components and Seam.Remoting contains methods for executing remote requests.<br />
The easiest way to become familiar with this object is to start with a simple example.<br />
A Hello World example:<br />
Let&#8217;s step through a simple example to see how the Seam object works. First of all, let&#8217;s create a<br />
new Seam component called helloAction.</p>
<p>@Stateless<br />
@Name(&#8220;helloAction&#8221;)<br />
public class HelloAction implements HelloLocal {<br />
public String sayHello(String name) {<br />
return &#8220;Hello, &#8221; + name;<br />
}<br />
}<br />
You also need to create a local interface for our new component &#8211; take special note of the<br />
@WebRemote annotation, as it&#8217;s required to make our method accessible via remoting:<br />
@Local<br />
public interface HelloLocal {<br />
@WebRemote<br />
public String sayHello(String name);<br />
}</p>
<p>That&#8217;s all the server-side code we need to write. Now for our web page &#8211; create a new page and<br />
import the helloAction component:</p>
<p>&lt;s:remote include=&#8221;helloAction&#8221;/&gt;</p>
<p>To make this a fully interactive user experience, let&#8217;s add a button to our page:<br />
&lt;button onclick=&#8221;javascript:sayHello()&#8221;&gt;Say Hello&lt;/button&gt;<br />
We&#8217;ll also need to add some more script to make our button actually do something when it&#8217;s clicked:</p>
<p>&lt;script type=&#8221;text/javascript&#8221;&gt;<br />
//&lt;![CDATA[<br />
function sayHello() {<br />
var name = prompt("What is your name?");<br />
Seam.Component.getInstance("helloAction").sayHello(name, sayHelloCallback);<br />
}<br />
function sayHelloCallback(result) {<br />
alert(result);<br />
}<br />
// ]]&gt;<br />
&lt;/script&gt;</p>
<p>We&#8217;re done! Deploy your application and browse to your page. Click the button, and enter a<br />
name when prompted. A message box will display the hello message confirming that the call was<br />
successful. If you want to save some time, you&#8217;ll find the full source code for this Hello World<br />
example in Seam&#8217;s /examples/remoting/helloworld directory.<br />
So what does the code of our script actually do? Let&#8217;s break it down into smaller pieces. To start<br />
with, you can see from the Javascript code listing that we have implemented two methods &#8211; the first<br />
method is responsible for prompting the user for their name and then making a remote request.<br />
Take a look at the following line:<br />
Seam.Component.getInstance(&#8220;helloAction&#8221;).sayHello(name, sayHelloCallback);<br />
The first section of this line, Seam.Component.getInstance(&#8220;helloAction&#8221;) returns a proxy,<br />
or &#8220;stub&#8221; for our helloAction component. We can invoke the methods of our component against this stub, which is exactly what<br />
happens with the remainder of the line: sayHello(name, sayHelloCallback);.<br />
What this line of code in its completeness does, is invoke the sayHello method of our component,<br />
passing in name as a parameter. The second parameter, sayHelloCallback isn&#8217;t a parameter<br />
of our component&#8217;s sayHello method, instead it tells the Seam Remoting framework that once<br />
it receives the response to our request, it should pass it to the sayHelloCallback Javascript<br />
method. This callback parameter is entirely optional, so feel free to leave it out if you&#8217;re calling a<br />
method with a void return type or if you don&#8217;t care about the result.<br />
The sayHelloCallback method, once receiving the response to our remote request then pops<br />
up an alert message displaying the result of our method call.</p>
<p>Seam.Component: The Seam.Component Javascript object provides a number of client-side methods for working<br />
with your Seam components. The two main methods, newInstance() and getInstance() are<br />
documented in the following sections however their main difference is that newInstance() will<br />
always create a new instance of a component type, and getInstance() will return a singleton<br />
instance.<br />
Seam.Component.newInstance():<br />
Use this method to create a new instance of an entity or Javabean component. The object<br />
returned by this method will have the same getter/setter methods as its server-side counterpart,<br />
or alternatively if you wish you can access its fields directly. Take the following Seam entity<br />
component for example:</p>
<p>@Name(&#8220;customer&#8221;)<br />
@Entity<br />
public class Customer implements Serializable<br />
{<br />
private Integer customerId;<br />
private String firstName;<br />
private String lastName;<br />
@Column public Integer getCustomerId() {<br />
return customerId;<br />
}<br />
public void setCustomerId(Integer customerId} {<br />
this.customerId = customerId;<br />
}<br />
@Column public String getFirstName() {<br />
return firstName;<br />
}<br />
public void setFirstName(String firstName) {<br />
this.firstName = firstName;<br />
}<br />
@Column public String getLastName() {<br />
return lastName;<br />
}<br />
public void setLastName(String lastName) {<br />
this.lastName = lastName;<br />
}<br />
}</p>
<p>To create a client-side Customer you would write the following code:</p>
<p>var customer = Seam.Component.newInstance(&#8220;customer&#8221;);</p>
<p>Then from here you can set the fields of the customer object:</p>
<p>customer.setFirstName(&#8220;John&#8221;);<br />
// Or you can set the fields directly<br />
customer.lastName = &#8220;Smith&#8221;;</p>
<p>Seam.Component.getInstance(): The getInstance() method is used to get a reference to a Seam session bean component stub,<br />
which can then be used to remotely execute methods against your component. This method<br />
returns a singleton for the specified component, so calling it twice in a row with the same<br />
component name will return the same instance of the component.<br />
To continue our example from before, if we have created a new customer and we now wish to<br />
save it, we would pass it to the saveCustomer() method of our customerAction component:</p>
<p>Seam.Component.getInstance(&#8220;customerAction&#8221;).saveCustomer(customer);</p>
<p>Seam.Component.getComponentName(): Passing an object into this method will return its component name if it is a component,<br />
or null if it is not.</p>
<p>if (Seam.Component.getComponentName(instance) == &#8220;customer&#8221;)<br />
alert(&#8220;Customer&#8221;);<br />
else if (Seam.Component.getComponentName(instance) == &#8220;staff&#8221;)<br />
alert(&#8220;Staff member&#8221;);</p>
<p>Seam.Remoting:<br />
Most of the client side functionality for Seam Remoting is contained within the Seam.Remoting<br />
object. While you shouldn&#8217;t need to directly call most of its methods, there are a couple of important<br />
ones worth mentioning.<br />
Seam.Remoting.createType():<br />
If your application contains or uses Javabean classes that aren&#8217;t Seam components, you may<br />
need to create these types on the client side to pass as parameters into your component method.<br />
Use the createType() method to create an instance of your type. Pass in the fully qualified Java<br />
class name as a parameter:</p>
<p>var widget = Seam.Remoting.createType(&#8220;com.acme.widgets.MyWidget&#8221;);</p>
<p>Seam.Remoting.getTypeName():<br />
This method is the equivalent of Seam.Component.getComponentName() but for non-component<br />
types. It will return the name of the type for an object instance, or null if the type is not known.<br />
The name is the fully qualified name of the type&#8217;s Java class.</p>
<p>Evaluating EL Expressions:<br />
Seam Remoting also supports the evaluation of EL expressions, which provides another<br />
convenient method for retrieving data from the server. Using the Seam.Remoting.eval() function,<br />
an EL expression can be remotely evaluated on the server and the resulting value returned<br />
to a client-side callback method. This function accepts two parameters, the first being the EL<br />
expression to evaluate, and the second being the callback method to invoke with the value of the<br />
expression. Here&#8217;s an example:</p>
<p>function customersCallback(customers) {<br />
for (var i = 0; i &lt; customers.length; i++) {<br />
alert(&#8220;Got customer: &#8221; + customers[i].getName());<br />
}<br />
}<br />
Seam.Remoting.eval(&#8220;#{customers}&#8221;, customersCallback);</p>
<p>In this example, the expression #{customers} is evaluated by Seam, and the value of the<br />
expression (in this case a list of Customer objects) is returned to the customersCallback()<br />
method. It is important to remember that the objects returned this way must have their types<br />
imported (via s:remote) to be able to work with them in Javascript. So to work with a list of<br />
customer objects, it is required to import the customer type:</p>
<p>&lt;s:remote include=&#8221;customer&#8221;/&gt;</p>
<p>Client Interfaces: In the configuration section above, the interface, or &#8220;stub&#8221; for our component is imported into our<br />
page either via seam/resource/remoting/interface.js: or using the s:remote tag:</p>
<p>&lt;script type=&#8221;text/javascript&#8221;<br />
src=&#8221;seam/resource/remoting/interface.js?customerAction&#8221;&gt;&lt;/script&gt;<br />
&lt;s:remote include=&#8221;customerAction&#8221;/&gt;</p>
<p>By including this script in our page, the interface definitions for our component, plus any other<br />
components or types that are required to execute the methods of our component are generated<br />
and made available for the remoting framework to use.<br />
There are two types of client stub that can be generated, &#8220;executable&#8221; stubs and &#8220;type&#8221; stubs.<br />
Executable stubs are behavioural, and are used to execute methods against your session bean<br />
components, while type stubs contain state and represent the types that can be passed in as<br />
parameters or returned as a result.<br />
The type of client stub that is generated depends on the type of your Seam component. If the<br />
component is a session bean, then an executable stub will be generated, otherwise if it&#8217;s an<br />
entity or JavaBean, then a type stub will be generated. There is one exception to this rule; if your<br />
component is a JavaBean (ie it is not a session bean nor an entity bean) and any of its methods<br />
are annotated with @WebRemote, then an executable stub will be generated for it instead of a<br />
type stub. This allows you to use remoting to call methods of your JavaBean components in a<br />
non-EJB environment where you don&#8217;t have access to session beans.</p>
<p>The Context:<br />
The Seam Remoting Context contains additional information which is sent and received as part<br />
of a remoting request/response cycle. At this stage it only contains the conversation ID but may<br />
be expanded in the future.</p>
<p>Setting and reading the Conversation ID:<br />
If you intend on using remote calls within the scope of a conversation then<br />
you need to be able to read or set the conversation ID in the Seam<br />
Remoting Context. To read the conversation ID after making a remote request call<br />
Seam.Remoting.getContext().getConversationId(). To set the conversation ID before<br />
making a request, call Seam.Remoting.getContext().setConversationId().<br />
If the conversation ID hasn&#8217;t been explicitly set with<br />
Seam.Remoting.getContext().setConversationId(), then it will be automatically assigned<br />
the first valid conversation ID that is returned by any remoting call. If you are working with multiple<br />
conversations within your page, then you may need to explicitly set the conversation ID before<br />
each call. If you are working with just a single conversation, then you don&#8217;t need to do anything<br />
special.</p>
<p>Remote calls within the current conversation scope:<br />
In some circumstances it may be required to make a remote call within the scope of the current<br />
view&#8217;s conversation. To do this, you must explicitly set the conversation ID to that of the view<br />
before making the remote call. This small snippet of JavaScript will set the conversation ID that<br />
is used for remoting calls to the current view&#8217;s conversation ID:<br />
Seam.Remoting.getContext().setConversationId( #{conversation.id} );</p>
<p>Batch Requests:<br />
Seam Remoting allows multiple component calls to be executed within a single request. It is<br />
recommended that this feature is used wherever it is appropriate to reduce network traffic.<br />
The method Seam.Remoting.startBatch() will start a new batch, and any component calls<br />
executed after starting a batch are queued, rather than being sent immediately. When all the<br />
desired component calls have been added to the batch, the Seam.Remoting.executeBatch()<br />
method will send a single request containing all of the queued calls to the server, where they will<br />
be executed in order. After the calls have been executed, a single response containining all return<br />
values will be returned to the client and the callback functions (if provided) triggered in the same<br />
order as execution.<br />
If you start a new batch via the startBatch() method but then decide you don&#8217;t want to send<br />
it, the Seam.Remoting.cancelBatch() method will discard any calls that were queued and exit<br />
the batch mode.<br />
To see an example of a batch being used, take a look at /examples/remoting/chatroom.</p>
<p>Working with Data types: Primitives / Basic Types:<br />
This section describes the support for basic data types. On the server side these values are<br />
generally compatible with either their primitive type or their corresponding wrapper class.<br />
String:<br />
Simply use Javascript String objects when setting String parameter values.<br />
Number:<br />
There is support for all number types supported by Java. On the client side, number values are<br />
always serialized as their String representation and then on the server side they are converted<br />
to the correct destination type. Conversion into either a primitive or wrapper type is supported for<br />
Byte, Double, Float, Integer, Long and Short types.<br />
Boolean:<br />
Booleans are represented client side by Javascript Boolean values, and server side by a Java<br />
boolean.<br />
JavaBeans:<br />
In general these will be either Seam entity or JavaBean components, or some other noncomponent<br />
class. Use the appropriate method (either Seam.Component.newInstance() for Seam<br />
components or Seam.Remoting.createType() for everything else) to create a new instance of<br />
the object.<br />
It is important to note that only objects that are created by either of these two methods should<br />
be used as parameter values, where the parameter is not one of the other valid types mentioned<br />
anywhere else in this section. In some situations you may have a component method where the<br />
exact parameter type cannot be determined, such as:<br />
@Name(&#8220;myAction&#8221;)<br />
public class MyAction implements MyActionLocal {<br />
public void doSomethingWithObject(Object obj) {<br />
// code<br />
}<br />
}</p>
<p>In this case you might want to pass in an instance of your myWidget component, however the<br />
interface for myAction won&#8217;t include myWidget as it is not directly referenced by any of its methods.<br />
To get around this, MyWidget needs to be explicitly imported:</p>
<p>&lt;s:remote include=&#8221;myAction,myWidget&#8221;/&gt;</p>
<p>This will then allow a myWidget object to be created with<br />
Seam.Component.newInstance(&#8220;myWidget&#8221;), which can then be passed to myAction.doSomethingWithObject().</p>
<p>Dates and Times:<br />
Date values are serialized into a String representation that is accurate to the millisecond. On the<br />
client side, use a Javascript Date object to work with date values. On the server side, use any<br />
java.util.Date (or descendent, such as java.sql.Date or java.sql.Timestamp class.<br />
Enums:<br />
On the client side, enums are treated the same as Strings. When setting the value for an enum<br />
parameter, simply use the String representation of the enum. Take the following component as<br />
an example:</p>
<p>@Name(&#8220;paintAction&#8221;)<br />
public class paintAction implements paintLocal {<br />
public enum Color {red, green, blue, yellow, orange, purple};<br />
public void paint(Color color) {<br />
// code<br />
}<br />
}</p>
<p>To call the paint() method with the color red, pass the parameter value as a String literal:<br />
Seam.Component.getInstance(&#8220;paintAction&#8221;).paint(&#8220;red&#8221;);<br />
The inverse is also true &#8211; that is, if a component method returns an enum parameter (or contains<br />
an enum field anywhere in the returned object graph) then on the client-side it will be represented as a String.</p>
<p>Collections:<br />
Bags:<br />
Bags cover all collection types including arrays, collections, lists, sets, (but excluding Maps &#8211; see<br />
the next section for those), and are implemented client-side as a Javascript array. When calling a<br />
component method that accepts one of these types as a parameter, your parameter should be a<br />
Javascript array. If a component method returns one of these types, then the return value will also<br />
be a Javascript array. The remoting framework is clever enough on the server side to convert the<br />
bag to an appropriate type for the component method call.<br />
Maps:<br />
As there is no native support for Maps within Javascript, a simple Map implementation is provided<br />
with the Seam Remoting framework. To create a Map which can be used as a parameter to a<br />
remote call, create a new Seam.Remoting.Map object:</p>
<p>var map = new Seam.Remoting.Map();</p>
<p>This Javascript implementation provides basic methods for working with Maps: size(),<br />
isEmpty(), keySet(), values(), get(key), put(key, value), remove(key) and<br />
contains(key). Each of these methods are equivalent to their Java counterpart. Where the<br />
method returns a collection, such as keySet() and values(), a Javascript Array object will be<br />
returned that contains the key or value objects (respectively).<br />
Debugging:<br />
To aid in tracking down bugs, it is possible to enable a debug mode which will display the contents<br />
of all the packets send back and forth between the client and server in a popup window. To enable<br />
debug mode, either execute the setDebug() method in Javascript:</p>
<p>Seam.Remoting.setDebug(true);</p>
<p>Or configure it via components.xml:</p>
<p>&lt;remoting:remoting debug=&#8221;true&#8221;/&gt;</p>
<p>To turn off debugging, call setDebug(false). If you want to write your own messages to the<br />
debug log, call Seam.Remoting.log(message).</p>
<p>The Loading Message:<br />
The default loading message that appears in the top right corner of the screen can be modified,<br />
its rendering customised or even turned off completely.<br />
Changing the message:<br />
To change the message from the default &#8220;Please Wait&#8230;&#8221; to something different, set the value of<br />
Seam.Remoting.loadingMessage:<br />
Seam.Remoting.loadingMessage = &#8220;Loading&#8230;&#8221;;<br />
Hiding the loading message:<br />
To completely suppress the display of the loading message, override the implementation of<br />
displayLoadingMessage() and hideLoadingMessage() with functions that instead do nothing:<br />
// don&#8217;t display the loading indicator<br />
Seam.Remoting.displayLoadingMessage = function() {};<br />
Seam.Remoting.hideLoadingMessage = function() {};<br />
A Custom Loading Indicator:<br />
It is also possible to override the loading indicator to display an animated icon, or anything else<br />
that you want. To do this override the displayLoadingMessage() and hideLoadingMessage()<br />
messages with your own implementation:<br />
Seam.Remoting.displayLoadingMessage = function() {<br />
// Write code here to display the indicator<br />
};<br />
Seam.Remoting.hideLoadingMessage = function() {<br />
// Write code here to hide the indicator<br />
};</p>
<p>Controlling what data is returned:<br />
When a remote method is executed, the result is serialized into an XML response that is returned<br />
to the client. This response is then unmarshaled by the client into a Javascript object. For<br />
complex types (i.e. Javabeans) that include references to other objects, all of these referenced<br />
objects are also serialized as part of the response. These objects may reference other objects,<br />
which may reference other objects, and so forth. If left unchecked, this object &#8220;graph&#8221; could<br />
potentially be enormous, depending on what relationships exist between your objects. And as<br />
a side issue (besides the potential verbosity of the response), you might also wish to prevent<br />
sensitive information from being exposed to the client.<br />
Seam Remoting provides a simple means to &#8220;constrain&#8221; the object graph, by specifying the<br />
exclude field of the remote method&#8217;s @WebRemote annotation. This field accepts a String array<br />
containing one or more paths specified using dot notation. When invoking a remote method, the<br />
objects in the result&#8217;s object graph that match these paths are excluded from the serialized result packet.<br />
For all our examples, we&#8217;ll use the following Widget class:</p>
<p>@Name(&#8220;widget&#8221;)<br />
public class Widget<br />
{<br />
private String value;<br />
private String secret;<br />
private Widget child;<br />
private Map&lt;String,Widget&gt; widgetMap;<br />
private List&lt;Widget&gt; widgetList;<br />
// getters and setters for all fields<br />
}</p>
<p>Constraining normal fields: If your remote method returns an instance of Widget, but you don&#8217;t want to expose the secret<br />
field because it contains sensitive information, you would constrain it like this:</p>
<p>@WebRemote(exclude = {&#8220;secret&#8221;})<br />
public Widget getWidget();</p>
<p>The value &#8220;secret&#8221; refers to the secret field of the returned object. Now, suppose that we don&#8217;t<br />
care about exposing this particular field to the client. Instead, notice that the Widget value that<br />
is returned has a field child that is also a Widget. What if we want to hide the child&#8217;s secret<br />
value instead? We can do this by using dot notation to specify this field&#8217;s path within the result&#8217;s<br />
object graph:</p>
<p>@WebRemote(exclude = {&#8220;child.secret&#8221;})<br />
public Widget getWidget();</p>
<p>Constraining Maps and Collections<br />
The other place that objects can exist within an object graph are within a Map or some kind of<br />
collection (List, Set, Array, etc). Collections are easy, and are treated like any other field. For<br />
example, if our Widget contained a list of other Widgets in its widgetList field, to constrain the<br />
secret field of the Widgets in this list the annotation would look like this:</p>
<p>@WebRemote(exclude = {&#8220;widgetList.secret&#8221;})<br />
public Widget getWidget();</p>
<p>To constrain a Map&#8217;s key or value, the notation is slightly different. Appending [key] after the Map&#8217;s<br />
field name will constrain the Map&#8217;s key object values, while [value] will constrain the value object<br />
values. The following example demonstrates how the values of the widgetMap field have their<br />
secret field constrained:</p>
<p>@WebRemote(exclude = {&#8220;widgetMap[value].secret&#8221;})<br />
public Widget getWidget();</p>
<p>Constraining objects of a specific type:<br />
There is one last notation that can be used to constrain the fields of a type of object no matter<br />
where in the result&#8217;s object graph it appears. This notation uses either the name of the component<br />
(if the object is a Seam component) or the fully qualified class name (only if the object is not a<br />
Seam component) and is expressed using square brackets:</p>
<p>@WebRemote(exclude = {&#8220;[widget].secret&#8221;})<br />
public Widget getWidget();</p>
<p>Combining Constraints:<br />
Constraints can also be combined, to filter objects from multiple paths within the object graph:</p>
<p>@WebRemote(exclude = {&#8220;widgetList.secret&#8221;, &#8220;widgetMap[value].secret&#8221;})</p>
<p>public Widget getWidget();</p>
<p>JMS Messaging:<br />
Seam Remoting provides experimental support for JMS Messaging. This section describes the<br />
JMS support that is currently implemented, but please note that this may change in the future. It<br />
is currently not recommended that this feature is used within a production environment.<br />
Configuration:<br />
Before you can subscribe to a JMS topic, you must first configure a list<br />
of the topics that can be subscribed to by Seam Remoting. List the topics<br />
under org.jboss.seam.remoting.messaging.subscriptionRegistry.allowedTopics in<br />
seam.properties, web.xml or components.xml.</p>
<p>&lt;remoting:remoting poll-timeout=&#8221;5&#8243; poll-interval=&#8221;1&#8243;/&gt;</p>
<p>Subscribing to a JMS Topic:<br />
The following example demonstrates how to subscribe to a JMS Topic:</p>
<p>function subscriptionCallback(message)<br />
{<br />
if (message instanceof Seam.Remoting.TextMessage)<br />
alert(&#8220;Received message: &#8221; + message.getText());<br />
}<br />
Seam.Remoting.subscribe(&#8220;topicName&#8221;, subscriptionCallback);</p>
<p>The Seam.Remoting.subscribe() method accepts two parameters, the first being the name of<br />
the JMS Topic to subscribe to, the second being the callback function to invoke when a message is received.<br />
There are two types of messages supported, Text messages and Object messages. If you<br />
need to test for the type of message that is passed to your callback function you can use<br />
the instanceof operator to test whether the message is a Seam.Remoting.TextMessage or<br />
Seam.Remoting.ObjectMessage. A TextMessage contains the text value in its text field (or<br />
alternatively call getText() on it), while an ObjectMessage contains its object value in its value<br />
field (or call its getValue() method).</p>
<p>Unsubscribing from a Topic<br />
To unsubscribe from a topic, call Seam.Remoting.unsubscribe() and pass in the topic name:</p>
<p>Seam.Remoting.unsubscribe(&#8220;topicName&#8221;);</p>
<p>Tuning the Polling Process:<br />
There are two parameters which you can modify to control how polling occurs. The first one is<br />
Seam.Remoting.pollInterval, which controls how long to wait between subsequent polls for<br />
new messages. This parameter is expressed in seconds, and its default setting is 10.<br />
The second parameter is Seam.Remoting.pollTimeout, and is also expressed as seconds. It<br />
controls how long a request to the server should wait for a new message before timing out and<br />
sending an empty response. Its default is 0 seconds, which means that when the server is polled,<br />
if there are no messages ready for delivery then an empty response will be immediately returned.<br />
Caution should be used when setting a high pollTimeout value; each request that has to wait for<br />
a message means that a server thread is tied up until a message is received, or until the request<br />
times out. If many such requests are being served simultaneously, it could mean a large number<br />
of threads become tied up because of this reason.<br />
It is recommended that you set these options via components.xml, however they can be overridden<br />
via Javascript if desired. The following example demonstrates how to configure the polling to occur<br />
much more aggressively. You should set these parameters to suitable values for your application:<br />
Via components.xml:</p>
<p>&lt;remoting:remoting poll-timeout=&#8221;5&#8243; poll-interval=&#8221;1&#8243;/&gt;</p>
<p>Via JavaScript:</p>
<p>// Only wait 1 second between receiving a poll response and sending the next poll request.<br />
Seam.Remoting.pollInterval = 1;</p>
<p>// Wait up to 5 seconds on the server for new messages<br />
Seam.Remoting.pollTimeout = 5;</p>
<p>Seam and the Google Web Toolkit: To use GWT in our applications, we need to install Seam resource servlet.</p>
<p>Spring Framework integration:</p>
<p>Hibernate Search:<br />
Configuration:<br />
Hibernate Search is configured either in the META-INF/persistence.xml or hibernate.cfg.xml<br />
file. Hibernate Search configuration has sensible defaults for most configuration parameters. Here is<br />
a minimal persistence unit configuration to get started.</p>
<p>&lt;persistence-unit name=&#8221;sample&#8221;&gt;<br />
&lt;jta-data-source&gt;java:/DefaultDS&lt;/jta-data-source&gt;<br />
&lt;properties&gt;<br />
[...]<br />
&lt;!&#8211; use a file system based index &#8211;&gt;<br />
&lt;property name=&#8221;hibernate.search.default.directory_provider&#8221;<br />
value=&#8221;org.hibernate.search.store.FSDirectoryProvider&#8221;/&gt;<br />
&lt;!&#8211; directory where the indexes will be stored &#8211;&gt;<br />
&lt;property name=&#8221;hibernate.search.default.indexBase&#8221;<br />
value=&#8221;/Users/prod/apps/dvdstore/dvdindexes&#8221;/&gt;<br />
&lt;/properties&gt;<br />
&lt;/persistence-unit&gt;</p>
<p>If you plan to target Hibernate Annotations or EntityManager 3.2.x (embedded into JBoss AS 4.2.GA), you also need to<br />
configure the appropriate event listeners.</p>
<p>&lt;persistence-unit name=&#8221;sample&#8221;&gt;<br />
&lt;jta-data-source&gt;java:/DefaultDS&lt;/jta-data-source&gt;<br />
&lt;properties&gt;<br />
[...]<br />
&lt;!&#8211; use a file system based index &#8211;&gt;<br />
&lt;property name=&#8221;hibernate.search.default.directory_provider&#8221;<br />
value=&#8221;org.hibernate.search.store.FSDirectoryProvider&#8221;/&gt;<br />
&lt;!&#8211; directory where the indexes will be stored &#8211;&gt;<br />
&lt;property name=&#8221;hibernate.search.default.indexBase&#8221;<br />
value=&#8221;/Users/prod/apps/dvdstore/dvdindexes&#8221;/&gt;<br />
&lt;property name=&#8221;hibernate.ejb.event.post-insert&#8221;<br />
value=&#8221;org.hibernate.search.event.FullTextIndexEventListener&#8221;/&gt;<br />
&lt;property name=&#8221;hibernate.ejb.event.post-update&#8221;<br />
value=&#8221;org.hibernate.search.event.FullTextIndexEventListener&#8221;/&gt;<br />
&lt;property name=&#8221;hibernate.ejb.event.post-delete&#8221;<br />
value=&#8221;org.hibernate.search.event.FullTextIndexEventListener&#8221;/&gt;<br />
&lt;/properties&gt;<br />
&lt;/persistence-unit&gt;</p>
<p>This step is no longer necessary if Hibernate Annotation or EntityManager 3.3.x are used.</p>
<p>In addition to the configuration file, the following jars have to be deployed:<br />
• hibernate-search.jar<br />
• hibernate-commons-annotations.jar<br />
• lucene-core.jar</p>
<p>If you deploy those in a EAR, don&#8217;t forget to update application.xml.</p>
<p>Usage<br />
Hibernate Search uses annotations to map entities to a Lucene index, check the reference<br />
documentation [http://www.hibernate.org/hib_docs/search/reference/en/html_single/] for more<br />
informations.<br />
Hibernate Search is fully integrated with the API and semantic of JPA / Hibernate. Switching from<br />
a HQL or Criteria based query requires just a few lines of code. The main API the application<br />
interacts with is the FullTextSession API (subclass of Hibernate&#8217;s Session).<br />
When Hibernate Search is present, JBoss Seam injects a FullTextSession.</p>
<p>@Stateful<br />
@Name(&#8220;search&#8221;)<br />
public class FullTextSearchAction implements FullTextSearch, Serializable {<br />
@In FullTextSession session;<br />
public void search(String searchString) {<br />
org.apache.lucene.query.Query luceneQuery = getLuceneQuery();<br />
org.hibernate.Query query session.createFullTextQuery(luceneQuery, Product.class);<br />
searchResults = query<br />
.setMaxResults(pageSize + 1)<br />
.setFirstResult(pageSize * currentPage)<br />
.list();<br />
}<br />
[...]<br />
}</p>
<p>FullTextSession extends org.hibernate.Session so that it can be used as a regular Hibernate Session.</p>
<p>If the Java Persistence API is used, a smoother integration is proposed.</p>
<p>@Stateful<br />
@Name(&#8220;search&#8221;)<br />
public class FullTextSearchAction implements FullTextSearch, Serializable {<br />
@In FullTextEntityManager em;<br />
public void search(String searchString) {<br />
org.apache.lucene.query.Query luceneQuery = getLuceneQuery();<br />
javax.persistence.Query query = em.createFullTextQuery(luceneQuery, Product.class);<br />
searchResults = query<br />
.setMaxResults(pageSize + 1)<br />
.setFirstResult(pageSize * currentPage)<br />
.getResultList();<br />
}<br />
[...]<br />
}</p>
<p>When Hibernate Search is present, a FulltextEntityManager is injected.<br />
FullTextEntityManager extends EntityManager with search specific methods, the same way<br />
FullTextSession extends Session.<br />
When an EJB 3.0 Session or Message Driven Bean injection is used (i.e. via the<br />
@PersistenceContext annotation), it is not possible to replace the EntityManager interface by<br />
the FullTextEntityManager interface in the declaration statement. However, the implementation<br />
injected will be a FullTextEntityManager implementation: downcasting is then possible.</p>
<p>@Stateful<br />
@Name(&#8220;search&#8221;)<br />
public class FullTextSearchAction implements FullTextSearch, Serializable {<br />
@PersistenceContext EntityManager em;<br />
public void search(String searchString) {<br />
org.apache.lucene.query.Query luceneQuery = getLuceneQuery();<br />
FullTextEntityManager ftEm = (FullTextEntityManager) em;<br />
javax.persistence.Query query = ftEm.createFullTextQuery(luceneQuery, Product.class);<br />
searchResults = query<br />
.setMaxResults(pageSize + 1)<br />
.setFirstResult(pageSize * currentPage)<br />
.getResultList();<br />
}<br />
[...]<br />
}</p>
<p>For people accustomed to Hibernate Search out of Seam, note that using Search.createFullTextSession is not necessary.</p>
<p>Check the DVDStore or the blog examples of the JBoss Seam distribution for a concrete use of Hibernate Search.</p>
<p>Configuring Seam and packaging Seam applications:<br />
Basic Seam configuration:<br />
First, let&#8217;s look at the basic configuration that is needed whenever we use Seam with JSF.</p>
<p>Integrating Seam with JSF and your servlet container:<br />
Of course, you need a faces servlet!</p>
<p>&lt;servlet&gt;<br />
&lt;servlet-name&gt;Faces Servlet&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;javax.faces.webapp.FacesServlet&lt;/servlet-class&gt;<br />
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;Faces Servlet&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;*.seam&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;</p>
<p>In addition, Seam requires the following entry in your web.xml file:</p>
<p>&lt;listener&gt;<br />
&lt;listener-class&gt;org.jboss.seam.servlet.SeamListener&lt;/listener-class&gt;<br />
&lt;/listener&gt;</p>
<p>This listener is responsible for bootstrapping Seam, and for destroying session and application contexts.<br />
Some JSF implementations have a broken implementation of server-side state saving that interferes with Seam&#8217;s conversation<br />
propagation. If you have problems with conversation propagation during form submissions, try switching to client-side state<br />
saving. You&#8217;ll need this in web.xml:</p>
<p>&lt;context-param&gt;<br />
&lt;param-name&gt;javax.faces.STATE_SAVING_METHOD&lt;/param-name&gt;<br />
&lt;param-value&gt;client&lt;/param-value&gt;<br />
&lt;/context-param&gt;</p>
<p>Using facelets:</p>
<p>If you want follow our advice and use facelets instead of JSP, add the following lines to facesconfig.xml:</p>
<p>&lt;application&gt;<br />
&lt;view-handler&gt;com.sun.facelets.FaceletViewHandler&lt;/view-handler&gt;<br />
&lt;/application&gt;</p>
<p>And the following lines to web.xml:</p>
<p>&lt;context-param&gt;<br />
&lt;param-name&gt;javax.faces.DEFAULT_SUFFIX&lt;/param-name&gt;<br />
&lt;param-value&gt;.xhtml&lt;/param-value&gt;<br />
&lt;/context-param&gt;</p>
<p>Seam Resource Servlet: The Seam Resource Servlet provides resources used by Seam Remoting, captchas (see the<br />
security chapter) and some JSF UI controls. Configuring the Seam Resource Servlet requires the following entry in web.xml:</p>
<p>&lt;servlet&gt;<br />
&lt;servlet-name&gt;Seam Resource Servlet&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;org.jboss.seam.servlet.SeamResourceServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;</p>
<p>&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;Seam Resource Servlet&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/seam/resource/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;</p>
<p>Seam servlet filters:<br />
Seam doesn&#8217;t need any servlet filters for basic operation. However, there are several features<br />
which depend upon the use of filters. To make things easier, Seam lets you add and configure<br />
servlet filters just like you would configure other built-in Seam components. To take advantage of<br />
this feature, we must first install a master filter in web.xml:</p>
<p>&lt;filter&gt;<br />
&lt;filter-name&gt;Seam Filter&lt;/filter-name&gt;<br />
&lt;filter-class&gt;org.jboss.seam.servlet.SeamFilter&lt;/filter-class&gt;<br />
&lt;/filter&gt;</p>
<p>&lt;filter-mapping&gt;<br />
&lt;filter-name&gt;Seam Filter&lt;/filter-name&gt;<br />
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />
&lt;/filter-mapping&gt;</p>
<p>The Seam master filter must be the first filter specified in web.xml. This ensures it is run first.</p>
<p>The Seam filters share a number of common attributes, you can set these in components.xml in<br />
addition to any parameters discussed below:<br />
• url-pattern — Used to specify which requests are filtered, the default is all requests. urlpattern<br />
is a Tomcat style pattern which allows a wildcard suffix.<br />
• regex-url-pattern — Used to specify which requests are filtered, the default is all requests.<br />
regex-url-pattern is a true regular expression match for request path. It&#8217;s worth noting when<br />
composing the regular expression that the request path does not contain the server or request<br />
context path.<br />
• disabled — Used to disable a built in filter.<br />
Adding the master filter enables the following built-in filters.</p>
<p>Exception handling:<br />
This filter provides the exception mapping functionality in pages.xml (almost all applications will<br />
need this). It also takes care of rolling back uncommitted transactions when uncaught exceptions<br />
occur. (According to the Java EE specification, the web container should do this automatically, but<br />
we&#8217;ve found that this behavior cannot be relied upon in all application servers. And it is certainly<br />
not required of plain servlet engines like Tomcat.)<br />
By default, the exception handling filter will process all requests, however this behavior may<br />
be adjusted by adding a &lt;web:exception-filter&gt; entry to components.xml, as shown in this<br />
example:</p>
<p>&lt;components xmlns=&#8221;http://jboss.com/products/seam/components&#8221;<br />
xmlns:web=&#8221;http://jboss.com/products/seam/web&#8221;&gt;<br />
&lt;web:exception-filter url-pattern=&#8221;*.seam&#8221;/&gt;<br />
&lt;/components&gt;</p>
<p>Conversation propagation with redirects:<br />
This filter allows Seam to propagate the conversation context across browser redirects. It<br />
intercepts any browser redirects and adds a request parameter that specifies the Seam<br />
conversation identifier.<br />
The redirect filter will process all requests by default, but this behavior can also be adjusted in components.xml:</p>
<p>&lt;web:redirect-filter url-pattern=&#8221;*.seam&#8221;/&gt;</p>
<p>Multipart form submissions:<br />
This feature is necessary when using the Seam file upload JSF control. It detects multipart form<br />
requests and processes them according to the multipart/form-data specification (RFC-2388). To<br />
override the default settings, add the following entry to components.xml:<br />
&lt;web:multipart-filter create-temp-files=&#8221;true&#8221;<br />
max-request-size=&#8221;1000000&#8243;<br />
url-pattern=&#8221;*.seam&#8221;/&gt;<br />
• create-temp-files — If set to true, uploaded files are written to a temporary file (instead of<br />
held in memory). This may be an important consideration if large file uploads are expected. The<br />
default setting is false.<br />
• max-request-size — If the size of a file upload request (determined by reading the Content-<br />
Length header in the request) exceeds this value, the request will be aborted. The default<br />
setting is 0 (no size limit).</p>
<p>Character encoding<br />
Sets the character encoding of submitted form data.<br />
This filter is not installed by default and requires an entry in components.xml to enable it:</p>
<p>&lt;web:character-encoding-filter encoding=&#8221;UTF-16&#8243;<br />
override-client=&#8221;true&#8221;<br />
url-pattern=&#8221;*.seam&#8221;/&gt;<br />
• encoding — The encoding to use.<br />
• override-client — If this is set to true, the request encoding will be set to whatever is<br />
specified by encoding no matter whether the request already specifies an encoding or not. If<br />
set to false, the request encoding will only be set if the request doesn&#8217;t already specify an<br />
encoding. The default setting is false.</p>
<p>RichFaces:<br />
If RichFaces is used in your project, Seam will install the RichFaces Ajax filter for you, making<br />
sure to install it before all other built-in filters. You don&#8217;t need to install the RichFaces Ajax filter<br />
in web.xml yourself.<br />
The RichFaces Ajax filter is only installed if the RichFaces jars are present in your project.<br />
To override the default settings, add the following entry to components.xml. The options are the<br />
same as those specified in the RichFaces Developer Guide:</p>
<p>&lt;web:ajax4jsf-filter force-parser=&#8221;true&#8221;<br />
enable-cache=&#8221;true&#8221;<br />
log4j-init-file=&#8221;custom-log4j.xml&#8221;<br />
url-pattern=&#8221;*.seam&#8221;/&gt;</p>
<p>• force-parser — forces all JSF pages to be validated by Richfaces&#8217;s XML syntax checker. If<br />
false, only AJAX responses are validated and converted to well-formed XML. Setting forceparser<br />
to false improves performance, but can provide visual artifacts on AJAX updates.<br />
• enable-cache — enables caching of framework-generated resources (e.g. javascript, CSS,<br />
images, etc). When developing custom javascript or CSS, setting to true prevents the browser<br />
from caching the resource.<br />
• log4j-init-file — is used to setup per-application logging. A path, relative to web application<br />
context, to the log4j.xml configuration file should be provided.</p>
<p>Identity Logging:<br />
This filter adds the authenticated user name to the log4j mapped diagnostic context so that it can<br />
be included in formatted log output if desired, by adding %X{username} to the pattern. By default, the logging filter will<br />
process all requests, however this behavior may be adjusted by adding a &lt;web:logging-filter&gt; entry to components.xml, as<br />
shown in this example:</p>
<p>&lt;components xmlns=&#8221;http://jboss.com/products/seam/components&#8221;<br />
xmlns:web=&#8221;http://jboss.com/products/seam/web&#8221;&gt;<br />
&lt;web:logging-filter url-pattern=&#8221;*.seam&#8221;/&gt;<br />
&lt;/components&gt;</p>
<p>Context management for custom servlets:<br />
Requests sent direct to some servlet other than the JSF servlet are not processed through the<br />
JSF lifecycle, so Seam provides a servlet filter that can be applied to any other servlet that needs<br />
access to Seam components.<br />
This filter allows custom servlets to interact with the Seam contexts. It sets up the Seam contexts<br />
at the beginning of each request, and tears them down at the end of the request. You should make<br />
sure that this filter is never applied to the JSF FacesServlet. Seam uses the phase listener for<br />
context management in a JSF request.<br />
This filter is not installed by default and requires an entry in components.xml to enable it:</p>
<p>&lt;web:context-filter url-pattern=&#8221;/media/*&#8221;/&gt;</p>
<p>The context filter expects to find the conversation id of any conversation context in a request<br />
parameter named conversationId. You are responsible for ensuring that it gets sent in the<br />
request.<br />
You are also responsible for ensuring propagation of any new conversation id back to the client.<br />
Seam exposes the conversation id as a property of the built in component conversation.</p>
<p>Adding custom filters:<br />
Seam can install your filters for you, allowing you to specify where in the chain your filter is<br />
placed (the servlet specification doesn&#8217;t provide a well defined order if you specify your filters in<br />
a web.xml). Just add the @Filter annotation to your Seam component (which must implement<br />
javax.servlet.Filter):</p>
<p>@Startup<br />
@Scope(APPLICATION)<br />
@Name(&#8220;org.jboss.seam.web.multipartFilter&#8221;)<br />
@BypassInterceptors<br />
@Filter(within=&#8221;org.jboss.seam.web.ajax4jsfFilter&#8221;)<br />
public class MultipartFilter extends AbstractFilter {</p>
<p>Adding the @Startup annotation means thar the component is available during Seam startup;<br />
bijection isn&#8217;t available here (@BypassInterceptors); and the filter should be further down the<br />
chain than the RichFaces filter (@Filter(within=&#8221;org.jboss.seam.web.ajax4jsfFilter&#8221;)).</p>
<p>Integrating Seam with your EJB container:<br />
We need to apply the SeamInterceptor to our Seam components. The simplest way to do this<br />
across an entire application is to add the following interceptor configuration in ejb-jar.xml:</p>
<p>&lt;interceptors&gt;<br />
&lt;interceptor&gt;<br />
&lt;interceptor-class&gt;org.jboss.seam.ejb.SeamInterceptor&lt;/interceptor-class&gt;<br />
&lt;/interceptor&gt;<br />
&lt;/interceptors&gt;<br />
&lt;assembly-descriptor&gt;<br />
&lt;interceptor-binding&gt;<br />
&lt;ejb-name&gt;*&lt;/ejb-name&gt;<br />
&lt;interceptor-class&gt;org.jboss.seam.ejb.SeamInterceptor&lt;/interceptor-class&gt;<br />
&lt;/interceptor-binding&gt;<br />
&lt;/assembly-descriptor&gt;</p>
<p>Seam needs to know where to go to find session beans in JNDI. One way to do this is specify<br />
the @JndiName annotation on every session bean Seam component. However, this is quite<br />
tedious. A better approach is to specify a pattern that Seam can use to calculate the JNDI<br />
name from the EJB name. Unfortunately, there is no standard mapping to global JNDI defined<br />
in the EJB3 specification, so this mapping is vendor-specific. We usually specify this option in components.xml.</p>
<p>For JBoss AS, the following pattern is correct:</p>
<p>&lt;core:init jndi-name=&#8221;myEarName/#{ejbName}/local&#8221; /&gt;</p>
<p>Where myEarName is the name of the EAR in which the bean is deployed.<br />
Outside the context of an EAR (when using the JBoss Embeddable EJB3 container), the following<br />
pattern is the one to use:</p>
<p>&lt;core:init jndi-name=&#8221;#{ejbName}/local&#8221; /&gt;</p>
<p>Don&#8217;t forget!: There is one final item you need to know about. You must place a seam.properties, METAINF/<br />
seam.properties or META-INF/components.xml file in any archive in which your Seam<br />
components are deployed (even an empty properties file will do). At startup, Seam will scan any<br />
archives with seam.properties files for seam components.<br />
In a web archive (WAR) file, you must place a seam.properties file in the WEB-INF/classes<br />
directory if you have any Seam components included here.<br />
That&#8217;s why all the Seam examples have an empty seam.properties file. You can&#8217;t just delete<br />
this file and expect everything to still work!<br />
You might think this is silly and what kind of idiot framework designers would make an empty file<br />
affect the behavior of their software?? Well, this is a workaround for a limitation of the JVM—if<br />
we didn&#8217;t use this mechanism, our next best option would be to force you to list every component<br />
explicitly in components.xml, just like some other competing frameworks do!</p>
<p>Packaging: Once you&#8217;ve packaged all this stuff together into an EAR, the archive structure will look something<br />
like this:</p>
<p>my-application.ear/<br />
jboss-seam.jar<br />
lib/<br />
jboss-el.jar<br />
META-INF/<br />
MANIFEST.MF<br />
application.xml<br />
my-application.war/<br />
META-INF/<br />
MANIFEST.MF<br />
WEB-INF/<br />
web.xml<br />
components.xml<br />
faces-config.xml<br />
lib/<br />
jsf-facelets.jar<br />
jboss-seam-ui.jar<br />
login.jsp<br />
register.jsp<br />
&#8230;<br />
my-application.jar/<br />
META-INF/<br />
MANIFEST.MF<br />
persistence.xml<br />
seam.properties<br />
org/<br />
jboss/<br />
myapplication/<br />
User.class<br />
Login.class<br />
LoginBean.class<br />
Register.class<br />
RegisterBean.class<br />
&#8230;</p>
<p>You should declare jboss-seam.jar as an ejb module in META-INF/application.xml; jbossel.<br />
jar should be placed in the EAR&#8217;s lib directory (putting it in the EAR classpath.<br />
If you want to use jBPM or Drools, you must include the needed jars in the EAR&#8217;s lib directory.<br />
If you want to use facelets (our recommendation), you must include jsf-facelets.jar in the<br />
WEB-INF/lib directory of the WAR.</p>
<p>If you want to use the Seam tag library (most Seam applications do), you must include jbossseam-<br />
ui.jar in the WEB-INF/lib directory of the WAR. If you want to use the PDF or email tag<br />
libraries, you need to put jboss-seam-pdf.jar or jboss-seam-mail.jar in WEB-INF/lib.<br />
If you want to use the Seam debug page (only works for applications using facelets), you must<br />
include jboss-seam-debug.jar in the WEB-INF/lib directory of the WAR.<br />
Seam ships with several example applications that are deployable in any Java EE container that<br />
supports EJB 3.0.</p>
<p>Boostrapping Hibernate in Seam: Seam will bootstrap a Hibernate SessionFactory from your hibernate.cfg.xml file if you<br />
install a built-in component:</p>
<p>&lt;persistence:hibernate-session-factory name=&#8221;hibernateSessionFactory&#8221;/&gt;<br />
You will also need to configure a managed session if you want a Seam managed Hibernate<br />
Session to be available via injection.<br />
&lt;persistence:managed-hibernate-session name=&#8221;hibernateSession&#8221;<br />
session-factory=&#8221;#{hibernateSessionFactory}&#8221;/&gt;</p>
<p>Boostrapping JPA in Seam:<br />
Seam will bootstrap a JPA EntityManagerFactory from your persistence.xml file if you install<br />
this built-in component:</p>
<p>&lt;persistence:entity-manager-factory name=&#8221;entityManagerFactory&#8221;/&gt;<br />
You will also need to configure a managed persistence context if you want a Seam managed JPA<br />
EntityManager to be available via injection.<br />
&lt;persistence:managed-persistence-context name=&#8221;entityManager&#8221;<br />
entity-manager-factory=&#8221;#{entityManagerFactory}&#8221;/&gt;</p>
<p>Packaging:<br />
We can package our application as a WAR, in the following structure:</p>
<p>my-application.war/<br />
META-INF/<br />
MANIFEST.MF<br />
WEB-INF/<br />
web.xml<br />
components.xml<br />
faces-config.xml<br />
lib/<br />
jboss-seam.jar<br />
jboss-seam-ui.jar<br />
jboss-el.jar<br />
jsf-facelets.jar<br />
hibernate3.jar<br />
hibernate-annotations.jar<br />
hibernate-validator.jar<br />
&#8230;<br />
my-application.jar/<br />
META-INF/<br />
MANIFEST.MF<br />
seam.properties<br />
hibernate.cfg.xml<br />
org/<br />
jboss/<br />
myapplication/<br />
User.class<br />
Login.class<br />
Register.class<br />
&#8230;<br />
login.jsp<br />
register.jsp<br />
&#8230;</p>
<p>If we want to deploy Hibernate in a non-EE environment like Tomcat or TestNG, we need to do<br />
a little bit more work.</p>
<p>Configuring SFSB and Session Timeouts in JBoss AS: It is very important that the timeout for Stateful Session Beans is set<br />
higher than the timeout for HTTP Sessions, otherwise SFSB&#8217;s may time out before the user&#8217;s HTTP session has ended.<br />
JBoss Application Server has a default session bean timeout of 30 minutes, which is configured<br />
in server/default/conf/standardjboss.xml (replace default with your own configuration).<br />
The default SFSB timeout can be adjusted by modifying the value of max-bean-life in the<br />
LRUStatefulContextCachePolicy cache configuration:</p>
<p>&lt;container-cache-conf&gt;<br />
&lt;cache-policy&gt;org.jboss.ejb.plugins.LRUStatefulContextCachePolicy&lt;/cache-policy&gt;<br />
&lt;cache-policy-conf&gt;<br />
&lt;min-capacity&gt;50&lt;/min-capacity&gt;<br />
&lt;max-capacity&gt;1000000&lt;/max-capacity&gt;<br />
&lt;remover-period&gt;1800&lt;/remover-period&gt;<br />
&lt;!&#8211; SFSB timeout in seconds; 1800 seconds == 30 minutes &#8211;&gt;<br />
&lt;max-bean-life&gt;1800&lt;/max-bean-life&gt;<br />
&lt;overager-period&gt;300&lt;/overager-period&gt;<br />
&lt;max-bean-age&gt;600&lt;/max-bean-age&gt;<br />
&lt;resizer-period&gt;400&lt;/resizer-period&gt;<br />
&lt;max-cache-miss-period&gt;60&lt;/max-cache-miss-period&gt;<br />
&lt;min-cache-miss-period&gt;1&lt;/min-cache-miss-period&gt;<br />
&lt;cache-load-factor&gt;0.75&lt;/cache-load-factor&gt;<br />
&lt;/cache-policy-conf&gt;<br />
&lt;/container-cache-conf&gt;</p>
<p>The default HTTP session timeout can be modified in server/default/deploy/jbosswebtomcat55.<br />
sar/conf/web.xml for JBoss 4.0.x, or in server/default/deploy/jbossweb.<br />
deployer/conf/web.xml for JBoss 4.2.x. The following entry in this file controls the default<br />
session timeout for all web applications:</p>
<p>&lt;session-config&gt;<br />
&lt;!&#8211; HTTP Session timeout, in minutes &#8211;&gt;<br />
&lt;session-timeout&gt;30&lt;/session-timeout&gt;<br />
&lt;/session-config&gt;</p>
<p>To override this value for your own application, simply include this entry in your application&#8217;s own web.xml.</p>
<p>Running Seam in a Portlet:<br />
If you want to run your Seam application in a portlet, take a look at the JBoss Portlet Bridge,<br />
an implementation of JSR-301 that supports JSF within a portlet, with extensions for Seam and RichFaces.</p>
<p>Seam annotations: When you write a Seam application, you&#8217;ll use a lot of annotations. Seam lets you use annotations<br />
to achieve a declarative style of programming. Most of the annotations you&#8217;ll use are defined by the<br />
EJB 3.0 specification. The annotations for data validation are defined by the Hibernate Validator<br />
package. Finally, Seam defines its own set of annotations.<br />
All of these annotations are defined in the package org.jboss.seam.annotations.</p>
<p>Annotations for component definition: The first group of annotations lets you define a Seam component. These annotations<br />
appear on the component class.</p>
<p>@Name<br />
@Name(&#8220;componentName&#8221;)<br />
Defines the Seam component name for a class. This annotation is required for all Seam<br />
components.<br />
@Scope<br />
@Scope(ScopeType.CONVERSATION)</p>
<p>Defines the default context of the component. The possible values are defined by the ScopeType enumeration: EVENT, PAGE,<br />
CONVERSATION, SESSION, BUSINESS_PROCESS, APPLICATION, STATELESS.</p>
<p>When no scope is explicitly specified, the default depends upon the component type. For<br />
stateless session beans, the default is STATELESS. For entity beans and stateful session<br />
beans, the default is CONVERSATION. For JavaBeans, the default is EVENT.</p>
<p>@Role<br />
@Role(name=&#8221;roleName&#8221;, scope=ScopeType.SESSION)</p>
<p>Allows a Seam component to be bound to multiple contexts variables. The @Name/@Scope<br />
annotations define a &#8220;default role&#8221;. Each @Role annotation defines an additional role.<br />
• name — the context variable name.</p>
<p>• scope — the context variable scope. When no scope is explicitly specified, the default depends upon the component type, as<br />
above.</p>
<p>@Roles<br />
@Roles({<br />
@Role(name=&#8221;user&#8221;, scope=ScopeType.CONVERSATION),<br />
@Role(name=&#8221;currentUser&#8221;, scope=ScopeType.SESSION)<br />
})</p>
<p>Allows specification of multiple additional roles.</p>
<p>@BypassInterceptors<br />
Disables Seam all interceptors on a particular component or method of a component.</p>
<p>@JndiName<br />
@JndiName(&#8220;my/jndi/name&#8221;)<br />
Specifies the JNDI name that Seam will use to look up the EJB component. If<br />
no JNDI name is explicitly specified, Seam will use the JNDI pattern specified by<br />
org.jboss.seam.core.init.jndiPattern.</p>
<p>@Conversational<br />
Specifies that a conversation scope component is conversational, meaning that no method of<br />
the component may be called unless a long-running conversation is active.</p>
<p>@PerNestedConversation<br />
Limits the scope of a CONVERSATION-scoped component to just the parent conversation<br />
in which it was instantiated. The component instance will not be visible to nested child<br />
conversations, which will get their own instance.<br />
Warning: this is ill-defined, since it implies that a component will be visible for some part of a<br />
request cycle, and invisible after that. It is not recommended that applications use this feature!</p>
<p>@Startup</p>
<p>@Scope(APPLICATION) @Startup(depends=&#8221;org.jboss.seam.bpm.jbpm&#8221;)</p>
<p>Specifies that an application scope component is started immediately at initialization time.<br />
This is mainly used for certain built-in components that bootstrap critical infrastructure such<br />
as JNDI, datasources, etc.</p>
<p>@Scope(SESSION) @Startup<br />
Specifies that a session scope component is started immediately at session creation time.<br />
• depends — specifies that the named components must be started first, if they are installed.</p>
<p>@Install(false)<br />
Specifies whether or not a component should be installed by default. The lack of an @Install<br />
annotation indicates a component should be installed.</p>
<p>@Install(dependencies=&#8221;org.jboss.seam.bpm.jbpm&#8221;)<br />
Specifies that a component should only be stalled if the components listed as dependencies are also installed.</p>
<p>@Install(genericDependencies=ManagedQueueSender.class)<br />
Specifies that a component should only be installed if a component that is implemented by a<br />
certain class is installed. This is useful when the dependency doesn&#8217;t have a single well-known<br />
name.<br />
@Install(classDependencies=&#8221;org.hibernate.Session&#8221;)<br />
Specifies that a component should only be installed if the named class is in the classpath.</p>
<p>@Install(precedence=BUILT_IN)<br />
Specifies the precedence of the component. If multiple components with the same name exist,<br />
the one with the higher precedence will be installed. The defined precendence values are (in<br />
ascending order):<br />
• BUILT_IN — Precedence of all built-in Seam components<br />
• FRAMEWORK — Precedence to use for components of frameworks which extend Seam<br />
• APPLICATION — Predence of application components (the default precedence)<br />
• DEPLOYMENT — Precedence to use for components which override application components<br />
in a particular deployment<br />
• MOCK — Precedence for mock objects used in testing<br />
@Synchronized<br />
@Synchronized(timeout=1000)<br />
Specifies that a component is accessed concurrently by multiple clients, and that Seam should<br />
serialize requests. If a request is not able to obtain its lock on the component in the given<br />
timeout period, an exception will be raised.</p>
<p>@ReadOnly<br />
Specifies that a JavaBean component or component method does not require state replication<br />
at the end of the invocation.</p>
<p>@AutoCreate<br />
Specifies that a component will be automatically created, even if the client does not specify<br />
create=true.</p>
<p>Annotations for bijection:<br />
The next two annotations control bijection. These attributes occur on component instance<br />
variables or property accessor methods.</p>
<p>@In<br />
Specifies that a component attribute is to be injected from a context variable at the beginning<br />
of each component invocation. If the context variable is null, an exception will be thrown.<br />
@In(required=false)<br />
Specifies that a component attribute is to be injected from a context variable at the beginning<br />
of each component invocation. The context variable may be null.<br />
@In(create=true)<br />
Specifies that a component attribute is to be injected from a context variable at the beginning<br />
of each component invocation. If the context variable is null, an instance of the component<br />
is instantiated by Seam.</p>
<p>@In(value=&#8221;contextVariableName&#8221;)<br />
Specifies the name of the context variable explicitly, instead of using the annotated instance<br />
variable name.<br />
@In(value=&#8221;#{customer.addresses['shipping']}&#8221;)<br />
Specifies that a component attribute is to be injected by evaluating a JSF EL expression at<br />
the beginning of each component invocation.<br />
• value — specifies the name of the context variable. Default to the name of the component<br />
attribute. Alternatively, specifies a JSF EL expression, surrounded by #{&#8230;}.<br />
• create — specifies that Seam should instantiate the component with the same name as<br />
the context variable if the context variable is undefined (null) in all contexts. Default to false.<br />
• required — specifies Seam should throw an exception if the context variable is undefined<br />
in all contexts.<br />
@Out<br />
Specifies that a component attribute that is a Seam component is to be outjected to its context<br />
variable at the end of the invocation. If the attribute is null, an exception is thrown.<br />
@Out(required=false)<br />
Specifies that a component attribute that is a Seam component is to be outjected to its context<br />
variable at the end of the invocation. The attribute may be null.<br />
@Out(scope=ScopeType.SESSION)<br />
Specifies that a component attribute that is not a Seam component type is to be outjected to<br />
a specific scope at the end of the invocation.<br />
Alternatively, if no scope is explicitly specified, the scope of the component with the @Out<br />
attribute is used (or the EVENT scope if the component is stateless).<br />
@Out(value=&#8221;contextVariableName&#8221;)<br />
Specifies the name of the context variable explicitly, instead of using the annotated instance<br />
variable name.<br />
• value — specifies the name of the context variable. Default to the name of the component<br />
attribute.<br />
• required — specifies Seam should throw an exception if the component attribute is null<br />
during outjection.<br />
Note that it is quite common for these annotations to occur together, for example:<br />
@In(create=true) @Out private User currentUser;<br />
The next annotation supports the manager component pattern, where a Seam component that<br />
manages the lifecycle of an instance of some other class that is to be injected. It appears on a<br />
component getter method.<br />
@Unwrap<br />
Specifies that the object returned by the annotated getter method is the thing that is injected<br />
instead of the component instance itself.<br />
The next annotation supports the factory component pattern, where a Seam component is<br />
responsible for initializing the value of a context variable. This is especially useful for initializing<br />
any state needed for rendering the response to a non-faces request. It appears on a component<br />
method.<br />
@Factory<br />
@Factory(&#8220;processInstance&#8221;) public void createProcessInstance() { &#8230; }<br />
Specifies that the method of the component is used to initialize the value of the named context<br />
variable, when the context variable has no value. This style is used with methods that return<br />
void.<br />
@Factory(&#8220;processInstance&#8221;, scope=CONVERSATION) public ProcessInstance<br />
createProcessInstance() { &#8230; }<br />
Specifies that the method returns a value that Seam should use to initialize the value of<br />
the named context variable, when the context variable has no value. This style is used with<br />
methods that return a value. If no scope is explicitly specified, the scope of the component with<br />
the @Factory method is used (unless the component is stateless, in which case the EVENT<br />
context is used).<br />
• value — specifies the name of the context variable. If the method is a getter method, default<br />
to the JavaBeans property name.<br />
• scope — specifies the scope that Seam should bind the returned value to. Only meaningful<br />
for factory methods which return a value.<br />
• autoCreate — specifies that this factory method should be automatically called whenever<br />
the variable is asked for, even if @In does not specify create=true.<br />
This annotation lets you inject a Log:<br />
@Logger(&#8220;categoryName&#8221;)<br />
Specifies that a component field is to be injected with an instance of<br />
org.jboss.seam.log.Log. For entity beans, the field must be declared as static.<br />
• value — specifies the name of the log category. Default to the name of the component<br />
class.<br />
The last annotation lets you inject a request parameter value:<br />
@RequestParameter<br />
@RequestParameter(&#8220;parameterName&#8221;)<br />
Specifies that a component attribute is to be injected with the value of a request parameter.<br />
Basic type conversions are performed automatically.<br />
• value — specifies the name of the request parameter. Default to the name of the<br />
component attribute.</p>
<p>Annotations for component lifecycle methods:<br />
These annotations allow a component to react to its own lifecycle events. They occur on methods<br />
of the component. There may be only one of each per component class.<br />
@Create<br />
@Create<br />
Specifies that the method should be called when an instance of the component is instantiated<br />
by Seam. Note that create methods are only supported for JavaBeans and stateful session<br />
beans.</p>
<p>@Destroy<br />
Specifies that the method should be called when the context ends and its context variables are<br />
destroyed. Note that destroy methods are only supported for JavaBeans and stateful session<br />
beans.<br />
Destroy methods should be used only for cleanup. Seam catches, logs and swallows any<br />
exception that propagates out of a destroy method.<br />
@Observer<br />
@Observer(&#8220;somethingChanged&#8221;)<br />
Specifies that the method should be called when a component-driven event of the specified<br />
type occurs.<br />
@Observer(value=&#8221;somethingChanged&#8221;,create=false)<br />
Specifies that the method should be called when an event of the specified type occurs but<br />
that an instance should not be created if one doesn&#8217;t exist. If an instance does not exist and<br />
create is false, the event will not be observed. The default value for create is true.</p>
<p>Annotations for context demarcation:<br />
These annotations provide declarative conversation demarcation. They appear on methods of<br />
Seam components, usually action listener methods.<br />
Every web request has a conversation context associated with it. Most of these conversations<br />
end at the end of the request. If you want a conversation that span multiple requests, you must<br />
&#8220;promote&#8221; the current conversation to a long-running conversation by calling a method marked<br />
with @Begin.</p>
<p>@Begin<br />
Specifies that a long-running conversation begins when this method returns a non-null<br />
outcome without exception.<br />
@Begin(join=true)<br />
Specifies that if a long-running conversation is already in progress, the conversation context<br />
is simply propagated.<br />
@Begin(nested=true)<br />
Specifies that if a long-running conversation is already in progress, a new nested conversation<br />
context begins. The nested conversation will end when the next @End is encountered, and the<br />
outer conversation will resume. It is perfectly legal for multiple nested conversations to exist<br />
concurrently in the same outer conversation.<br />
@Begin(pageflow=&#8221;process definition name&#8221;)<br />
Specifies a jBPM process definition name that defines the pageflow for this conversation.<br />
@Begin(flushMode=FlushModeType.MANUAL)<br />
Specify the flush mode of any Seam-managed persistence contexts.<br />
flushMode=FlushModeType.MANUAL supports the use of atomic conversations where all write<br />
operations are queued in the conversation context until an explicit call to flush() (which<br />
usually occurs at the end of the conversation).<br />
• join — determines the behavior when a long-running conversation is already in progress.<br />
If true, the context is propagated. If false, an exception is thrown. Default to false. This<br />
setting is ignored when nested=true is specified.<br />
• nested — specifies that a nested conversation should be started if a long-running<br />
conversation is already in progress.<br />
• flushMode — set the flush mode of any Seam-managed Hibernate sessions or JPA<br />
persistence contexts that are created during this conversation.<br />
• pageflow — a process definition name of a jBPM process definition deployed via<br />
org.jboss.seam.bpm.jbpm.pageflowDefinitions.<br />
@End<br />
@End<br />
Specifies that a long-running conversation ends when this method returns a non-null outcome<br />
without exception.<br />
• beforeRedirect — by default, the conversation will not actually be destroyed until after<br />
any redirect has occurred. Setting beforeRedirect=true specifies that the conversation<br />
should be destroyed at the end of the current request, and that the redirect will be processed<br />
in a new temporary conversation context.<br />
@StartTask<br />
&#8220;Starts&#8221; a jBPM task. Specifies that a long-running conversation begins when this method<br />
returns a non-null outcome without exception. This conversation is associated with the jBPM<br />
task specified in the named request parameter. Within the context of this conversation, a<br />
business process context is also defined, for the business process instance of the task<br />
instance.<br />
• The jBPM TaskInstance will be available in a request context variable named<br />
taskInstance. The jPBM ProcessInstance will be available in a request context variable<br />
named processInstance. (Of course, these objects are available for injection via @In.)<br />
• taskIdParameter — the name of a request parameter which holds the id of the task. Default<br />
to &#8220;taskId&#8221;, which is also the default used by the Seam taskList JSF component.<br />
• flushMode — set the flush mode of any Seam-managed Hibernate sessions or JPA<br />
persistence contexts that are created during this conversation.<br />
@BeginTask<br />
Resumes work on an incomplete jBPM task. Specifies that a long-running conversation<br />
begins when this method returns a non-null outcome without exception. This conversation is<br />
associated with the jBPM task specified in the named request parameter. Within the context<br />
of this conversation, a business process context is also defined, for the business process<br />
instance of the task instance.<br />
• The jBPM org.jbpm.taskmgmt.exe.TaskInstance will be available in a request context<br />
variable named taskInstance. The jPBM org.jbpm.graph.exe.ProcessInstance will be<br />
available in a request context variable named processInstance.<br />
• taskIdParameter — the name of a request parameter which holds the id of the task. Default<br />
to &#8220;taskId&#8221;, which is also the default used by the Seam taskList JSF component.<br />
• flushMode — set the flush mode of any Seam-managed Hibernate sessions or JPA<br />
persistence contexts that are created during this conversation.<br />
@EndTask<br />
&#8220;Ends&#8221; a jBPM task. Specifies that a long-running conversation ends when this method<br />
returns a non-null outcome, and that the current task is complete. Triggers a jBPM transition.<br />
The actual transition triggered will be the default transition unless the application has called<br />
Transition.setName() on the built-in component named transition.<br />
@EndTask(transition=&#8221;transitionName&#8221;)<br />
Triggers the given jBPM transition.<br />
• transition — the name of the jBPM transition to be triggered when ending the task.<br />
Defaults to the default transition.<br />
• beforeRedirect — by default, the conversation will not actually be destroyed until after<br />
any redirect has occurred. Setting beforeRedirect=true specifies that the conversation<br />
should be destroyed at the end of the current request, and that the redirect will be processed<br />
in a new temporary conversation context.<br />
@CreateProcess<br />
@CreateProcess(definition=&#8221;process definition name&#8221;)<br />
Creates a new jBPM process instance when the method returns a non-null outcome without<br />
exception. The ProcessInstance object will be available in a context variable named<br />
processInstance.<br />
• definition — the name of the jBPM process definition deployed via<br />
org.jboss.seam.bpm.jbpm.processDefinitions.<br />
@ResumeProcess<br />
@ResumeProcess(processIdParameter=&#8221;processId&#8221;)<br />
Re-enters the scope of an existing jBPM process instance when the method returns a nonnull<br />
outcome without exception. The ProcessInstance object will be available in a context<br />
variable named processInstance.<br />
• processIdParameter — the name a request parameter holding the process id. Default to<br />
&#8220;processId&#8221;.<br />
@Transition<br />
@Transition(&#8220;cancel&#8221;)<br />
Marks a method as signalling a transition in the current jBPM process instance whenever the<br />
method returns a non-null result.</p>
<p>Annotations for use with Seam JavaBean components in a J2EE environment: Seam provides an annotation that lets you force a<br />
rollback of the JTA transaction for certain action listener outcomes.</p>
<p>@Transactional<br />
Specifies that a JavaBean component should have a similar transactional behavior to the<br />
default behavior of a session bean component. ie. method invocations should take place in<br />
a transaction, and if no transaction exists when the method is called, a transaction will be<br />
started just for that method. This annotation may be applied at either class or method level.<br />
Do not use this annotation on EJB 3.0 components, use @TransactionAttribute!</p>
<p>@ApplicationException<br />
Synonym for javax.ejb.ApplicationException, for use in a pre Java EE 5 environment. Applied<br />
to an exception to denote that it is an application exception and should be reported to the<br />
client directly(i.e., unwrapped).<br />
Do not use this annotation on EJB 3.0 components, use<br />
@javax.ejb.ApplicationException instead.<br />
• rollback — by default false, if true this exception should set the transaction to rollback<br />
only<br />
• end — by default false, if true this exception should end the current long-running<br />
conversation</p>
<p>@Interceptors<br />
@Interceptors({DVDInterceptor, CDInterceptor})<br />
Synonym for javax.interceptors.Interceptors, for use in a pre Java EE 5 environment. Note<br />
that this may only be used as a meta-annotation. Declares an ordered list of interceptors for<br />
a class or method.<br />
Do not use this annotations on EJB 3.0 components, use<br />
@javax.interceptor.Interceptors instead.<br />
These annotations are mostly useful for JavaBean Seam components. If you use EJB 3.0<br />
components, you should use the standard Java EE5 annotation.</p>
<p>Annotations for exceptions: These annotations let you specify how Seam should handle an exception that propagates out of<br />
a Seam component.<br />
@Redirect<br />
@Redirect(viewId=&#8221;error.jsp&#8221;)<br />
Specifies that the annotated exception causes a browser redirect to a specified view id.<br />
• viewId — specifies the JSF view id to redirect to. You can use EL here.<br />
• message — a message to be displayed, default to the exception message.<br />
• end — specifies that the long-running conversation should end, default to false.<br />
@HttpError<br />
@HttpError(errorCode=404)<br />
Specifies that the annotated exception causes a HTTP error to be sent.<br />
• errorCode — the HTTP error code, default to 500.<br />
• message — a message to be sent with the HTTP error, default to the exception message.<br />
• end — specifies that the long-running conversation should end, default to false.</p>
<p>Annotations for Seam Remoting:<br />
Seam Remoting requires that the local interface of a session bean be annotated with the following annotation:<br />
@WebRemote<br />
@WebRemote(exclude=&#8221;path.to.exclude&#8221;)<br />
Indicates that the annotated method may be called from client-side JavaScript. The exclude<br />
property is optional and allows objects to be excluded from the result&#8217;s object graph (see the<br />
Remoting chapter for more details).</p>
<p>Annotations for Seam interceptors:<br />
The following annotations appear on Seam interceptor classes.<br />
Please refer to the documentation for the EJB 3.0 specification for information about the<br />
annotations required for EJB interceptor definition.<br />
@Interceptor<br />
@Interceptor(stateless=true)<br />
Specifies that this interceptor is stateless and Seam may optimize replication.<br />
@Interceptor(type=CLIENT)<br />
Specifies that this interceptor is a &#8220;client-side&#8221; interceptor that is called before the EJB<br />
container.<br />
@Interceptor(around={SomeInterceptor.class, OtherInterceptor.class})<br />
Specifies that this interceptor is positioned higher in the stack than the given interceptors.<br />
@Interceptor(within={SomeInterceptor.class, OtherInterceptor.class})<br />
Specifies that this interceptor is positioned deeper in the stack than the given interceptors.<br />
Annotations for asynchronicity:<br />
The following annotations are used to declare an asynchronous method, for example:<br />
@Asynchronous public void scheduleAlert(Alert alert, @Expiration Date date) { &#8230; }<br />
@Asynchronous public Timer scheduleAlerts(Alert alert,<br />
@Expiration Date date,<br />
@IntervalDuration long interval) { &#8230; }<br />
@Asynchronous<br />
@Asynchronous<br />
Specifies that the method call is processed asynchronously.<br />
@Duration<br />
@Duration<br />
Specifies that a parameter of the asynchronous call is the duration before the call is processed<br />
(or first processed for recurring calls).<br />
@Expiration<br />
@Expiration<br />
Specifies that a parameter of the asynchronous call is the datetime at which the call is<br />
processed (or first processed for recurring calls).<br />
@IntervalDuration<br />
@IntervalDuration<br />
Specifies that an asynchronous method call recurs, and that the annotationed parameter is<br />
duration between recurrences.</p>
<p>Annotations for use with JSF:<br />
The following annotations make working with JSF easier.<br />
@Converter<br />
Allows a Seam component to act as a JSF converter. The annotated class must be a Seam<br />
component, and must implement javax.faces.convert.Converter.<br />
• id — the JSF converter id. Defaults to the component name.<br />
• forClass — if specified, register this component as the default converter for a type.<br />
@Validator<br />
Allows a Seam component to act as a JSF validator. The annotated class must be a Seam<br />
component, and must implement javax.faces.validator.Validator.<br />
• id — the JSF validator id. Defaults to the component name.<br />
27.10.1. Annotations for use with dataTable<br />
The following annotations make it easy to implement clickable lists backed by a stateful session<br />
bean. They appear on attributes.<br />
@DataModel<br />
@DataModel(&#8220;variableName&#8221;)<br />
Outjects a property of type List, Map, Set or Object[] as a JSF DataModel into the scope<br />
of the owning component (or the EVENT scope if the owning component is STATELESS). In the<br />
case of Map, each row of the DataModel is a Map.Entry.<br />
• value — name of the conversation context variable. Default to the attribute name.<br />
• scope — if scope=ScopeType.PAGE is explicitly specified, the DataModel will be kept in the<br />
PAGE context.<br />
@DataModelSelection<br />
@DataModelSelection<br />
Injects the selected value from the JSF DataModel (this is the element of the underlying<br />
collection, or the map value). If only one @DataModel attribute is defined for a component, the<br />
selected value from that DataModel will be injected. Otherwise, the component name of each<br />
@DataModel must be specified in the value attribute for each @DataModelSelection.<br />
If PAGE scope is specified on the associated @DataModel, then, in addition to the DataModel<br />
Selection being injected, the associated DataModel will also be injected. In this case, if the<br />
property annotated with @DataModel is a getter method, then a setter method for the property<br />
must also be part of the Business API of the containing Seam Component.<br />
• value — name of the conversation context variable. Not needed if there is exactly one<br />
@DataModel in the component.<br />
@DataModelSelectionIndex<br />
@DataModelSelectionIndex<br />
Exposes the selection index of the JSF DataModel as an attribute of the component (this is the<br />
row number of the underlying collection, or the map key). If only one @DataModel attribute is<br />
defined for a component, the selected value from that DataModel will be injected. Otherwise,<br />
the component name of each @DataModel must be specified in the value attribute for each<br />
@DataModelSelectionIndex.<br />
• value — name of the conversation context variable. Not needed if there is exactly one<br />
@DataModel in the component.<br />
Meta-annotations for databinding<br />
These meta-annotations make it possible to implement similar functionality to @DataModel and<br />
@DataModelSelection for other datastructures apart from lists.<br />
@DataBinderClass<br />
@DataBinderClass(DataModelBinder.class)<br />
Specifies that an annotation is a databinding annotation.<br />
@DataSelectorClass<br />
@DataSelectorClass(DataModelSelector.class)<br />
Specifies that an annotation is a dataselection annotation.</p>
<p>Annotations for packaging:<br />
This annotation provides a mechanism for declaring information about a set of components that<br />
are packaged together. It can be applied to any Java package.<br />
@Namespace<br />
@Namespace(value=&#8221;http://jboss.com/products/seam/example/seampay&#8221;)<br />
Specifies that components in the current package are associated with the given namespace.<br />
The declared namespace can be used as an XML namespace in a components.xml file to<br />
simplify application configuration.<br />
@Namespace(value=&#8221;http://jboss.com/products/seam/core&#8221;, prefix=&#8221;org.jboss.seam.core&#8221;)<br />
Specifies a namespace to associate with a given package. Additionally, it specifies a<br />
component name prefix to be applied to component names specified in the XML file. For<br />
example, an XML element named init that is associated with this namespace would be<br />
understood to actually refer to a component named org.jboss.seam.core.init.</p>
<p>Annotations for integrating with the servlet container:<br />
These annotations allow you to integrate your Seam components with the servlet container.<br />
@Filter<br />
Use the Seam component (which implements javax.servlet.Filter) annotated with<br />
@Filter as a servlet filter. It will be executed by Seam&#8217;s master filter.<br />
•<br />
@Filter(around={&#8220;seamComponent&#8221;, &#8220;otherSeamComponent&#8221;})<br />
Specifies that this filter is positioned higher in the stack than the given filters.<br />
•<br />
@Filter(within={&#8220;seamComponent&#8221;, &#8220;otherSeamComponent&#8221;})<br />
Specifies that this filter is positioned deeper in the stack than the given filters.</p>
<p>Seam JSF controls: Seam includes a number of JSF controls that are useful for working with Seam. These are<br />
intended to complement the built-in JSF controls, and controls from other third-party libraries. We<br />
recommend JBoss RichFaces, and Apache MyFaces Trinidad tag libraries for use with Seam. We<br />
do not recommend the use of the Tomahawk tag library.<br />
29.1. Tags<br />
To use these tags, define the &#8220;s&#8221; namespace in your page as follows (facelets only):<br />
&lt;html xmlns=&#8221;http://www.w3.org/1999/xhtml&#8221;<br />
xmlns:s=&#8221;http://jboss.com/products/seam/taglib&#8221;&gt;<br />
The ui example demonstrates the use of a number of these tags.<br />
29.1.1. Navigation Controls<br />
29.1.1.1. &lt;s:button&gt;<br />
Description<br />
A button that supports invocation of an action with control over conversation propagation. Does<br />
not submit the form.<br />
Attributes<br />
• value — the label.<br />
• action — a method binding that specified the action listener.<br />
• view — the JSF view id to link to.<br />
• fragment — the fragment identifier to link to.<br />
• disabled — is the link disabled?<br />
• propagation — determines the conversation propagation style: begin, join, nest, none or<br />
end.<br />
• pageflow — a pageflow definition to begin. (This is only useful when propagation=&#8221;begin&#8221;<br />
or propagation=&#8221;join&#8221; is used).<br />
Usage<br />
&lt;s:button id=&#8221;cancel&#8221;<br />
Chapter 29. Seam JSF controls<br />
408<br />
value=&#8221;Cancel&#8221;<br />
action=&#8221;#{hotelBooking.cancel}&#8221;/&gt;<br />
You can specify both view and action on &lt;s:link /&gt;. In this case, the action wil be called once<br />
the redirect to the specified view has occured.<br />
29.1.1.2. &lt;s:conversationId&gt;<br />
Description<br />
Add the conversation id to JSF link or button (e.g. &lt;h:commandLink /&gt; , &lt;s:button /&gt;).<br />
Attributes<br />
None<br />
29.1.1.3. &lt;s:taskId&gt;<br />
Description<br />
Add the task id to an output link (or similar JSF control), when the task is available via #{task}.<br />
Attributes<br />
None.<br />
29.1.1.4. &lt;s:link&gt;<br />
Description<br />
A link that supports invocation of an action with control over conversation propagation. Does not<br />
submit the form.<br />
Attributes<br />
• value — the label.<br />
• action — a method binding that specified the action listener.<br />
• view — the JSF view id to link to.<br />
• fragment — the fragment identifier to link to.<br />
• disabled — is the link disabled?<br />
• propagation — determines the conversation propagation style: begin, join, nest, none or<br />
end.<br />
• pageflow — a pageflow definition to begin. (This is only useful when using<br />
propagation=&#8221;begin&#8221; or propagation=&#8221;join&#8221;.)<br />
Navigation Controls<br />
409<br />
Usage<br />
&lt;s:link id=&#8221;register&#8221; view=&#8221;/register.xhtml&#8221;<br />
value=&#8221;Register New User&#8221;/&gt;<br />
You can specify both view and action on &lt;s:link /&gt;. In this case, the action will be called once<br />
the redirect to the specified view has occured.<br />
29.1.1.5. &lt;s:conversationPropagation&gt;<br />
Description<br />
Customize the conversation propagation for a command link or button (or similar JSF control).<br />
Facelets only.<br />
Attributes<br />
• type — determines the conversation propagation style: begin, join, nest, none or end.<br />
• pageflow — a pageflow definition to begin. (This is only useful when using<br />
propagation=&#8221;begin&#8221; or propagation=&#8221;join&#8221;.)<br />
Usage<br />
&lt;h:commandButton value=&#8221;Apply&#8221; action=&#8221;#{personHome.update}&#8221;&gt;<br />
&lt;s:conversationPropagation type=&#8221;join&#8221; /&gt;<br />
&lt;/h:commandButton&gt;<br />
29.1.1.6. &lt;s:defaultAction&gt;<br />
Description<br />
Specify the default action to run when the form is submitted using the enter key.<br />
Currently you can only nest it inside buttons (e.g. &lt;h:commandButton /&gt;, &lt;a:commandButton /&gt;<br />
or &lt;tr:commandButton /&gt;).<br />
You must specify an id on the action source. You can only have one default action per form.<br />
Attributes<br />
None.<br />
Usage<br />
&lt;h:commandButton id=&#8221;foo&#8221; value=&#8221;Foo&#8221; action=&#8221;#{manager.foo}&#8221;&gt;<br />
Chapter 29. Seam JSF controls<br />
410<br />
&lt;s:defaultAction /&gt;<br />
&lt;/h:commandButton&gt;<br />
29.1.2. Converters and Validators<br />
29.1.2.1. &lt;s:convertDateTime&gt;<br />
Description<br />
Perform date or time conversions in the Seam timezone.<br />
Attributes<br />
None.<br />
Usage<br />
&lt;h:outputText value=&#8221;#{item.orderDate}&#8221;&gt;<br />
&lt;s:convertDateTime type=&#8221;both&#8221; dateStyle=&#8221;full&#8221;/&gt;<br />
&lt;/h:outputText&gt;<br />
29.1.2.2. &lt;s:convertEntity&gt;<br />
Description<br />
Assigns an entity converter to the current component. This is primarily useful for radio button and<br />
dropdown controls.<br />
The converter works with any managed entity which has an @Id annotation &#8211; either simple or<br />
composite.<br />
Attributes<br />
None.<br />
Configuration<br />
You must use Seam managed transactions (see Section 9.2, “Seam managed transactions”) with<br />
&lt;s:convertEntity /&gt;.<br />
If your Managed Persistence Context isn&#8217;t called entityManager, then you need to set it in<br />
components.xml:<br />
&lt;component name=&#8221;org.jboss.seam.ui.EntityConverter&#8221;&gt;<br />
&lt;property name=&#8221;entityManager&#8221;&gt;#{em}&lt;/property&gt;<br />
Converters and Validators<br />
411<br />
&lt;/component&gt;<br />
If you are using a Managed Hibernate Session then you need to set it in components.xml:<br />
&lt;component name=&#8221;org.jboss.seam.ui.EntityConverter&#8221;&gt;<br />
&lt;property name=&#8221;session&#8221;&gt;#{hibernateSession}&lt;/property&gt;<br />
&lt;/component&gt;<br />
If you want to use more than one entity manager with the entity converter, you can create a copy<br />
of the entity converter for each entity manager in components.xml:<br />
&lt;component name=&#8221;myEntityConverter&#8221;&gt;<br />
&lt;property name=&#8221;entityManager&#8221;&gt;#{em}&lt;/property&gt;<br />
&lt;/component&gt;<br />
&lt;h:selectOneMenu value=&#8221;#{person.continent}&#8221;&gt;<br />
&lt;s:selectItems value=&#8221;#{continents.resultList}&#8221; var=&#8221;continent&#8221;<br />
label=&#8221;#{continent.name}&#8221; /&gt;<br />
&lt;f:converter converterId=&#8221;myEntityConverter&#8221; /&gt;<br />
&lt;/h:selectOneMenu&gt;<br />
Usage<br />
&lt;h:selectOneMenu value=&#8221;#{person.continent}&#8221; required=&#8221;true&#8221;&gt;<br />
&lt;s:selectItems value=&#8221;#{continents.resultList}&#8221; var=&#8221;continent&#8221;<br />
label=&#8221;#{continent.name}&#8221;<br />
noSelectionLabel=&#8221;Please Select&#8230;&#8221;/&gt;<br />
&lt;s:convertEntity /&gt;<br />
&lt;/h:selectOneMenu&gt;<br />
29.1.2.3. &lt;s:convertEnum&gt;<br />
Description<br />
Assigns an enum converter to the current component. This is primarily useful for radio button and<br />
dropdown controls.<br />
Attributes<br />
None.<br />
Chapter 29. Seam JSF controls<br />
412<br />
Usage<br />
&lt;h:selectOneMenu value=&#8221;#{person.honorific}&#8221;&gt;<br />
&lt;s:selectItems value=&#8221;#{honorifics}&#8221; var=&#8221;honorific&#8221;<br />
label=&#8221;#{honorific.label}&#8221;<br />
noSelectionLabel=&#8221;Please select&#8221; /&gt;<br />
&lt;s:convertEnum /&gt;<br />
&lt;/h:selectOneMenu&gt;<br />
29.1.2.4. &lt;s:validate&gt;<br />
Description<br />
A non-visual control, validates a JSF input field against the bound property using Hibernate<br />
Validator.<br />
Attributes<br />
None.<br />
Usage<br />
&lt;h:inputText id=&#8221;userName&#8221; required=&#8221;true&#8221;<br />
value=&#8221;#{customer.userName}&#8221;&gt;<br />
&lt;s:validate /&gt;<br />
&lt;/h:inputText&gt;<br />
&lt;h:message for=&#8221;userName&#8221; styleClass=&#8221;error&#8221; /&gt;<br />
29.1.2.5. &lt;s:validateAll&gt;<br />
Description<br />
A non-visual control, validates all child JSF input fields against their bound properties using<br />
Hibernate Validator.<br />
Attributes<br />
None.<br />
Usage<br />
&lt;s:validateAll&gt;<br />
&lt;div&gt;<br />
&lt;h:outputLabel for=&#8221;username&#8221;&gt;Username:&lt;/h:outputLabel&gt;<br />
Formatting<br />
413<br />
&lt;h:inputText id=&#8221;username&#8221; value=&#8221;#{user.username}&#8221;<br />
required=&#8221;true&#8221;/&gt;<br />
&lt;h:message for=&#8221;username&#8221; styleClass=&#8221;error&#8221; /&gt;<br />
&lt;/div&gt;<br />
&lt;div&gt;<br />
&lt;h:outputLabel for=&#8221;password&#8221;&gt;Password:&lt;/h:outputLabel&gt;<br />
&lt;h:inputSecret id=&#8221;password&#8221; value=&#8221;#{user.password}&#8221;<br />
required=&#8221;true&#8221;/&gt;<br />
&lt;h:message for=&#8221;password&#8221; styleClass=&#8221;error&#8221; /&gt;<br />
&lt;/div&gt;<br />
&lt;div&gt;<br />
&lt;h:outputLabel for=&#8221;verify&#8221;&gt;Verify Password:&lt;/h:outputLabel&gt;<br />
&lt;h:inputSecret id=&#8221;verify&#8221; value=&#8221;#{register.verify}&#8221;<br />
required=&#8221;true&#8221;/&gt;<br />
&lt;h:message for=&#8221;verify&#8221; styleClass=&#8221;error&#8221; /&gt;<br />
&lt;/div&gt;<br />
&lt;/s:validateAll&gt;<br />
29.1.3. Formatting<br />
29.1.3.1. &lt;s:decorate&gt;<br />
Description<br />
&#8220;Decorate&#8221; a JSF input field when validation fails or when required=&#8221;true&#8221; is set.<br />
Attributes<br />
• template — the facelets template to use to decorate the component<br />
#{invalid} and #{required} are available inside s:decorate; #{required} evaluates to true<br />
if you have set the input component being decorated as required, and #{invalid} evaluates to<br />
true if a validation error occurs.<br />
Usage<br />
&lt;s:decorate template=&#8221;edit.xhtml&#8221;&gt;<br />
&lt;ui:define name=&#8221;label&#8221;&gt;Country:&lt;/ui:define&gt;<br />
&lt;h:inputText value=&#8221;#{location.country}&#8221; required=&#8221;true&#8221;/&gt;<br />
&lt;/s:decorate&gt;<br />
&lt;ui:composition xmlns=&#8221;http://www.w3.org/1999/xhtml&#8221;<br />
xmlns:ui=&#8221;http://java.sun.com/jsf/facelets&#8221;<br />
Chapter 29. Seam JSF controls<br />
414<br />
xmlns:h=&#8221;http://java.sun.com/jsf/html&#8221;<br />
xmlns:f=&#8221;http://java.sun.com/jsf/core&#8221;<br />
xmlns:s=&#8221;http://jboss.com/products/seam/taglib&#8221;&gt;<br />
&lt;div&gt;<br />
&lt;s:label styleClass=&#8221;#{invalid?&#8217;error&#8217;:&#8221;}&#8221;&gt;<br />
&lt;ui:insert name=&#8221;label&#8221;/&gt;<br />
&lt;s:span styleClass=&#8221;required&#8221; rendered=&#8221;#{required}&#8221;&gt;*&lt;/s:span&gt;<br />
&lt;/s:label&gt;<br />
&lt;span&gt;<br />
&lt;s:validateAll&gt;<br />
&lt;ui:insert/&gt;<br />
&lt;/s:validateAll&gt;<br />
&lt;/span&gt;<br />
&lt;s:message styleClass=&#8221;error&#8221;/&gt;<br />
&lt;/div&gt;<br />
&lt;/ui:composition&gt;<br />
29.1.3.2. &lt;s:div&gt;<br />
Description<br />
Render a HTML &lt;div&gt;.<br />
Attributes<br />
None.<br />
Usage<br />
&lt;s:div rendered=&#8221;#{selectedMember == null}&#8221;&gt;<br />
Sorry, but this member does not exist.<br />
&lt;/s:div&gt;<br />
29.1.3.3. &lt;s:span&gt;<br />
Description<br />
Render a HTML &lt;span&gt;.<br />
Formatting<br />
415<br />
Attributes<br />
None.<br />
Usage<br />
&lt;s:span styleClass=&#8221;required&#8221; rendered=&#8221;#{required}&#8221;&gt;*&lt;/s:span&gt;<br />
29.1.3.4. &lt;s:fragment&gt;<br />
Description<br />
A non-rendering component useful for enabling/disabling rendering of it&#8217;s children.<br />
Attributes<br />
None.<br />
Usage<br />
&lt;s:fragment rendered=&#8221;#{auction.highBidder ne null}&#8221;&gt;<br />
Current bid:<br />
&lt;/s:fragment&gt;<br />
29.1.3.5. &lt;s:label&gt;<br />
Description<br />
&#8220;Decorate&#8221; a JSF input field with the label. The label is placed inside the HTML &lt;label&gt; tag, and<br />
is associated with the nearest JSF input component. It is often used with &lt;s:decorate&gt;.<br />
Attributes<br />
• style — The control&#8217;s style<br />
• styleClass — The control&#8217;s style class<br />
Usage<br />
&lt;s:label styleClass=&#8221;label&#8221;&gt;<br />
Country:<br />
&lt;/s:label&gt;<br />
&lt;h:inputText value=&#8221;#{location.country}&#8221; required=&#8221;true&#8221;/&gt;<br />
Chapter 29. Seam JSF controls<br />
416<br />
29.1.3.6. &lt;s:message&gt;<br />
Description<br />
&#8220;Decorate&#8221; a JSF input field with the validation error message.<br />
Attributes<br />
None.<br />
Usage<br />
&lt;f:facet name=&#8221;afterInvalidField&#8221;&gt;<br />
&lt;s:span&gt;<br />
&#160;Error:&#160;<br />
&lt;s:message/&gt;<br />
&lt;/s:span&gt;<br />
&lt;/f:facet&gt;<br />
29.1.4. Seam Text<br />
29.1.4.1. &lt;s:validateFormattedText&gt;<br />
Description<br />
Checks that the submitted value is valid Seam Text<br />
Attributes<br />
None.<br />
29.1.4.2. &lt;s:formattedText&gt;<br />
Description<br />
Outputs Seam Text, a rich text markup useful for blogs, wikis and other applications that might<br />
use rich text. See the Seam Text chapter for full usage.<br />
Attributes<br />
• value — an EL expression specifying the rich text markup to render.<br />
Usage<br />
&lt;s:formattedText value=&#8221;#{blog.text}&#8221;/&gt;</p>
<p>Dropdowns<br />
29.1.5.1. &lt;s:enumItem&gt;<br />
Description<br />
Creates a SelectItem from an enum value.<br />
Attributes<br />
• enumValue — the string representation of the enum value.<br />
• label — the label to be used when rendering the SelectItem.<br />
Usage<br />
&lt;h:selectOneRadio id=&#8221;radioList&#8221;<br />
layout=&#8221;lineDirection&#8221;<br />
value=&#8221;#{newPayment.paymentFrequency}&#8221;&gt;<br />
&lt;s:convertEnum /&gt;<br />
Chapter 29. Seam JSF controls<br />
418<br />
&lt;s:enumItem enumValue=&#8221;ONCE&#8221; label=&#8221;Only Once&#8221; /&gt;<br />
&lt;s:enumItem enumValue=&#8221;EVERY_MINUTE&#8221; label=&#8221;Every Minute&#8221; /&gt;<br />
&lt;s:enumItem enumValue=&#8221;HOURLY&#8221; label=&#8221;Every Hour&#8221; /&gt;<br />
&lt;s:enumItem enumValue=&#8221;DAILY&#8221; label=&#8221;Every Day&#8221; /&gt;<br />
&lt;s:enumItem enumValue=&#8221;WEEKLY&#8221; label=&#8221;Every Week&#8221; /&gt;<br />
&lt;/h:selectOneRadio&gt;<br />
29.1.5.2. &lt;s:selectItems&gt;<br />
Description<br />
Creates a List&lt;SelectItem&gt; from a List, Set, DataModel or Array.<br />
Attributes<br />
• value — an EL expression specifying the data that backs the List&lt;SelectItem&gt;<br />
• var— defines the name of the local variable that holds the current object during iteration<br />
• label — the label to be used when rendering the SelectItem. Can reference the var variable.<br />
• itemValue — Value to return to the server if this option is selected. Optional, by default the var<br />
object is used. Can reference the var variable.<br />
• disabled — if true the SelectItem will be rendered disabled. Can reference the var variable.<br />
• noSelectionLabel — specifies the (optional) label to place at the top of list (if<br />
required=&#8221;true&#8221; is also specified then selecting this value will cause a validation error).<br />
• hideNoSelectionLabel — if true, the noSelectionLabel will be hidden when a value is<br />
selected<br />
Usage<br />
&lt;h:selectOneMenu value=&#8221;#{person.age}&#8221;<br />
converter=&#8221;ageConverter&#8221;&gt;<br />
&lt;s:selectItems value=&#8221;#{ages}&#8221; var=&#8221;age&#8221; label=&#8221;#{age}&#8221; /&gt;<br />
&lt;/h:selectOneMenu&gt;<br />
29.1.6. Other<br />
29.1.6.1. &lt;s:cache&gt;<br />
Description<br />
Cache the rendered page fragment using JBoss Cache. Note that &lt;s:cache&gt; actually uses the<br />
instance of JBoss Cache managed by the built-in pojoCache component.<br />
Other<br />
419<br />
Attributes<br />
• key — the key to cache rendered content, often a value expression. For example, if we<br />
were caching a page fragment that displays a document, we might use key=&#8221;Document-<br />
#{document.id}&#8221;.<br />
• enabled — a value expression that determines if the cache should be used.<br />
• region — a JBoss Cache node to use (different nodes can have different expiry policies).<br />
Usage<br />
&lt;s:cache key=&#8221;entry-#{blogEntry.id}&#8221; region=&#8221;pageFragments&#8221;&gt;<br />
&lt;div&gt;<br />
&lt;h3&gt;#{blogEntry.title}&lt;/h3&gt;<br />
&lt;div&gt;<br />
&lt;s:formattedText value=&#8221;#{blogEntry.body}&#8221;/&gt;<br />
&lt;/div&gt;<br />
&lt;p&gt;<br />
[Posted on&#160;<br />
&lt;h:outputText value="#{blogEntry.date}"&gt;<br />
&lt;f:convertDateTime timezone="#{blog.timeZone}" locale="#{blog.locale}"<br />
type="both"/&gt;<br />
&lt;/h:outputText&gt;]<br />
&lt;/p&gt;<br />
&lt;/div&gt;<br />
&lt;/s:cache&gt;<br />
29.1.6.2. &lt;s:fileUpload&gt;<br />
Description<br />
Renders a file upload control. This control must be used within a form with an encoding type of<br />
multipart/form-data, i.e:<br />
&lt;h:form enctype=&#8221;multipart/form-data&#8221;&gt;<br />
For multipart requests, the Seam Multipart servlet filter must also be configured in web.xml:<br />
&lt;filter&gt;<br />
&lt;filter-name&gt;Seam Filter&lt;/filter-name&gt;<br />
&lt;filter-class&gt;org.jboss.seam.servlet.SeamFilter&lt;/filter-class&gt;<br />
&lt;/filter&gt;<br />
Chapter 29. Seam JSF controls<br />
420<br />
&lt;filter-mapping&gt;<br />
&lt;filter-name&gt;Seam Filter&lt;/filter-name&gt;<br />
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />
&lt;/filter-mapping&gt;<br />
Configuration<br />
The following configuration options for multipart requests may be configured in components.xml:<br />
• createTempFiles — if this option is set to true, uploaded files are streamed to a temporary<br />
file instead of in memory.<br />
• maxRequestSize — the maximum size of a file upload request, in bytes.<br />
Here&#8217;s an example:<br />
&lt;component&gt;<br />
&lt;property name=&#8221;createTempFiles&#8221;&gt;true&lt;/property&gt;<br />
&lt;property name=&#8221;maxRequestSize&#8221;&gt;1000000&lt;/property&gt;<br />
&lt;/component&gt;<br />
Attributes<br />
• data — this value binding receives the binary file data. The receiving field should be declared<br />
as a byte[] or InputStream (required).<br />
• contentType — this value binding receives the file&#8217;s content type (optional).<br />
• fileName — this value binding receives the filename (optional).<br />
• fileSize — this value binding receives the file size (optional).<br />
• accept — a comma-separated list of content types to accept, may not be supported by the<br />
browser. E.g. &#8220;images/png,images/jpg&#8221;, &#8220;images/*&#8221;.<br />
• style — The control&#8217;s style<br />
• styleClass — The control&#8217;s style class<br />
Usage<br />
&lt;s:fileUpload id=&#8221;picture&#8221; data=&#8221;#{register.picture}&#8221;<br />
accept=&#8221;image/png&#8221;<br />
Other<br />
421<br />
contentType=&#8221;#{register.pictureContentType}&#8221; /&gt;<br />
29.1.6.3. &lt;s:graphicImage&gt;<br />
Description<br />
An extended &lt;h:graphicImage&gt; that allows the image to be created in a Seam Component;<br />
further transforms can be applied to the image.<br />
All attributes for &lt;h:graphicImage&gt; are supported, as well as:<br />
Attributes<br />
• value — image to display. Can be a path String (loaded from the classpath), a byte[],<br />
a java.io.File, a java.io.InputStream or a java.net.URL. Currently supported image<br />
formats are image/png, image/jpeg and image/gif.<br />
• fileName — if not specified the served image will have a generated file name. If you want to<br />
name your file, you should specify it here. This name should be unique<br />
Transformations<br />
To apply a transform to the image, you would nest a tag specifying the transform to apply. Seam<br />
currently supports these transforms:<br />
&lt;s:transformImageSize&gt;<br />
• width — new width of the image<br />
• height — new height of the image<br />
• maintainRatio — if true, and one of width/height are specified, the image will be resized<br />
with the dimension not specified being calculated to maintain the aspect ratio.<br />
• factor — scale the image by the given factor<br />
&lt;s:transformImageBlur&gt;<br />
• radius — perform a convolution blur with the given radius<br />
&lt;s:transformImageType&gt;<br />
• contentType — alter the type of the image to either image/jpeg or image/png<br />
It&#8217;s easy to create your own transform &#8211; create a UIComponent which implements<br />
org.jboss.seam.ui.graphicImage.ImageTransform. Inside the applyTransform()method<br />
use image.getBufferedImage() to get the original image and image.setBufferedImage() to<br />
set your transformed image. Transforms are applied in the order specified in the view.<br />
Chapter 29. Seam JSF controls<br />
422<br />
Usage<br />
&lt;s:graphicImage rendered=&#8221;#{auction.image ne null}&#8221;<br />
value=&#8221;#{auction.image.data}&#8221;&gt;<br />
&lt;s:transformImageSize width=&#8221;200&#8243; maintainRatio=&#8221;true&#8221;/&gt;<br />
&lt;/s:graphicImage&gt;<br />
29.1.6.4. &lt;s:remote&gt;<br />
Description<br />
Generates the Javascript stubs required to use Seam Remoting.<br />
Attributes<br />
• include — a comma-separated list of the component names (or fully qualified class names)for<br />
which to generate Seam Remoting Javascript stubs. See Chapter 22, Remoting for more details.<br />
Usage<br />
&lt;s:remote include=&#8221;customerAction,accountAction,com.acme.MyBean&#8221;/&gt;<br />
29.2. Annotations<br />
Seam also provides annotations to allow you to use Seam components as JSF converters and<br />
validators:<br />
@Converter<br />
@Name(&#8220;itemConverter&#8221;)<br />
@BypassInterceptors<br />
@Converter<br />
public class ItemConverter implements Converter {<br />
@Transactional<br />
public Object getAsObject(FacesContext context, UIComponent cmp, String value) {<br />
EntityManager entityManager = (EntityManager)<br />
Component.getInstance(&#8220;entityManager&#8221;);<br />
entityManager.joinTransaction();<br />
// Do the conversion<br />
}<br />
Annotations<br />
423<br />
public String getAsString(FacesContext context, UIComponent cmp, Object value) {<br />
// Do the conversion<br />
}<br />
}<br />
&lt;h:inputText value=&#8221;#{shop.item}&#8221; converter=&#8221;itemConverter&#8221; /&gt;<br />
Registers the Seam component as a JSF converter. Shown here is a converter which is able<br />
to access the JPA EntityManager inside a JTA transaction, when converting the value back<br />
to it&#8217;s object representation.<br />
@Validator<br />
@Name(&#8220;itemValidator&#8221;)<br />
@BypassInterceptors<br />
@Validator<br />
public class ItemValidator implements Validator {<br />
public void validate(FacesContext context, UIComponent cmp, Object value)<br />
throws ValidatorException {<br />
ItemController ItemController = (ItemController) Component.getInstance(&#8220;itemController&#8221;);<br />
return itemController.validate(value);<br />
}<br />
}<br />
&lt;h:inputText value=&#8221;#{shop.item}&#8221; validator=&#8221;itemValidator&#8221; /&gt;<br />
Registers the Seam component as a JSF validator. Shown here is a validator which injects<br />
another Seam component; the injected component is used to validate the value.</p>
<p>JBoss EL: Seam uses JBoss EL which provides an extension to the standard Unified Expression Language<br />
(EL). JBoss EL provides a number of enhancements that increase the expressiveness and power of EL expressions.</p>
<p>Parameterized Expressions: Standard EL does not allow you to use a method with user defined parameters — of course, JSF<br />
listener methods (e.g. a valueChangeListener) take parameters provided by JSF.<br />
JBoss EL removes this restriction. For example:</p>
<p>&lt;h:commandButton action=&#8221;#{hotelBooking.bookHotel(hotel)}&#8221; value=&#8221;Book Hotel&#8221;/&gt;<br />
@Name(&#8220;hotelBooking&#8221;)<br />
public class HotelBooking {<br />
public String bookHotel(Hotel hotel) {<br />
// Book the hotel<br />
}<br />
}</p>
<p>Usage: Just as in calls to method from Java, parameters are surrounded by parentheses, and separated by commas:</p>
<p>&lt;h:commandButton action=&#8221;#{hotelBooking.bookHotel(hotel, user)}&#8221; value=&#8221;Book Hotel&#8221;/&gt;</p>
<p>The parameters hotel and user will be evaluated as value expressions and passed to the<br />
bookHotel() method of the component.<br />
Any value expression may be used as a parameter:</p>
<p>&lt;h:commandButton action=&#8221;#{hotelBooking.bookHotel(hotel.id, user.username)}&#8221; value=&#8221;Book Hotel&#8221;/&gt;</p>
<p>It&#8217;s important to fully understand how this extension to EL works. When the page is rendered, the<br />
parameter names are stored (for example, hotel.id and user.username), and evaluated (as value expressions) when the page is<br />
submitted. You can&#8217;t pass objects as parameters!<br />
You must ensure that the parameters are available not only when the page is rendered, but also when it is submittedIf the<br />
arguments can not be resolved when the page is submitted the action method will be called with null arguments!<br />
You can also pass literal strings using single quotes:</p>
<p>&lt;h:commandLink action=&#8221;#{printer.println(&#8216;Hello world!&#8217;)}&#8221; value=&#8221;Hello&#8221;/&gt;</p>
<p>Unified EL also supports value expressions, used to bind a field to a backing bean. Value<br />
expressions use JavaBean naming conventions and expect a getter/setter pair. Often JSF expects<br />
a value expression where only retrieval (get) is needed (e.g. the rendered attribute). Many objects,<br />
however, don&#8217;t have appropriately named property accessors or require parameters.<br />
JBoss EL removes this restriction by allowing values to be retrieved using the method syntax.<br />
For example:</p>
<p>&lt;h:outputText value=&#8221;#{person.name}&#8221; rendered=&#8221;#{person.name.length() &gt; 5}&#8221; /&gt;</p>
<p>You can access the size of a collection in a similar manner:</p>
<p>#{searchResults.size()}</p>
<p>In general any expression of the form #{obj.property} would be identical to the expression</p>
<p>#{obj.getProperty()}.</p>
<p>Parameters are also allowed. The following example calls the productsByColorMethod with a literal string argument:</p>
<p>#{controller.productsByColor(&#8216;blue&#8217;)}</p>
<p>Limitations and Hints: When using JBoss EL you should keep the following points in mind:<br />
• Incompatibility with JSP 2.1 — JBoss EL can&#8217;t currently be used with JSP 2.1 as the compiler<br />
rejects expressions with parameters in. So, if you want to use this extension with JSF 1.2, you<br />
will need to use Facelets. The extension works correctly with JSP 2.0.</p>
<p>• Use inside iterative components — Components like &lt;c:forEach /&gt; and &lt;ui:repeat /&gt;iterate<br />
over a List or array, exposing each item in the list to nested components. This works great if<br />
you are selecting a row using a &lt;h:commandButton /&gt; or &lt;h:commandLink /&gt;:</p>
<p>@Factory(&#8220;items&#8221;)<br />
public List&lt;Item&gt; getItems() {<br />
return entityManager.createQuery(&#8220;select &#8230;&#8221;).getResultList();<br />
}<br />
&lt;h:dataTable value=&#8221;#{items}&#8221; var=&#8221;item&#8221;&gt;<br />
&lt;h:column&gt;<br />
&lt;h:commandLink value=&#8221;Select #{item.name}&#8221; action=&#8221;#{itemSelector.select(item})&#8221; /&gt;<br />
&lt;/h:column&gt;<br />
&lt;/h:dataTable&gt;</p>
<p>However if you want to use &lt;s:link /&gt; or &lt;s:button /&gt; you must expose the items<br />
as a DataModel, and use a &lt;dataTable /&gt; (or equivalent from a component set like<br />
&lt;rich:dataTable /&gt; ). Neither &lt;s:link /&gt; or &lt;s:button /&gt; submit the form (and therefore<br />
produce a bookmarkable link) so a &#8220;magic&#8221; parameter is needed to recreate the item when the<br />
action method is called. This magic parameter can only be added when a data table backed by a DataModel is used.</p>
<p>• Calling a MethodExpression from Java code — Normally, when a MethodExpression is<br />
created, the parameter types are passed in by JSF. In the case of a method binding, JSF<br />
assumes that there are no parameters to pass. With this extension, we can&#8217;t know the parameter<br />
types until after the expression has been evaluated. This has two minor consequences:<br />
• When you invoke a MethodExpression in Java code, parameters you pass may be ignored.<br />
Parameters defined in the expression will take precedence.<br />
• Ordinarily, it is safe to call methodExpression.getMethodInfo().getParamTypes() at any<br />
time. For an expression with parameters, you must first invoke the MethodExpression before<br />
calling getParamTypes().<br />
Both of these cases are exceedingly rare and only apply when you want to invoke the<br />
MethodExpression by hand in Java code.</p>
<p>Projection: JBoss EL supports a limited projection syntax. A projection expression maps a sub-expression<br />
across a multi-valued (list, set, etc&#8230;) expression. For instance, the expression:</p>
<p>#{company.departments}<br />
might return a list of departments. If you only need a list of department names, your only option is<br />
to iterate over the list to retrieve the values. JBoss EL allows this with a projection expression:<br />
#{company.departments.{d|d.name}}<br />
The subexpression is enclosed in braces. In this example, the expression d.name is evaluated<br />
for each department, using d as an alias to the department object. The result of this expression<br />
will be a list of String values.<br />
Any valid expression can be used in an expression, so it would be perfectly valid to write the<br />
following, assuming you had a use for the lengths of all the department names in a company:<br />
#{company.departments.{d|d.size()}}<br />
Projections can be nested. The following expression returns the last names of every employee<br />
in every department:<br />
#{company.departments.{d|d.employees.{emp|emp.lastName}}}<br />
Nested projections can be slightly tricky, however. The following expression looks like it returns<br />
a list of all the employees in all the departments:<br />
#{company.departments.{d|d.employees}}<br />
However, it actually returns a list containing a list of the employees for each individual department.<br />
To combine the values, it is necessary to use a slightly longer expression:<br />
#{company.departments.{d|d.employees.{e|e}}}<br />
It is important to note that this syntax cannot be parsed by Facelets or JSP and thus cannot be<br />
used in xhtml or JSP files. We anticipate that the projection syntax will change in future versions<br />
of JBoss EL.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/vikash28.wordpress.com/159/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/vikash28.wordpress.com/159/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/vikash28.wordpress.com/159/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/vikash28.wordpress.com/159/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/vikash28.wordpress.com/159/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/vikash28.wordpress.com/159/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/vikash28.wordpress.com/159/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/vikash28.wordpress.com/159/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/vikash28.wordpress.com/159/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/vikash28.wordpress.com/159/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/vikash28.wordpress.com/159/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/vikash28.wordpress.com/159/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/vikash28.wordpress.com/159/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/vikash28.wordpress.com/159/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=159&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://vikash28.wordpress.com/2011/05/08/jboss-seam/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4093cf2bdffa21a21a476dc8f7079984?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">vikash28</media:title>
		</media:content>
	</item>
		<item>
		<title>About GWT</title>
		<link>http://vikash28.wordpress.com/2009/12/24/about-gwt/</link>
		<comments>http://vikash28.wordpress.com/2009/12/24/about-gwt/#comments</comments>
		<pubDate>Thu, 24 Dec 2009 07:01:22 +0000</pubDate>
		<dc:creator>vikash28</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vikash28.wordpress.com/2009/12/24/about-gwt/</guid>
		<description><![CDATA[<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=109&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=109&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://vikash28.wordpress.com/2009/12/24/about-gwt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4093cf2bdffa21a21a476dc8f7079984?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">vikash28</media:title>
		</media:content>
	</item>
		<item>
		<title>Important topics for interviews</title>
		<link>http://vikash28.wordpress.com/2009/11/30/important-topics-for-interviews/</link>
		<comments>http://vikash28.wordpress.com/2009/11/30/important-topics-for-interviews/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 15:28:53 +0000</pubDate>
		<dc:creator>vikash28</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vikash28.wordpress.com/2009/11/30/important-topics-for-interviews/</guid>
		<description><![CDATA[1) JSF, Richfaces (View) 2) Hibernate (mapping, filter, listener, HQL) 3) Oracle 10g -&#62; PL/SQL 4) Design Pattern -&#62; Singleton, Service Locator, Delegate, Facade, DAO/DTO, Command, Decorator. 5) Struts(1.2,2.0), Spring, Spring-MVC. 6) Web Services -&#62; REST, WSDL 7) JQuery, AJAX, JSON 8) Core Java (Collection, Thread(Synchronization), File Operation(Serialization), Exception Handling). 9) Spring (IOC, DI{ How [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=105&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>1) JSF, Richfaces (View)</p>
<p>2) Hibernate (mapping, filter, listener, HQL)</p>
<p>3) Oracle 10g -&gt; PL/SQL</p>
<p>4) Design Pattern -&gt; Singleton, Service Locator, Delegate, Facade, DAO/DTO, Command, Decorator.</p>
<p>5) Struts(1.2,2.0), Spring, Spring-MVC.</p>
<p>6) Web Services -&gt; REST, WSDL</p>
<p>7) JQuery, AJAX, JSON</p>
<p>8) Core Java (Collection, Thread(Synchronization), File Operation(Serialization), Exception Handling).</p>
<p>9) Spring (IOC, DI{ How to achieve DI without spring}, Transaction Management{Isolation Level}).</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/vikash28.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/vikash28.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/vikash28.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/vikash28.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/vikash28.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/vikash28.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/vikash28.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/vikash28.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/vikash28.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/vikash28.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/vikash28.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/vikash28.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/vikash28.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/vikash28.wordpress.com/105/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=105&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://vikash28.wordpress.com/2009/11/30/important-topics-for-interviews/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4093cf2bdffa21a21a476dc8f7079984?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">vikash28</media:title>
		</media:content>
	</item>
		<item>
		<title>About EJB 2.0</title>
		<link>http://vikash28.wordpress.com/2009/11/18/about-ejb-2-0/</link>
		<comments>http://vikash28.wordpress.com/2009/11/18/about-ejb-2-0/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 11:34:00 +0000</pubDate>
		<dc:creator>vikash28</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vikash28.wordpress.com/2009/11/18/about-ejb-2-0/</guid>
		<description><![CDATA[<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=97&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=97&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://vikash28.wordpress.com/2009/11/18/about-ejb-2-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4093cf2bdffa21a21a476dc8f7079984?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">vikash28</media:title>
		</media:content>
	</item>
		<item>
		<title>About EJB 3.0</title>
		<link>http://vikash28.wordpress.com/2009/11/18/about-ejb-3-0/</link>
		<comments>http://vikash28.wordpress.com/2009/11/18/about-ejb-3-0/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 11:33:43 +0000</pubDate>
		<dc:creator>vikash28</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vikash28.wordpress.com/2009/11/18/about-ejb-3-0/</guid>
		<description><![CDATA[The timely rebirth of EJB is made possible through innovations introduced in Java SE 5, such as metadata annotations as well as the adoption of ideas like dependency injection and object-relational mapping (ORM)-based persistence. EJB 3 is a powerful and highly usable platform worth its place as the de facto standard for mission-critical enterprise development. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=96&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The timely rebirth of EJB is made possible through innovations<br />
introduced in Java SE 5, such as metadata annotations as well as the<br />
adoption of ideas like dependency injection and object-relational mapping (ORM)-based persistence.<br />
EJB 3 is a powerful and highly usable platform worth its place as the de facto standard for mission-critical enterprise development.<br />
We also offer a first glimpse into the impressive Java Persistence API, a promising technology that aims to standardize Java ORM and expand EJB 3 beyond the traditional boundaries of web-based client-server applications managed by containers.<br />
Enterprise JavaBeans (EJB) is a platform for building portable, reusable, and scalable business applications using the Java programming language. Since its initial incarnation, EJB has been touted as a component model or framework that lets you build enterprise Java applications without having to reinvent services such as transactions, security, automated persistence and so on that you may need for building an application.EJB allows application developers to focus on building business logic without having to spend time on building infrastructure code.<br />
From a developer’s point of view, an EJB is a piece of Java code that executes in a specialized runtime environment called the EJB container, which provides a number of component services. The persistence services are provided by a specialized framework called the persistence provider.EJB functions both as a component and a framework. We’ll also examine how EJB lends itself to building layered applications.<br />
The real idea behind a component is that it should effectively encapsulate application behavior.<br />
There are three types of EJB components: session beans, message-driven beans,and entities. Session beans and message-driven beans are used to implement business logic in an EJB application, and entities are used for persistence.<br />
EJB allows development of reusable components. For example, you can implement the credit card–charging module as an EJB component that may be accessed by multiple applications.<br />
The container provides the services to the EJB components in a rather elegant new way: metadata annotations are used to preconfigure the EJBs by specifying the type of services to add when the container deploys the EJBs.<br />
Java 5 introduced metadata annotations, which are property settings that mark a piece of code, such as a class or method, as having particular attributes. This is a declarative style of programming, in which the developer specifies what should be done and the system<br />
adds the code to do it.<br />
In EJB, metadata annotations dramatically simplify development and testing of applications, without having to depend on an external XML configuration file. It allows developers to declaratively add services to EJB components as and when they need. As figure 1.3 depicts, an annotation transforms a simple POJO into an EJB.<br />
Being able to support high-performance, fault-tolerant, scalable applications is an up-front concern for the EJB platform instead of being an afterthought.<br />
When the need to support a larger number of users becomes a reality, you won’t have to rewrite your code. Thankfully these concerns are taken care of by EJB container vendors. You’ll be able to count on moving your application to a distributed, clustered server farm by doing nothing more than a bit of configuration.<br />
EJB lets you turn your application into a web services powerhouse with ease when you need to.<br />
EJB 2 entity beans, which are intended to represent business objects, have numerous limitations that make it extremely difficult to use them to implement a persistent object model.<br />
EJB 3 enables you to easily follow good object-oriented<br />
design or DDD. The entities defined by EJB 3 Java Persistence API (JPA) support<br />
OO features, such as inheritance or polymorphism. It’s easy to implement a persistence object model with the EJB 3 JPA. More importantly, you can easily add business logic to your entities, so that implementing a rich domain model with EJB 3 is a trivial task.<br />
Despite its impressive services and vision, EJB 3 is not the only act in town. You can combine various technologies to more or less match EJB services and infrastructure.For example, you could use Spring with other open source technologies such as Hibernate and AspectJ to build your application, so why choose EJB 3?</p>
<p><strong>Ease of use</strong><br />
Thanks to the unwavering focus on ease of use, EJB 3 is probably the simplest server-side development platform around. The features that shine the brightest are POJO programming, annotations in favor of verbose XML, heavy use of sensible defaults, and JPA, all of which you will be learning about in this book.Although the number of EJB services is significant, you’ll find them very intuitive.For the most part, EJB 3 has a practical outlook and doesn’t demand that you understand the theoretical intricacies. </p>
<p><strong>Integrated solution stack</strong><br />
EJB 3 offers a complete stack of server solutions, including persistence, messaging,lightweight scheduling, remoting, web services, dependency injection (DI) and interceptors. This means that you won’t have to spend a lot of time looking for third-party tools to integrate into your application.In addition, EJB 3 provides seamless integration with other Java EE technologies, such as JDBC, JavaMail,Java Transaction API JTA (JTA), Java Messaging Service (JMS), Java Authentication and Authorization Service (JAAS), Java Naming and Directory Interface (JNDI),Java Remote Method Invocation (RMI) and so on.EJB is also guaranteed to seamlessly integrate with presentation-tier technologies like JavaServer Pages (JSP),servlets, JavaServer Faces (JSF) and Swing.</p>
<p><strong>Open Java EE standard</strong><br />
EJB is a critical part of the Java EE standard. This is an extremely important concept to grasp if you are to adopt EJB 3. EJB 3 has an open, public API specification,which organizations are encouraged to use to create a container or persistence provider implementation. The EJB 3 standard is developed by the Java Community Process JCP) consisting of a nonexclusive group of individuals driving the Java standard.The open standard leads to broader vendor support for EJB 3, which means you don’t have to depend on a proprietary solution.</p>
<p><strong>Broad vendor support</strong><br />
EJB is supported by a large and diverse variety of independent organizations.This includes the technology world’s largest, most respected, and most financially strong names, such as Oracle and IBM as well as passionate and energetic open source groups like JBoss and Geronimo.</p>
<p><strong>Stable, high-quality code base</strong><br />
Although EJB 3 is a groundbreaking step, most application server implementations will still benefit from a relatively stable code base that has lived through some of the most demanding enterprise environments over a prolonged period of time.</p>
<p><strong>Clustering, load balancing, and failover</strong><br />
Features historically added by most application server vendors are robust support for clustering, load balancing, and failover. EJB application servers have a proven track record of supporting some of the largest high-performance computing (HPC)-enabled server farm environments. More importantly, you can leverage such support with no changes to code, no third-party tool integration, and relatively simple configuration (beyond the inherent work in setting up a hardware cluster). This means that you can rely on hardware clustering to scale up your application with EJB 3 if you need to.</p>
<p><strong><strong>Understanding EJB types</strong></strong><br />
EJB classifies beans into three types, based on what they are used for:<br />
■ Session beans<br />
■ Message-driven beans<br />
■ Entities</p>
<p><strong>Getting inside EJB</strong><br />
When you build a simple Java class, you need a Java Virtual Machine (JVM) to execute it. In a similar way (as you learned in the previous section) to execute session beans and MDBs you need an EJB container, and to run your entities you need a persistence provider.</p>
<p><strong>Accessing EJB services: the EJB container</strong><br />
the container transparently provides EJB component services such as transactions, security management,remoting, and web services support. As a matter of fact, you might even think of the container as a JVM on steroids, whose purpose is to execute EJBs. In EJB 3, the container provides services applicable to session beans and MDBs only. The task of putting an EJB 3 component inside a container is called<br />
deployment.</p>
<p><strong>Accessing JPA services: the persistence provider</strong><br />
Instead of following the JVM-like container model, JPA follows a model similar to APIs, like JDBC. JPA provides persistence services such as retrieving, adding, modifying, and deleting JPA entities when you explicitly ask for them by invoking EntityManager API methods.<br />
The “provider” terminology comes from APIs such as JDBC and JNDI too. you know that a “provider” is essentially the vendor implementation that the JDBC API uses under the covers.Similarly Products that provide JPA implementation are called persistence providers or persistence engines.JBoss Hibernate and Oracle TopLink are two popular JPA providers.<br />
Since JPA is completely pluggable and separable, the persistence provider and container in an EJB 3 solution need not come from the same vendor.For example,you could use Hibernate inside a BEA WebLogic container if it suits you better,instead of the Kodo implementation WebLogic ships with.</p>
<p><strong>Gaining functionality with EJB services</strong></p>
<p><strong>Integration -&gt; Session beans and MDBs -&gt; </strong><br />
Helps glue together components, ideally through simple configuration instead of code. In EJB 3, this is done through dependency injection (DI) as well as lookup.<br />
<strong>Pooling -&gt; Stateless session beans, MDBs -&gt;</strong><br />
For each EJB component, the EJB platform creates a pool of component instances that are shared by clients. At any point in time, each pooled instance is only allowed to be used by a single client. As soon as an instance is finished servicing a client,it is returned to the pool for reuse instead of being frivolously discarded for the garbage collector to reclaim.<br />
<strong>Thread-safety -&gt; Session beans and MDBs -&gt;</strong><br />
EJB makes all components thread-safe and highly performant in ways that are completely invisible. This means that you can write your server components as if you were developing a single-threaded desktop<br />
application. It doesn’t matter how complex the component itself is;<br />
EJB will make sure it is thread-safe.<br />
<strong>State management -&gt; Stateful session beans -&gt;</strong><br />
The EJB container manages state transparently for stateful components<br />
instead of having you write verbose and error-prone code for state management.This means that you can maintain state in instance variables as if you were developing a desktop application. EJB takes care of all the details of session maintenance behind the scenes.<br />
<strong>Messaging -&gt; MDBs -&gt;</strong><br />
EJB 3 allows you to write messaging-aware components without having<br />
to deal with a lot of the mechanical details of the Java Messaging<br />
Service (JMS) API.<br />
<strong>Transactions -&gt; Session beans and MDB -&gt;</strong><br />
EJB supports declarative transaction management that helps you add transactional behavior to components using simple configuration instead of code.In effect, you can designate any component method to be transactional.If the method completes normally, EJB commits the transaction and makes the data changes made by the method permanent.Otherwise the transaction is rolled back.<br />
<strong>Security -&gt; Session beans -&gt;</strong><br />
EJB supports integration with the Java Authentication and Authorization Service (JAAS) API, so it is very easy to completely externalize security and secure an application using simple configuration instead of cluttering up your application with security code.<br />
<strong>Interceptors -&gt; Session beans and MDBs -&gt;</strong><br />
EJB 3 introduces AOP in a very lightweight, accessible manner using interceptors. This allows you to easily separate out crosscutting concerns such as logging, auditing, and so on in a configurable way.<br />
<strong>Remote access -&gt; Session beans -&gt;</strong><br />
In EJB 3, you can make components remotely accessible without writing<br />
any code. In addition, EJB 3 enables client code to access remote components as if they were local components using DI.<br />
<strong>Web services -&gt; Stateless session beans -&gt;</strong><br />
EJB 3 can transparently turn business components into robust web services with minimal code change.<br />
<strong>Persistence -&gt; Entities -&gt;</strong><br />
Providing standards-based, 100 percent configurable automated persistence as an alternative to verbose and error-prone JDBC/SQL code is a principal goal of the EJB 3 platform.<br />
<strong>Caching and performance -&gt; Entities -&gt;</strong><br />
In addition to automating persistence, JPA transparently provides a number of services geared toward data caching, performance optimization and application tuning. These services are invaluable in supporting medium to large-scale systems.</p>
<p><strong>New features: simplifying EJB</strong><br />
There are three primary sources of complexities in EJB 2:the heavyweight programming model, direct use of the Java Naming Directory Interface (JNDI) and a verbose XML deployment descriptor.<br />
Three primary techniques in EJB 3 eliminate these sources of complexity: metadata annotations, minimal deployment descriptors and dependency injection.</p>
<p><strong>Replacing deployment descriptors with annotations</strong><br />
annotations simplify the EJB programming model, remove the need for detailed deployment descriptors and act as an effective delivery mechanism for dependency injection.<br />
<strong>Java metadata annotations: a brief primer</strong><br />
Annotations essentially allow us to “attach” additional information (officially called attributes) to a Java class, interface, method, or variable.The additional information conveyed by annotations can be used by a development environment like Eclipse, the Java compiler, a deployment tool, a persistence provider like Hibernate or a runtime environment like the Java EE container.Another way to think about annotations is that they are “custom” Java modifiers (in addition to private,public, static, final, and so on) that can be used by anything handling Java source or byte code.This is how annotations look:</p>
<p>import mypackage.Author;<br />
@Author(&#8220;Debu Panda, Reza Rahman and Derek Lane&#8221;)<br />
public class EJB3InAction implements ManningBook</p>
<p>Note that, just like anything else, annotations and attribute-oriented programming have a few weaknesses.Specifically, it isn’t always a good idea to mix and match configuration with source code such as annotations.This means that you would have to change source code each time you made a configuration change to something like a database connection resource or deployment environment entry.EJB 3 solves this problem by allowing you to override annotations with XML<br />
deployment descriptors where appropriate.</p>
<p><strong>Know your deployment descriptor</strong><br />
A deployment descriptor is simply an XML file that contains application configuration information.Every deployment unit in Java EE can have a deployment descriptor that describes its contents and environment. Some typical examples of deployment units are the Enterprise Archive (EAR), Web Application Archive (WAR), and the EJB (ejb-jar) module.<br />
We know in EJB 2, how verbose the XML (ejb-jar.xml) descriptor was.<br />
Most elements were required even if they were trivial. Ex:</p>
<p>HelloUserBean<br />
ejb3inaction.example.Hello<br />
ejb3inaction.example.HelloUserBean<br />
Stateless<br />
Container</p>
<p>The EJB 3 makes deployment descriptors completely optional.</p>
<p><strong>Mixing annotations and deployment descriptors</strong></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/vikash28.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/vikash28.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/vikash28.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/vikash28.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/vikash28.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/vikash28.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/vikash28.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/vikash28.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/vikash28.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/vikash28.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/vikash28.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/vikash28.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/vikash28.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/vikash28.wordpress.com/96/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=96&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://vikash28.wordpress.com/2009/11/18/about-ejb-3-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4093cf2bdffa21a21a476dc8f7079984?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">vikash28</media:title>
		</media:content>
	</item>
		<item>
		<title>About XML Spy</title>
		<link>http://vikash28.wordpress.com/2009/11/18/about-xml-spy/</link>
		<comments>http://vikash28.wordpress.com/2009/11/18/about-xml-spy/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 11:28:59 +0000</pubDate>
		<dc:creator>vikash28</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vikash28.wordpress.com/?p=94</guid>
		<description><![CDATA[<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=94&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=94&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://vikash28.wordpress.com/2009/11/18/about-xml-spy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4093cf2bdffa21a21a476dc8f7079984?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">vikash28</media:title>
		</media:content>
	</item>
		<item>
		<title>About XPath</title>
		<link>http://vikash28.wordpress.com/2009/11/18/about-xpath/</link>
		<comments>http://vikash28.wordpress.com/2009/11/18/about-xpath/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 11:28:39 +0000</pubDate>
		<dc:creator>vikash28</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vikash28.wordpress.com/2009/11/18/about-xpath/</guid>
		<description><![CDATA[<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=93&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=93&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://vikash28.wordpress.com/2009/11/18/about-xpath/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4093cf2bdffa21a21a476dc8f7079984?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">vikash28</media:title>
		</media:content>
	</item>
		<item>
		<title>About XQuery</title>
		<link>http://vikash28.wordpress.com/2009/11/18/about-xquery/</link>
		<comments>http://vikash28.wordpress.com/2009/11/18/about-xquery/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 11:28:19 +0000</pubDate>
		<dc:creator>vikash28</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vikash28.wordpress.com/?p=91</guid>
		<description><![CDATA[<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=91&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=vikash28.wordpress.com&amp;blog=10250492&amp;post=91&amp;subd=vikash28&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://vikash28.wordpress.com/2009/11/18/about-xquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/4093cf2bdffa21a21a476dc8f7079984?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">vikash28</media:title>
		</media:content>
	</item>
	</channel>
</rss>
