10 min read

Seam application architecture

As most enterprise Java developers are probably familiar with JSF and JSP, we will be using this as the view technology for our sample applications. Facelets is the recommended view technology for Seam-based applications once we have a solid understanding of Seam.

In a standard Java EE application, Enterprise Application Resource (EAR) files contain one or more Web Application Resource (WAR) files and one or more sets of Java Archive (JAR) files containing Enterprise JavaBeans (EJB) functionality. Seam applications are generally deployed in exactly the same manner as depicted in the following diagram. It is possible to deploy Seam onto a servlet-only container (for example, Tomcat) and use POJOs as the server-side Seam components. However, in this situation, we don’t get any of the benefits that EJBs provide, such as security, transaction handling, management, or pooling.

Seam 2.x Web Development

Seam components

Within Seam, components are simple POJOs. There is no need to implement any interfaces or derive classes from a Seam-specific base class to make Seam components classes. For example, a Seam component could be:

  • A simple POJO
  • a stateless Session Bean
  • a stateful Session Bean
  • a JPA entity and so on

Seam components are defined by adding the @Name annotation to a class definition. The @Name annotation takes a single parameter to define the name of the Seam component. The following example shows how a stateless Session Bean is defined as a Seam component called calcAction.

package com.davidsalter.seamcalculator;
@Stateless
@Name("calcAction")
public class CalcAction implements Calc {
...
}

When a Seam application is deployed to JBoss, the log output at startup lists what Seam components are deployed, and what type they are. This can be useful for diagnostic purposes, to ensure that your components are deployed correctly. Output similar to the following will be shown in the JBoss console log when the CalcAction class is deployed:

21:24:24,097 INFO [Initialization] Installing components...
21:24:24,121 INFO [Component] Component: calcAction, scope:
STATELESS, type: STATELESS_SESSION_BEAN, class: com.davidsalter.
seamcalculator.CalcAction, JNDI: SeamCalculator/CalcAction/local

Object Injection and Outjection

One of the benefits of using Seam is that it acts as the “glue” between the web technology and the server-side technology. By this we mean that the Seam Framework allows us to use enterprise beans (for example, Session Beans) directly within the Web tier without having to use Data Transfer Object (DTO) patterns and without worrying about exposing server-side functionality on the client.

Additionally, if we are using Session Beans for our server-side functionality, we don’t really have to develop an additional layer of JSF backing beans, which are essentially acting as another layer between our web page and our application logic.

In order to fully understand the benefits of Seam, we need to first describe what we mean by Injection and Outjection.

Injection is the process of the framework setting component values before an object is created. With injection, the framework is responsible for setting components (or injecting them) within other components. Typically, Injection can be used to allow component values to be passed from the web page into Seam components.

Outjection works in the opposite direction to Injection. With Outjection, components are responsible for setting component values back into the framework. Typically, Outjection is used for setting component values back into the Seam Framework, and these values can then be referenced via JSF Expression Language (EL) within JSF pages. This means that Outjection is typically used to allow data values to be passed from Seam components into web pages.

Seam allows components to be injected into different Seam components by using the @In annotation and allows us to outject them by using the @Out annotation. For example, if we have some JSF code that allows us to enter details on a web form, we may use an <h:inputText …/> tag such as this:

<h:inputText value="#{calculator.value1}" required="true"/>

The Seam component calculator could then be injected into a Seam component using the @In annotation as follows:

@In
private Calculator calculator;

With Seam, all of the default values on annotations are the most likely ones to be used. In the preceding example therefore, Seam will look up a component called calculator and inject that into the calculator variable. If we wanted Seam to inject a variable with a different name to the variable that it is being injected into, we can adorn the @In annotation with the value parameter.

@In (value="myCalculator")
private Calculator calculator;

In this example, Seam will look up a component called myCalculator and inject it into the variable calculator.

Similarly, if we want to outject a variable from a Seam component into a JSF page, we would use the @Out annotation.

@Out
private Calculator calculator;

The outjected calculator object could then be used in a JSF page in the following manner:

<h:outputText value="#{calculator.answer}"/>

Example application

To see these concepts in action, and to gain an understanding of how Seam components are used instead of JSF backing beans, let us look at a simple calculator web application. This simple application allows us to enter two numbers on a web page. Clicking the Add button on the web page will cause the sum of the numbers to be displayed.

This basic application will give us an understanding of the layout of a Seam application and how we can inject and outject components between the business layer and the view. The application functionality is shown in the following screenshot.

Seam 2.x Web Development

The sample code for this application can be downloaded from the Packt web site, at http://www.packtpub.com/support.

For this sample application, we have a single JSF page that is responsible for:

  • Reading two numeric values from the user
  • Invoking business logic to add the numbers together
  • Displaying the results of adding the numbers together
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<html>
 <head>
 <title>Seam Calculator</title>
 </head>
 <body>
 <f:view>
 <h:form>
 <h:panelGrid columns="2">
 Value 1: <h:inputText value="#{calculator.
 value1}" />
 Value 2: <h:inputText value="#{calculator.
 value2}" />
 Add them together gives: <h:outputText value="
 #{calculator.answer} "/>
 </h:panelGrid>
 <h:commandButton value="Add" action=
 "#{calcAction.calculate}"/>
 </h:form>
 </f:view>
 </body>
</html>

We can see that there is nothing Seam-specific in this JSF page. However, we are binding two inputText areas, one outputText area, and a button action to Seam components by using standard JSF Expression Language.

JSF EL Seam Binding
calculator.value1 This is bound to the member variable value1 on the Seam component called calculator. This value will be injected into the Seam component.
calculator.value2 This is bound to the member variable value2 on the Seam component called calculator. This value will be injected into the Seam component.
calculator.answer This is bound to the member variable answer on the Seam component called calculator. This value will be outjected from the Seam component.
calcAction.calculate This will invoke the method calculate() on the Seam component called calcAction.

Our business logic for this sample application is performed in a simple POJO class called Calculator.java.

package com.davidsalter.seamcalculator;
import java.io.Serializable;
import org.jboss.seam.annotations.Name;

@Name("calculator") public class Calculator { private double value1; private double value2; private double answer;

public double getValue1() {
return value1;
}

public void setValue1(double value1) {
this.value1 = value1;
}

public double getValue2() {
return value2;
}

public void setValue2(double value2) {
this.value2 = value2;
}

public double getAnswer() {
return answer;
}

public void add() {
this.answer = value1 + value2;
}
}

This class is decorated with the @Name(“calculator”) annotation, which causes it to be registered to Seam with the name, “calculator”. The @Name annotation causes this object to be registered as a Seam component that can subsequently be used within other Seam components via Injection or Outjection by using the @In and @Out annotations.

Finally, we need to have a class that is acting as a backing bean for the JSF page that allows us to invoke our business logic. In this example, we are using a Stateless Session Bean. The Session Bean and its local interface are as follows.

In the Java EE 5 specification, a Stateless Session Bean is used to represent a single application client’s communication with an application server. A Stateless Session Bean, as its name suggests, contains no state information; so they are typically used as transaction façades. A Façade is a popular design pattern, which defines how simplified access to a system can be provided. For more information about the Façade pattern, check out the following link: http://java.sun.com/blueprints/corej2eepatterns/Patterns/SessionFacade.html

Defining a Stateless Session Bean using Java EE 5 technologies requires an interface and an implementation class to be defined. The interface defines all of the methods that are available to clients of the Session Bean, whereas the implementation class contains a concrete implementation of the interface. In Java EE 5, a Session Bean interface is annotated with either the @Local or @Remote or both annotations. An @Local interface is used when a Session Bean is to be accessed locally within the same JVM as its client (for example, a web page running within an application server). An @Remote interface is used when a Session Bean’s clients are remote to the application server that is running within a different JVM as the application server.

There are many books that cover Stateless Session Beans and EJB 3 in depth, such as EJB 3 Developer’s Guide by Michael Sikora, published by Packt Publishing. For more information on this book, check out the following link: http://www.packtpub.com/developer-guide-for-ejb3

In the following code, we are registering our CalcAction class with Seam under the name calcAction. We are also Injecting and Outjecting the calculator variable so that we can use it both to retrieve values from our JSF form and pass them back to the form.

package com.davidsalter.seamcalculator;

import javax.ejb.Stateless;

import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Name;

@Stateless
@Name(“calcAction”)
public class CalcAction implements Calc {

@In
@Out
private Calculator calculator;

public String calculate() {

calculator.add();
return “”;
}
}
package com.davidsalter.seamcalculator;
import javax.ejb.Local;

@Local
public interface Calc {
public String calculate();
}

That’s all the code we need to write for our sample application. If we review this code, we can see several key points where Seam has made our application development easier:

  • All of the code that we have developed has been written as POJOs, which will make unit testing a lot easier.
  • We haven’t extended or implemented any special Seam interfaces.
  • We’ve not had to define any JSF backing beans explicitly in XML.
  • We’re using Java EE Session Beans to manage all of the business logic and web-tier/business-tier integration.
  • We’ve not used any DTO objects to transfer data between the web and the business tiers. We’re using a Seam component that contains both state and behavior.

If you are familiar with JSF, you can probably see that adding Seam into a fairly standard JSF application has already made our development simpler. Finally, to enable Seam to correctly find our Seam components and deploy them correctly to the application server, we need to create an empty file called seam.properties and place it within the root of the classpath of the EJB JAR file. Because this file is empty, we will not discuss it further here. To deploy the application as a WAR file embedded inside an EAR file, we need to write some deployment descriptors.

LEAVE A REPLY

Please enter your comment!
Please enter your name here