Seam
Introduction[edit]
Seam manages components, that means it manages the complete lifecycle and scope of the components (inversion of control principle), named as context of a component. Thereto it injects dependencies to the components (dependency injection).
Most Seam application use session beans as JSF action listeners.
Seam lets you use a JSF EL expression inside EJB-QL. Under the covers, this results in an ordinary JPA setParameter() call on the standard JPA Query object.
Seam integrates Hibernate Validator and lets you use it for data validation (even if you are not using Hibernate for persistence).
Architecture and Dynamics[edit]
Components[edit]
A Seam component needs a component name specified by the @Name annotation. This name must be unique within the Seam application. When JSF asks Seam to resolve a context variable with a name that is the same as a Seam component name, and the context variable is currently undefined (null), Seam will instantiate that component, and bind the new instance to the context variable. Whenever Seam instantiates a component, it binds the new instance to a context variable in the component's default context. The default context is specified using the @Scope annotation.
Contexts[edit]
A context defines a namespace, a set of context variables. Usually we obtain components from a context via injection, and put component instances into a context via outjection. Each Seam component type has a default scope if not explicitly specified. The scope is specified by the @Scope annotation. Types are:
| Type | Description | Default for |
| APPLICATION | Analogous the servlet application scope. | |
| BUSINESS_PROCESS | Spans multiple conversations for multiple users as controlled declaratively by start and end states in the business process definition file. | |
| CONVERSATION | The conversation scope maintains data for a single user across a well-defined series of pages | entities, SFSB |
| EVENT | Analogous the servlet request scope. Exists form the beginning of the Restore View phase until the end of the render response phase in the JSF life cycle. | JavaBeans |
| METHOD | ||
| PAGE | Begins at the start of the JSF Render Response phase and carries on with each adjoining JSF postback until a redirect or a navigation to another page occurs. | |
| SESSION | Analogous to the servlet session scope. | |
| STATELESS | forces a component to be instatiated each time the component name is resolved. | SLSB, message driven beans |
| UNSPECIFIED |
Conversation[edit]
There is always a conversation context often a temporary conversation context active during the apply request values, process validations, update model values, invoke application and render response phases of the JSF request lifecycle. Seam transparently propagates the conversation context (including the temporary conversation context) across JSF postbacks and redirects. If you don't do anything special, a non-faces request (a GET request for example) will not propagate the conversation context and will be processed in a new temporary conversation.
Bijection[edit]
Dependency injection allows a component to obtain a reference to another component by having the container "inject" the other component to a setter method or instance variable. In all dependency injection implementations that we have seen, injection occurs when the component is constructed, and the reference does not subsequently change for the lifetime of the component instance. Bijection is used to assemble stateful components from various different contexts (a component from a "wider" context may even have a reference to a component from a "narrower" context). Values are injected from context variables into attributes of the component being invoked, and also outjected from the component attributes back out to the context, allowing the component being invoked to manipulate the values of contextual variables simply by setting its own instance variables. Since the value of contextual variables changes over time, and since Seam components are stateful, bijection takes place every time a component is invoked. Injected values are disinjected (i.e, set to null) immediately after method completion and outjection
Startup[edit]
Seam does this by registering a servlet filter, a servlet and a JSF phase listener.
- When the web application starts the servlet container bootstraps Seam, at which time it loads the contextual container, scans the classpath for components and serves component instances. All components annotated both with @Startup and @Scope(ScopeType.APPLICATION) are instantiated.
Sessions[edit]
The SeamListener also captures notifications when new HTTP sessions are started, at which time it instantiates startup components that reside in the session scope (i.e., annotated with both @Startup and @Scope(ScopeType.SESSION)).
Requests[edit]
- requests e.g. to /faces/* are routed to the Faces Servlet (s. web.xml)
- the extension is replaced with javax.faces.DEFAULT_SUFFIX
- the Faces Servlet hands the view ID to the registered Facelet view handler
- the view handler builds the UI component tree
Installation and Configuration[edit]
- download jboss-seam-2.0.2.SP1.zip and extract to <ECLIPSE_WORKSPACE>
- add jboss.home to <SEAM_DIR>\build.properties
Web application configuration[edit]
- in web.xml:
<listener> <listener-class>org.jboss.seam.servlet.SeamListener</listener-class> </listener> <JSF_SERVLET_CONFIGURATION> <FACELET_CONFIGURATION> <filter> <filter-name>Seam Filter</filter-name> <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class> </filter> <filter-mapping> <filter-name>Seam Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
<FACELET_CONFIGURATIION>
If you want JSP and Facelets together s http://wiki.java.net/bin/view/Projects/FaceletsFAQ#How_do_I_use_Facelets_and_JSP_in.
Filter configuration[edit]
Voraussetzung ist die Filter-Konfiguration in web.xml.
- <WAR-File>/WEB-INF/components.xml
Components configuration[edit]
- <WAR-File>/WEB-INF/components.xml
<components xmlns="http://jboss.com/products/seam/components" xmlns:bpm="http://jboss.com/products/seam/bpm" xmlns:core="http://jboss.com/products/seam/core" xmlns:security="http://jboss.com/products/seam/security" xmlns:transaction="http://jboss.com/products/seam/transaction" ...> ... <security:identity authenticate-method="#{authenticator.authenticate}"/> <!-- The standard action #{identity.login} in an facelet calls actually the method authenticate() of the seam component authenticator. --> ... <bpm:jbpm> <bpm:process-definitions> <value><Processdefinition-FILENAME in WAR-File/WEB-INF/></value> </bpm:process-definitions> </bpm:jbpm> <bpm:pageflow-definitions> <value><Pageflow-FILENAME in WAR-File/WEB-INF/></value> <value><Pageflow-FILENAME in WAR-File/WEB-INF/></value> </bpm:pageflow-definitions> </components>
Debugging[edit]
in components.xml insert
<component name="org.jboss.seam.core.init"> <property name="debug">true</property> </component>
Libs[edit]
| jboss-seam.jar | Provides the Seam container, Seam annotations, bijection, extended JSF life cycle, CRUD framework, security, jBPM integration, Drools integration, web services, page flows, asynchronous support, conversations, extended EL, managed transactions and persistence, and the integration test framework. |
| jboss-seam-remoting.jar | Supports invoking Seam components using Ajax requests and allows JavaScript to listen for messages on JMS queues and topics |
| jboss-seam-ui.jar | Includes the Seam JSF components, file upload capability, graphics generation, Facelet integration, and conversation controls |
| jboss-seam-debug.jar | Activates the hot deployment classloader and provides a Seam debug page and developer-oriented error page |
| jboss-seam-ioc.jar | Provides integration with Spring and other IoC containers |
| jboss-seam-pdf.jar | Has support for generating PDF files using Facelet templates and a document storage mechanism for pushing binary files |
| jboss-seam-mail.jar | Provides email integration and supports creating emails from Facelet templates |
seam-gen[edit]
- <SEAM_DIR>/seam.bat (setup|...|reset)
create project from db[edit]
- seam setup populates seam-gen/build.properties
- seam create-project
- seam generate
- seam restart
Annotations[edit]
Seam defines own annotations and uses some other annotations.
org.hibernate.validator.Length[edit]
org.hibernate.validator.NotNull[edit]
org.jboss.seam.annotations.datamodel.DataModel[edit]
@org.jboss.seam.annotations.datamodel.DataModel[(scope=ScopeType.<TYPE>)] <attribute declaration>
The @DataModel annotation exposes an attibute of type java.util.List to the JSF page as an instance of javax.faces.model.DataModel. This allows us to use the list in a JSF <h:dataTable> with clickable links for each row. In this case, the DataModel is made available in a session context variable named messageList.
org.jboss.seam.annotations.datamodel.DataModelSelection[edit]
@org.jboss.seam.annotations.datamodel.DataModelSelection <attribute declaration>
The @DataModelSelection annotation tells Seam to inject the List element that corresponded to the clicked link.
org.jboss.seam.annotations.Factory[edit]
@org.jboss.seam.annotations.Factory[("<context variable name>")]
<method_declaration>
The @Factory annotation tells Seam to create an instance of the bean and invoke the method to initialize the value. We call method a factory method. Marks a method as a factory method for a context variable. A factory method is called whenever no value is bound to the named context variable, and is expected to initialize the value of the context variable. There are two kinds of factory methods. Factory methods with void return type are responsible for outjecting a value to the context variable. Factory methods which return a value do not need to explicitly ouject the value, since Seam will bind the returned value to the specified scope. This annotation supports use of the Seam "factory component" pattern.
org.jboss.seam.annotations.In[edit]
@org.jboss.seam.annotations.In[("<Contextvariablename>|<EL_Expression>") [create=true] [required=false]]
<attribute_declaration>|<setter_method>
The attribute is injected by Seam. Examples for injections are EntityManager or FacesMessages. By default Seam will use the name of the property or instance variable that is being injected. You may wish to specify the context variable name explicitly, using, for example, @In("currentUser"). If you want Seam to create an instance of the component when there is no existing component instance bound to the named context variable, you should specify @In(create=true). If the value is optional (it can be null), specify @In(required=false).
org.jboss.seam.annotations.Logger[edit]
@org.jboss.seam.annotations.Logger private org.jboss.seam.log.Log log;
org.jboss.seam.annotations.Name[edit]
@org.jboss.seam.annotations.Name("<Name>")
<class_declaration>
specifies the name of the Seam component.
org.jboss.seam.annotations.Out[edit]
@org.jboss.seam.annotations.Out[([required=(true|false) [,scope=<SCOPE>])] <attribute_declaration>|<getter_method>
The @Out annotation specifies that an attribute should be outjected, either from an instance variable.
org.jboss.seam.annotations.Scope[edit]
@org.jboss.seam.annotations.Scope(org.jboss.seam.ScopeType.<SCOPE_TYPE>) <class_declaration>
specifies what context a component instance is bound to, when it is instantiated by Seam.
org.jboss.seam.annotations.Unwrap[edit]
@org.jboss.seam.annotations.Unwrap <method_declaration>
A manager component is any component with an @Unwrap method. This method returns the value that will be visable to clients, and is called every time a context variable is referenced.
Standard components[edit]
Identity[edit]
- Name "identity"
@org.jboss.seam.annotations.In private org.jboss.seam.security.Identity idendity;
is a standard component of the Seam security model und lives as long as the session.
Mehtods:
- getUsername()
- getPassword()
Standard Functionality[edit]
JBoss EL[edit]
Seam provides an extension to the standard Unified Expression Language (EL) called JBoss EL.
Logging[edit]
The org.jboss.seam.log.log (s. annotations) class has a specialised syntax e.g.
log.info("creating component '#0' on #1", name(), date());
log.info("#{<SEAM COMPONENT>.<attribute>}");
Methods:
- info()
- debug()
- error()
Security[edit]
The security functionality was extended during between version 2.0.2 to 2.1.0 (s. documentation).
Authentication[edit]
For less complex applications Seam offers a simple method:
- configure components.xml to call the simple authentication method
- write an authentication method (no parameter, return true if success, else false) (s. Seam class identity)
- write a login form
Pageflow[edit]
There are two ways to define pageflow in Seam:
- Using JSF or Seam navigation rules - the stateless navigation model
- Using jPDL - the stateful navigation model through jBPM integration
You can use them together or independently or not at all.
[edit]
The stateless model defines a mapping from a set of named, logical outcomes of an event directly to the resulting page of the view. The navigation rules are entirely oblivious to any state held by the application other than what page was the source of the event. This means that your action listener methods must sometimes make decisions about the page flow, since only they have access to the current state of the application.
You can specify JSF- or Seam navigation rule.
- seam pageflow navigation rules in <WAR-File>/WEB-INF/pages.xml
<pages>
<page view-id="<NAME>" [action="#{<COMPONENT.<METHOD>}"]>
[<action if="<CONDITION>" execute="#{<COMPONENT>.<METHOD>}"/>]
</page>
</pages>
or
- as JSF navigation rule in faces-config.xml.
<navigation-rule>
<from-view-id>/numberGuess.jsp</from-view-id>
<navigation-case>
<from-outcome>guess</from-outcome>
<to-view-id>/numberGuess.jsp</to-view-id>
<redirect/>
</navigation-case>
<navigation-case>
<from-outcome>win</from-outcome>
<to-view-id>/win.jsp</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
- If you find navigation rules overly verbose, you can return view ids directly from your action listener methods, e.g.:
public String guess()
{
if (guess==randomNumber) return "/win.jsp";
if (++guessCount==maxGuesses) return "/searchResults.jsp?searchPattern=#{searchAction.searchPattern}";
return null;
}
<page>[edit]
<page view-id=<View> [action=<EL_Expression>]
<param name="<PARAM_NAME>" [value="#{<OJECTMODEL_TARGET>}"/>
</page>
The action is executed just before rendering the page. The page action method can return a JSF outcome. If the outcome is non-null, Seam will use the defined navigation rules to navigate to a view. The parameters are evaluated before page rendering and used for links via <s:link> to this page.
[edit]
The stateful model defines a set of transitions between a set of named, logical application states. In this model, it is possible to express the flow of any user interaction entirely in the jPDL pageflow definition, and write action listener methods that are completely unaware of the flow of the interaction.
Business process management[edit]
Seam applications use jBPM for two different problems, for pageflow navigation and for business process management. A simple business process definition looks much the same as a page flow definition, except that instead of <page> nodes, we have <task-node> nodes. In a long-running business process, the wait states are where the system is waiting for some user to log in and perform a task.
API[edit]
FacesMessages[edit]
FacesMessages.instance().add("...");
output see JSF
Seam tags[edit]
Seam use Facelets for the user interface. An example of an xhtml file is
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">
<s:button>[edit]
<s:button />
corresponding to the JSF tag <h:commandButton>. It is translated to <input type="button">.
<s:decorate>[edit]
<s:decorate id="<NAME>" template="<TEMPLATENAME>" /> </s:decorate>
extends the functionality of composition tag of facelets.
<s:link>[edit]
<s:link view="<VIEWNAME>" value="<TEXT>" />
corresponding to the JSF tag <h:commandLink>. Seam Seam will prepare page parameters associated with the target view ID. For a specific description of the parameter see the documentation 'Conversations and workspace management'.
<s:validateAll>[edit]
This JSF component tells JSF to validate all contained input fields against the Hibernate Validator annotations specified in the entitiy bean.
Applications[edit]
- s. JBoss
Resources[edit]
- Seam in Action by Dan Allen in C:\Uwes\Documents\Software_Development\Programming\Frameworks\Seam\SeaminAction.pdf, Source code extracted to <ECLIPSE_WORKSPACE>/seaminaction
Status[edit]
- Seam in Action Part 1 and project seamgen_contacts
