Seasar DI Container with AOP

Setup

S2JSF requirements are the same as Seasar2 requirements. It requires JDK1.4 or higher. Just extract downloaded s2-jsf-x.x.x.zip archive file and import unzipped s2jsf directory to Eclipse workspace(File -> import -> Existing Project into Workspace)

S2JSF sample files must be downloaded separately. The sample uses Tomcat5 and Tomcat Plugin. Download and setup these software before installing S2JSF samples.
Execute the following steps to used the samples:

  1. Download and extract downloaded archive file
  2. Import the unzipped file into Eclipse workspace.
  3. Start Tomcat
  4. S2JSF samples may be viewed by accesing http://localhost:8080/s2jsf-example/ from your web browser (assuming tomcat was installed on port 8080.)

Samples

hello.html

Enter http://localhost:8080/s2jsf-example/hello/hello.html?message=Hitoshi as a URI in a web browser. "Hello Hitoshi" should be displayed.
This sample show how to do the followings:

  • Declaring S2JSF namespace
  • Layout function
  • Using taglib
  • Specifying tags by inject attribute
  • Using title tag
  • Changing pages by page with link
  • Passing parameters between pages
  • Writing navigation-rule
  • Printing string using ValueBinding

Let's look at the HTML:

listing 1: hello.html
01:<html xmlns:m="http://www.seasar.org/maya" m:extends="/WEB-INF/layout/layout.html">
02:<head>
03:<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
04:<title>Hello</title>
05:</head>
06:<body> 07: <span m:inject="f:param" m:name="layoutTitle" m:value="Hello"/> 08: <span m:inject="s:insert" m:name="body">
09: Hello <span m:value="#{message}">hoge</span>
10: </span>
11:</body>
12:</html>

The first line, xmlns:m="http://www.seasar.org/maya", is the S2JSF namespace declaration. It is used to associate namespace URI, http://www.seasar.org/maya, to a prefix character. Character "m" is usually used as this character, but it may be any arbitrary character string consistent with the XML namespace specification.

m:extends attribute specifies the layout to extend. To provide consistent look & feel, there are many sites where the layout of pages are divided into header, menu, body, and footer with pages having a common header, menu, and footer and only differing in the content of the body. To correspond to this layout, S2JSF allows developers to create a base template layout and for each individual pages to extend this template. For example, in the above situation where pages differ only in the body section, only the body section should be individually created.
listing 2 Layout.html is an example of a base template.

Line 7 sets the value to layoutTitle to value of layoutTitle set in layout.html. As is this example, to pass a parameter to the parent page, f:param tag is used inside the body tag.
Lines 8 to 10 overwrite the parent page's body section.
Line 9 is used to output a string to the HTML document. String matching pattern #{...} is called a ValueBinding and is used to dynamically set a value. When S2JSF find a ValueBinding string, it tries to set a value by searching in request, parameter, session, and then S2Container. When #{variable name.property name} is specified, variable name is first resolved and then the value of property is used.
To output a value dynamically, value attribute in a span element is used as in line 9. #{message} specifies to output the content of message parameter in a request. The content of the span tag, hoge, will be ignored during execution. It is only used as a dummy place holder when hello.html file is opened directly from a web browser.

listing 2: layout.html
01:<html xmlns:m="http://www.seasar.org/maya">
02:<head>
03:<meta http-equiv="Content-Type" content="text/html; charset=Windows-31j" />
04:<link m:inject="s:link" rel="stylesheet" type="text/css" href="/css/global.css"/>
05:<title m:value="#{layoutTitle}"/>
06:</head>
07:<body>
08:<table border="0" cellspacing="5">
09:<tr>
10:  <td colspan="2"><span m:inject="s:insert" m:src="/WEB-INF/layout/header.html"/></td>
11:</tr>
12:<tr>
13: <td width="140" valign="top">
14: <span m:inject="s:insert" m:src="/WEB-INF/layout/menu.html"/>
15: </td>
16: <td valign="top" align="left">
17: <span m:inject="s:insert" m:name="body"/>
18: </td>
19:</tr>
20:<tr>
21: <td colspan="2">
22: <hr/>
23: </td>
24:</tr>
25:<tr>
26: <td colspan="2">
27: <span m:inject="s:insert" m:src="/WEB-INF/layout/footer.html"/>
28: </td>
29:</tr>
30:</table>
31:</body>
32:</html>

inject attribute is used to specify a JSF's JSP tag within a HTML document. Existing JSF taglib may be used. In the above HTML document, inject attribute in line 4 is set to s:link.
Line 5 specifies the default title of the generated HTML document. Value of the title is set to layoutTitle. The value of this variable should be set by the pages extending this base template.
The prefix "s" is defined in the WEB-INF/classes/jsf.dicon(or WEB-INF/src) file as follows. Note that prefix s is associated with URI http://www.seasar.org.jsf.
Line 17 defines the body section of the document. Naming the document section using the name attribute makes it possible to easily extend the layout and overwrite the content. For example, the body section of the above sample may be overwritten by defining <span m:inject="s:insert" m:name="body">...,</span> in the extended page.

listing 3: jsf.dicon (example for this sample)
<component class="org.seasar.jsf.runtime.JsfConfigImpl">
    <initMethod name="addTaglibUri">
        <arg>"h"</arg>
        <arg>"http://java.sun.com/jsf/html"</arg>
    <initMethod>
    <initMethod name="addTaglibUri">
        <arg>"f"</arg>
        <arg>"http://java.sun.com/jsf/core"</arg>
    <initMethod>
<initMethod name="addTaglibUri"> <arg>"s"</arg>
<arg>"http://www.seasar.org/jsf"</arg>
</initMethod>
</component>
Span element in line 10 in listing 2 inserts header.html page. The inject attribute is set to insert and the src attribute specifies the file to insert. In the sample, header.html contains the following elements and inserts an image seasar.gif.

listing 4: header.html
<html xmlns:m="http://www.seasar.org/maya">
<body>
<span m:inject="s:insert">
<img m:inject="h:graphicImage" m:url="/images/seasar.gif"/>
</span> </body>
</html>

The page to be inserted has a span tag with inject="s:insert" attribute and without the name attribute. Content to be inserted are specified as child elements of this span tag. Elements above this span element are displayed when the file is directly opened with a web browser but are ignored when the page is generated (i.e. URI to generate the page is used instead of a file name.)
Following is the content of menu.html used in the sample.

listing 5: menu.html
<html xmlns:m="http://www.seasar.org/maya">
...
01:<body>
02:    <span m:inject="s:insert">
03:        <form>
04:            <ul>
05:                <li>
06:                    <a m:action="hello">Hello
07:                        <span m:inject="f:param" m:name="message" m:value="World"/>
08:                    </a>
09:                </li>
10:                <li>
11:                    <a m:action="add">Add</a>
12:                </li>
13:                ...
14:            </ul>
15:        </form>
16:    </span>
17:</body>
18:</html>

The inserted page contains the page name of URI to locate when action attribute in an anchor tag is clicked. Action attribute may specify a JavaBeans method or page name. To specify a JavaBeans method, value of the action attribute is set to ${parameter_name.method.name}. To specify a page name, action attribute is set to a string containing the name of the page name.
In the above listing, page name hello is defined in the following section in the WEB-INF/faces-config.xml file.

listing 6: faces-config.xml
<navigation-rule>
<navigation-case>
<from-outcome>hello</from-outcome>
<to-view-id>/hello/hello.html</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>

Value of from-outcome element is set to the page name to locate. The actual URI to locate is contained the the to-view-id element. redirect tag is used to redirect to the page. When redirect tag is not specified, it is forwarded to the page.
In the sample listing above, the page name hello is associated to URI /hello/hello.html. When the use selects a link, the web browser will be redirected to this /hello/hello.html document.

Furthermore, parameter may be passed to the redirected page by specifying a f:param. In
menu.html, there is a span tag with inject set to f:param with name set to message and value set to World. This setting will result in passing a parameter named message with value World.

add.html

This sample demonstrate the followings:

  • How input value works with JavaBean property
  • How to call JavaBeans' method when button is clicked
  • How to auto-bind an object of request, session, S2Container in a way of coding setter method at Action

The sample add.html is as follows:

listing 7: add.html
01:<html xmlns:m="http://www.seasar.org/maya" m:extends="/WEB-INF/layout/layout.html">
02:<head> 03:<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> 04:<title>Add</title> 05:</head> 06:<body> 07: <span m:inject="f:param" m:name="layoutTitle" m:value="Add"/>
08: <span m:inject="s:insert" m:name="body">
09: <form>
10: <span m:inject="h:messages" m:globalOnly="false" m:showDetail="true"/>
11: <input type="text" m:value="#{addDto.arg1}"/> +
12: <input type="text" m:value="#{addDto.arg2}"/> =
13: <span m:value="#{addDto.result}"/> 14: <input type="submit" value="calculate" m:action="#{addAction.calculate}"/> 15: </form>
16: </span>
17:</body>
18:</html>

The content of the Head element from line 2 to line 5 are all ignored during actual runtime but are used when the add.html is directly opened from a web browser.
Line 10 specifies error output operation. When globalOnly is set to true, error messages that are not specific to an input (global error messages) are outputted. When it is set to true, all error messages are outputted.
Line 11 associates input tag with a JavaBeans property. Input values are set to JavaBeans property if it passes the validation conditions. It the value is invalid, it is displayed as is on a page. Unlike in Struts where input values are set to a String by an ActionForm and then validated, JSF validates the input and ony passes valid data.
Value of the value attribute addDdo is defined in the examples/jsf/dicon/add.dicon file as follows:

listing 8: add.dicon (partial listing)
<component name="addDto" class="examples.jsf.dto.AddDto" instance="request"/>
instance attribute is set to "request" so addTdo is managed in a request scope.
app.dicon which defined the root element includes add.dicon file using the following include statement:
listing 9: app.dicon (partial listing)
<include path="examples/jsf/dicon/add.dicon"/>

Line 14 in listing 7 specifies to call method calculate() when a button is clicked. Specifying methods name as a value to an action attribute that is to be called when an user clicks on a button or a link is named MethodBinding. The syntax of the value is #{variable name,method name}. Methods called by MethodBinding should not have any argument and should return a String.
addAction in the sample is defined in the add.dicon file as follows:

listing 10: add.dicon(partial)
<component name="addAction" class="examples.jsf.action.impl.AddActionImpl"
 instance="request"/>

Action class received entered value through a property so the instance is set to request.
It is not neccessary separate an interface with an implementation, but it offers a clearer specification.

package examples.jsf.action;

public interface AddAction {
    public String calculate();
}
package examples.jsf.action.impl;

import examples.jsf.action.AddAction;
import examples.jsf.dto.AddDto;
import examples.jsf.logic.AddLogic;

public class AddActionImpl implements AddAction {

    private AddDto addDto;
    private AddLogic addLogic;

    public void setAddDto(AddDto addDto) {
        this.addDto = addDto;
    }

    public void setAddLogic(AddLogic addLogic) {
        this.addLogic = addLogic;
    }

    public String calculate() {
        int result = addLogic.calculate(addDto);
        addDto.setResult(result);
        return null;
    }
}

To receive entered value, setter method is defined to addDto property.
Right before calling on method specified in MethodBinding, S2JSF checks if there is any property defined by a setter method. When there is a property, S2JSF checks if there is any variable with the same name as the property in request attributes, parameters, session attributes, and S2Containters. When there is a matching variable, S2JSF automatically calls on the setter method and set the value of that variable.

variable named addLogic is not defined anywhere but when property type is an interface, S2Container automatically sets the class implementing that interface.
Class implementing AddLogic is defined in add.dicon as follows:

<component class="examples.jsf.logic.impl.AddLogicImpl"/>

If the method called by MethodBinding returns a null, process is transferred to itself.

forEachList.html

This sample demostrates the following topics:

  • Repetition using forEach.
  • Transferring page when previewing with anchor tag
  • Transferring page when previewing with buttonr tag

Following is a part of the sample HTML document:

01:<form>
02:    <table border="1">
03:        <tr bgcolor="#7777FF">
04:            <th>Key</th>
05:            <th>Name</th>
06:            <th colspan="2">to ResultPage</th>
07:        </tr>
08:        <span m:inject="s:forEach" m:items="#{forEachDtoList}"
09:            m:var="e" m:varIndex="i">
10:        <tr>
11:            <td><span m:value="#{e.key}">111</span></td>
12:            <td><span m:value="#{e.name}">aaa</span></td>
13:            <td><a href="forEachResult.html" m:action="forEachResult">to ResultPage
14:                    <span m:inject="f:param" m:name="index" m:value="#{i}"/>
15:                </a>
16:            </td>
17:            <td>
18:                <input type="button" m:action="forEachResult" value="to ResultPage"
19:                    onclick="location.href='forEachResult.html'">
20:                    <span m:inject="f:param" m:name="index" m:value="#{i}"/>
21:                </input>
22:            </td>
23:        </tr>
24:        </span>
25:    </table>
26:</form>

forEach in span element in line 8 is used to specify a loop of lines 8 through 24. items attribute specifies how to loop, var attribute specifies variable name to access value assigned in a loop, varIndex attributes specifies loop control variable.

Value of element in a loop may be obtained through properties of variable name assigned to var attribute. For example, lines 11 and 12 respectively gets values of key and name of elements in a loop.

In line 13, href attribute and action attribute are both specified. In this kind of situation, href is ignored during execution. The href attribute, however, is effective mean to move to another page when the html file is directly opened from a web browser.

Line 14 is an example to passing parameter using param. It is specified in a span element that is a child to the a element. The parameter is passed to the target of the target URI.

Line 18 is a example of a button with action attribute and onclick attribute. onclick attribute is ignored when executed but is used to transfer to page 'forEachResult.html' when the html file is directly opened from the web browser.

Line 20 is used to pass parameter to the transferred page when the button is pressed.

forEachResult.html

This sample demonstrates the followings:

  • Page initialization
  • Setting getter method in Action to request property and automatically set session.

Following is a part of the sample HTML document:

01:<html xmlns:m="http://www.seasar.org/maya"
02: m:action="#{forEachResultInitAction.initialize}"
03: m:extends="/WEB-INF/layout/layout.html">
04:<head>
05:<meta http-equiv="Content-Type" content="text/html; charset=Windows-31j" />
06:<title>ForEach</title>
07:</head>
08:<body>
09:<span m:inject="f:param" m:name="layoutTitle" m:value="ForEach"/>
10:<span m:inject="s:insert" m:name="body"> 11: Key:<span m:value="#{forEachDto.key}">111</span> 12: Name:<span m:value="#{forEachDto.name}">aaa</span><br /> 13: <a href="forEachList.html">previous</a> 14:</span> 15:</body> 16:</html>

action attribute in row 2 specifies the initialization method. The Action class is defined as follows:

package examples.jsf.action.impl;

import java.util.List;

import examples.jsf.action.ForEachResultInitAction;
import examples.jsf.dto.ForEachDto;

public class ForEachResultInitActionImpl implements ForEachResultInitAction {
    private int index;
    private List forEachDtoList;
    private ForEachDto forEachDto;

    public void setIndex(int index) {
        this.index = index;
    }

    public void setForEachDtoList(List forEachDtoList) {
        this.forEachDtoList = forEachDtoList;
    }

    public ForEachDto getForEachDto() {
        return forEachDto;
    }

    public String initialize() {
        forEachDto = (ForEachDto) forEachDtoList.get(index);
        return null;
    }
}

Remember that the page that linked to this page had child to a anchor tag and button tag that had an param attribute which passes index. So, by defining setIndex() method, S2JSF will automatically set the parameter value. Furthermore, by defining setForEachDtoList() method, it is possible to refer to forEachDtoList defined in examples/jsf/dicon/foreach.dicon.
By using initMethod tag, it is possible to call on arbitrary method. Thus, objects may be constructed more freely.

<component name="forEachDtoList" class="java.util.ArrayList" instance="session">
<initMethod name="add" >
<arg>
<component class="examples.jsf.dto.ForEachDto" >
<property name="key">"111"</property>
<property name="name">"aaa"</property>
</component>
</arg>
</initMethod>
<initMethod name="add" >
<arg>
<component class="examples.jsf.dto.ForEachDto" >
<property name="key">"222"</property>
<property name="name">"bbb"</property>
</component>
</arg>
</initMethod>
</component>

Set object based on index specified in initialize() method to forEachDto property. After initialize() method is executed, S2JSF automatically sets value of forEachDto property to forEachDto attribute in a request because forEachDto property has a getter method defined. It is possible to set to a session instead of a request by declaring the following constant:
public static final String property name_EXPORT = "session";