Documentation
Home
Quick overview (new)
Tutorial
Download
Installation
Javadoc

Tag Library Reference
Components Tags
Extension Tags

Printer Versions
Quick Overview (new)
Tutorial
Overview (old)

Old Documents
Overview (old)

JSP Framework

Components
Tutorial v0.3

Author : Cedric Dumoulin

Date : 14 Nov. 2000

Rev : 4 Jul. 2001

 

Latest version (Web site) : http://www.lifl.fr/~dumoulin/components

 

Table of Content

Components Tutorial v0.3. 1

1      Tutorial overview.. 1

2      Setup your development environment2

3      Write your first page. 2

3.1       Plan your components and main layout2

3.2       Write components. 3

3.3       Assemble Components in a Page. 5

3.4       Try Your Page. 7

4      Reuse Existing Layouts. 7

4.1       Classic Layout / template. 7

4.2       Portal8

4.3       Vertical Boxes. 9

5      Definitions. 10

5.1       Declare Definitions. 11

5.2       Use Definitions. 11

5.3       Set Web Application Configuration. 12

5.4       Definitions as Component Parameters. 12

5.5       Extended Definitions. 14

5.6       Definitions as Forward. 15

6      Write More Complex Components. 16

6.1       Submenu Component16

6.2       View Sources Component18

6.3       Body Including Twice the Same Component18

7      Internationalization (i18n)21

7.1       Select Language Menu. 22

7.2       Select Language Action. 22

7.3       Localized Definition Descriptions Files. 23

7.4       Try Your Pages. 23

8      Multi-Channels. 23

 

1         Tutorial overview

 

This tutorial shows you how to write and use Components to define a Web site. Use this tutorial to learn the basic skills you'll need to develop a Web site and to learn about some of the features of the Components Framework.

In this tutorial, you will create a fictitious web site, with pages illustrating Components features : basic page, portal page, definitions, i18n. 

This tutorial cover the view part of the UI, it doesn?t cover the model and controller part of the MVC 2 model.

Along the way, you'll learn how to perform the following tasks:

  • Build a page
    • Identify components
    • Write components
    • Assemble components
    • Write a layout Component
  • Reuse existing layouts / templates
    • Reuse classic layout
    • Reuse portal layout
    • Reuse vertical boxes layout
  • Use component definitions
    • Declare and use definitions
    • Extends definitions
    • Definitions as component parameters
    • Struts and definitions
  • Design intelligent component
    • Build new layouts
    • Reusable sub-menu
    • Reusable components (included twice)
    • View sources component and menu
  • Create i18n components

2         Setup your development environment

In order to run examples of this tutorial, you need to install a JSP server, like Tomcat. You also need the Components Library and the Struts Library.

We suppose that you have some basic knowledge of web development, JSP and JSP tags.

Examples of this tutorial are in the Components distribution file.

However, we advise you to write yourself the examples. For that, you can create a directory under the web server webapps directory (call it tutorial), and put all your files and sub-directories under this directory.

In order to avoid rewriting configurations files, you can copy the complete WEB-INF directory from the tutorial to your directory.

3         Write your first page

Your first page is a simple page that will be improved later in this tutorial.

3.1      Plan your components and main layout

Your first page look like the following picture :


 


It is divided in header, footer, menu and body. Such division identifies our main components :

  • header : containing company logo
  • footer : containing copyrights
  • menu : containing direct links to others pages
  • body : the main area of the page

These components are assembled together using a layout or template. This layout is also a component. As layouts are often used, there exist a library of layouts. But, in this tutorial, you will learn how to write simple layout.

Once you have your main components and your layout, you need to set up your web page main entrance (i.e. : define the web page  that will process the http request). This can simply be done in a jsp file.

Starting from the page main entrance, we can draw a tree of components, like the following :

 


You will next learn how to write these components, the layout, and the page entrance.

3.2      Write components

Covered topics : write simple components; the ?html link? problem.

3.2.1      Header

Your header will contain the company logo.

Copy directory images from the distribution tutorial directory to your examples root directory.

Create a new blank file, and save it under common/header.jsp.

Edit your new file, and place your images, as in following :

<a href="http://www.mycompany.com">

   <img src="/images/headerLeft-logo.gif" align="left" border="0">

</a>

<img src="/images/headerRight-logo.gif" align="right" border="0">

You can note that images path is absolute (starting with ?/?). You need to use an absolute path because this component can be included from pages residing at different places, not always at your site root.

3.2.1.1  The ?html link? problem

Using simple absolute path work fine if your web site is placed directly at the root of your domain name (i.e. : at www.mycompany.com). If your web site is under a subdomain (i.e. : at www.mycompany.com/my_site), as it is often the case, you need to prefix this path with the subdomain name (my_site). In order to have a portable site, you can retrieve the subdomain name from the http request.

Our component becomes :

<a href="http://www.mycompany.com">

   <img src="<%=request.getContextPath()%>/images/headerLeft-logo.gif" align="left" border="0">

</a>

<img src="<%=request.getContextPath()%>/images/headerRight-logo.gif" align="right" border="0">

It is a good habit to prefix absolute links used in client side (html links) by the subdomain name, retrieved from the http request. In this tutorial, you will always prefix html links with subdomain name.

[to do : propose a tag to transform links transparently. Ex :
<toRelativePath absolutePath=?/images/logo.gif? /> ; this tag will convert provided absolute path to a path relative from where component is included. 001013]

 

3.2.2      Footer

The footer contains company copyrights.

Create a new file, and save it under common/footer.jsp.

Write copyrights notice, as in following :

<div align="center">

  <font color="#023264" size="-1">

    <em>         Copyright &copy; 2000, MyCompany         </em>

  </font>

</div>

<img src="<%=request.getContextPath()%>/images/struts-power.gif" align="right" border="0">

3.2.3      Menu

The menu contains links to other pages. For now, you just write a simple menu. You will create more sophisticated menus later in this tutorial.

Create a new file, and save it under basic/menu.jsp.

Now, you can create your menu : create a table, with tree rows. Normally, each row contains a link to a page. Here, only first row contains link to the main page.

Your code should looks like the following :

<table>

<tr bgcolor="Blue">

  <td>

    Menu

  </td>

</tr>

<tr>

  <td width="120" valign="top">

    <font size="-1"><a href="<%=request.getContextPath()%>/index.jsp">Home</a></font>

  </td>

</tr>

<tr>

  <td width="120" valign="top">

    <font size="-1">Item 2</a></font>

  </td>

</tr>

<tr>

  <td width="120" valign="top">

    <font size="-1">Item 3</a></font>

  </td>

</tr>

</table>

 

3.2.4      Body

The body is the active part of your pages. For now, you will develop a simple body writing the classic sentence ?Hello the World?. You will develop other bodies later.

Create a new file, and save it under basic/hello.jsp.

In your file, write ?Hello the World?.

The code should looks like the following :

<div align="center">

  <font size="+1"><b>Hello the World</b></font>

</div>

 

3.3      Assemble Components in a Page

Covered topics : passing parameters, basic layout understanding, assembling components in layout, include mechanism understanding. Retrieving of parameter values.

 

Now, you will assemble your components. For that, you will develop a component taking in charge the layout, and including previously developed components where you want them to reside. This component can be seen as a Template.

In order for your layout component be reusable, you will pass it components to include as parameters.

3.3.1      Passing Parameters

To pass parameters to the component that will do the layout, you write something like that :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<comp:insert page="/basic/myLayout.jsp" flush="true">

  <comp:put name="title"  value="My first page" />

  <comp:put name="header" value="/common/header.jsp" />

  <comp:put name="footer" value="/common/footer.jsp" />

  <comp:put name="menu"   value="/basic/menu.jsp" />

  <comp:put name="body"   value="/basic/helloBody.jsp" />

</comp:insert>

Or like the following, which is the same, but looks like more familiar to people already using Struts Template :

<%@ taglib uri="/WEB-INF/components.tld" prefix="template" %>

 

<template:insert page="/basic/myLayout.jsp" flush="true">

  <template:put name="title"  value="My first page" />

  <template:put name="header" value="/common/header.jsp" />

  <template:put name="footer" value="/common/footer.jsp" />

  <template:put name="menu"   value="/basic/menu.jsp" />

  <template:put name="body"   value="/basic/helloBody.jsp" />

</template:insert>

 

Create a new file, and save it under basicPage.jsp. Copy previous lines in it.

The first line instructs the web server to use the components tag library. It also specifies that all tags from this library will start with the prefix comp.

The tag itself specifies the component?s page to include : /basic/myLayout.jsp. You will develop this component in a few moments. We pass parameters to this component, each one is identified by a name. The value can be of any type. Here we use hard-coded strings.

 

3.3.2      Write Layout / Template

First, create a new file, and save it under basic/myLayout.jsp.

In this file, create a table reflecting your layout, as describe in Plan your components and main layout.

The code looks like this :

<html>

<head>

       <title></title>

</head>

 

<body>

<TABLE width="100%">

 

  <TR>

    <TD colspan="2">header</TD></TR>

  <TR>

    <TD width="120">menu</TD>

    <TD>body</TD></TR>

  <TR>

    <TD colspan="2">footer</TD>

  </TR>

</TABLE>

 

 

</body>

</html>

Note : This layout contains <html>, <head> and <body> tags. This component is used to define the html page.

3.3.3      Insert Components

Now, you will insert (include) components by using special tags.

Put the following code at the beginning of your page :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

This instruct jsp processor to use the special tags library
"/WEB-INF/components.tld",and that tags will be prefixed by ?comp?.

Next, you can insert your components by using following tag :

<comp:insert attribute=?body? flush=?true? />

This tag inserts a component whose name is taken from the value of the attribute ?body?. It is why you must use attribute=??.

Do the same for each of your component. The code should looks like :

  ?

<TABLE width="100%">

 

  <TR>

    <TD colspan="2"><comp:insert attribute="header" /></TD></TR>

  <TR>

    <TD width="120"><comp:insert attribute="menu" /></TD>

    <TD><comp:insert attribute="body" /></TD></TR>

  <TR>

    <TD colspan="2"><comp:insert attribute="footer" /></TD>

  </TR>

</TABLE>

  ?

3.3.4      Set Page Title

Your layout component will be used several times. But you certainly want a different title for each page using this layout. For that, you will pass the page title as a parameter. In the layout, you extract the title from parameters, and put the value in the correct place :

   ?

<head>

    <title><comp:getAsString name="title"/></title>

</head>

   ?

Tag getAsString (formerly getAttribute) retrieves the value of a component?s attribute, and write it directly as a string. So, the tag will be replaced by the value you passed to the component.

3.3.5      Complete code

Following is the complete code for your first layout component :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<html>

<head>

    <title><comp:getAsString name="title"/></title>

</head>

 

<body>

<TABLE width="100%">

 

  <TR>

    <TD colspan="2"><comp:insert attribute="header" /></TD></TR>

  <TR>

    <TD width="120"><comp:insert attribute="menu" /></TD>

    <TD><comp:insert attribute="body" /></TD></TR>

  <TR>

    <TD colspan="2"><comp:insert attribute="footer" /></TD>

  </TR>

</TABLE>

 

 

</body>

</html>

 

3.4      Try Your Page

You can test your page by starting your web server, and pointing on your newly created page ?basicPage.jsp?.

 

Note : your configuration files must be set correctly before starting the web server. For now, you can simply copy the entire WEB-INF directory in your tutorial directory.

4         Reuse Existing Layouts

Covered topics : Reuse layouts.

 

Assembling of components is often done in the same way. It is possible to develop some basic layouts and reuse them inside a web site, or even from site to site. Provided examples come with some layouts : classic layout, portal (columns), vertical boxes.

You will first learn how to reuse such layouts. In a later chapter, you will learn how to build your own layouts.

4.1      Classic Layout / template

The most common layout for a page is the header / menu / body / footer layout. We provide one of this layout under /layout/classicLayout.jsp. You can use it in place of your previously defined layout : simply change the name of included component in basicPage.jsp :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<comp:insert page="/layout/classicLayout.jsp" flush="true">

  <comp:put name="title"  value="My first page" />

  <comp:put name="header" value="/common/header.jsp" />

  <comp:put name="footer" value="/common/footer.jsp" />

  <comp:put name="menu"   value="/basic/menu.jsp" />

  <comp:put name="body"   value="/basic/helloBody.jsp" />

</comp:insert>

Note that there is no change in the passed parameters. In the same way, you can change the way a layout component laid sub-components. If well designed, you can change all site look and feel simply by changing main layout component !

4.2      Portal

Covered topics : use of layout inside components, list as parameter to a component.

 

Here, you will learn how to build a portal by assembling components.

A portal is made of components, ?stacked ? into columns. Portal page use the layout common to all site. So, you only need to define the body of your portal page.

This body uses a component that lay sub components in columns. You need to pass as parameters the number of columns you want, and one list of components for each column.

4.2.1      Prepare Portal Components

First, you need to define some components to assemble in your page. You can define your own components, or copy the one defined in the tutorial (under portal/*).

Copy components from directory ?portal/*? in your tutorial directory (keep the sub directory ?portal? ).

4.2.2      Assemble Portal Components

Create a new file and save it under portal/portalBody.jsp.

Include the portal layout (called /layout/columnsLayout.jsp), passing it the requested number of columns, and one list of components for each column. List names must be ?listX?, where ?X? is the index of the list, starting at zero.

Your code looks like following :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<comp:insert page="/layout/columnsLayout.jsp" flush="true">

  <comp:put name="numCols" value="2" />

  <comp:putList name="list0" >

    <comp:add value="/portal/login.jsp" />

    <comp:add value="/portal/messages.jsp" />

    <comp:add value="/portal/newsFeed.jsp" />

    <comp:add value="/portal/advert2.jsp" />

  </comp:putList>

  <comp:putList name="list1" >

    <comp:add value="/portal/advert3.jsp" />

    <comp:add value="/portal/stocks.jsp" />

    <comp:add value="/portal/whatsNew.jsp" />

    <comp:add value="/portal/personalLinks.jsp" />

    <comp:add value="/portal/search.jsp" />

  </comp:putList>

</comp:insert>

In this code, you declare three attributes : one variable and two lists. Values are added to the list in the specified order. Here, you add sub-components URLs. It is possible to add definitions name instead (see definitions).

4.2.3      Set up web page

You can now include your portal body in any components. Preferably, you will include it in a page using the main layout.

Create the page in a new file called /portalPage.jsp :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<comp:insert page="/layout/classicLayout.jsp" flush="true">

  <comp:put name="title"  value="My First Portal Page" />

  <comp:put name="header" value="/common/header.jsp" />

  <comp:put name="footer" value="/common/footer.jsp" />

  <comp:put name="menu"   value="/basic/menu.jsp" />

  <comp:put name="body"   value="/portal/portalBody.jsp" />

</comp:insert>

Note that you use ?classicLayout.jsp? rather than your ?myLayout.jsp?. Both layouts are nearly the same, except than classicLayout include a style sheet used in the entire site.

Check result by pointing your browser on the page.

4.3      Vertical Boxes

We often need to put components one under the others. The vertical boxes layout (/layout/vboxLayout.jsp) does exactly that. You pass it a list of components, and it laid them vertically.

As an example, we will improve the menu : it will now be made of three components : one showing an image, one providing links to pages and one providing links to a component writing sources.

4.3.1      Assemble Components

Create a new file and save it under /common/menu.jsp. In this file, include the vboxLayout component, and pass it a list with sub-components URLs.

Your code should looks like :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<comp:insert page="/layout/vboxLayout.jsp" flush="true" >

  <comp:putList name="componentsList" >

    <comp:add value="/common/menu/menuLogo.jsp" />

    <comp:add value="/common/menu/menuLinks.jsp" />

    <comp:add value="/common/menu/menuSrc.jsp" />

  </comp:putList>

</comp:insert>

The vboxLayout component requires one parameter called ?componentList?. It is a list of URLs referencing sub-components to include. Of course, you need to have such components.

MenuLogo.jsp

Following is the code of this component :

<img src="<%=request.getContextPath()%>/images/struts-power.gif" width="95" height="37" border="0" alt="">

MenuLinks.jsp

Following is the code of this component :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<comp:insert page="/common/submenu.jsp" flush="true">

  <comp:put name="title" value="Main Menu" />

  <comp:putList name="items" >

    <comp:add value="Home" />

    <comp:add value="Basic Page" />

    <comp:add value="First Portal" />

  </comp:putList>

  <comp:putList name="links" >

    <comp:add value="index.jsp" />

    <comp:add value="basicPage.jsp" />

    <comp:add value="portalPage.jsp" />

  </comp:putList>

</comp:insert>

This component uses another component, submenu.jsp. This later takes a list of items and a list of links as parameters, and shows them in a menu fashion. You will learn later how to write the submenu component. For now, copy it from the original /tutorial/common directory to /common/submenu.jsp

MenuSrc.jsp

Following is the code of this component :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<comp:insert page="/common/menuViewSrc.jsp" flush="true" >

  <comp:putList name="list" >

    <comp:add value="/basicPage.jsp" />

    <comp:add value="/portalPage.jsp" />

    <comp:add value="/portal/portalBody.jsp" />

    <comp:add value="/common/header.jsp" />

    <comp:add value="/common/menu.jsp" />

    <comp:add value="/common/footer.jsp" />

    <comp:add value="/layout/classicLayout.jsp" />

    <comp:add value="/layout/vboxLayout.jsp" />

  </comp:putList>

</comp:insert>

This component uses another component, menuSrc.jsp. This later takes a list of pages URLs, and shows links pointing to a component writing source of an URL. You will learn later how to write needed components. For now, copy them (viewSrc.jsp; viewSrcBody.jsp, menuViewSrc.jsp) from the original /tutorial/common directory to /common/.

4.3.2      Set up web page

You can now use your new menu.

Edit the /portalPage.jsp , and specify the path to your new menu :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<comp:insert page="/layout/classicLayout.jsp" flush="true">

  <comp:put name="title"  value="My First Portal Page" />

  <comp:put name="header" value="/common/header.jsp" />

  <comp:put name="footer" value="/common/footer.jsp" />

  <comp:put name="menu"   value="/common/menu.jsp" />

  <comp:put name="body"   value="/portal/portalBody.jsp" />

</comp:insert>

 

Check result by pointing your browser to the page.

You have certainly notice that the vertical boxes example require a lot of small components whose only purpose is to declare parameters used by other components. In the next chapter, we will see how to remove such components, replacing them by definitions declared in a central file.

5         Definitions

 Note 1 : In previous Components versions, Definitions was called Instances.

Note 2 : It is now possible to define a Definition into a jsp page (not yet described in tutorial. See comps-doc/test/testDefinition.jsp for an example).

 

A component definition is a component associated with parameters, and identified by a definition name.

Definitions allow to :

  • Centralize declaration of page description
  • Avoid repetitive declaration of nearly the same pages (by using definitions inheritance)
  • Avoid creation of intermediate components used to pass parameters
  • Specify the name of a definition as forward in the struts-config file
  • Specify the name of a definition as component parameters
  • Overload definition attributes
  • Use a different copy of a component, depending on the local (i18n)
  • Use a different copy of a component, depending on a key like the channel (see multi-channels)

Definitions are declared in a description file in XML. You can place this file anywhere and call it as you want, but its preferred place is under WEB-INF/componentDefinitions.xml. There is a DTD for this file, located in lib/components-config.dtd. Actually, parser doesn?t use the dtd to validate file.

5.1      Declare Definitions

Create a new file, and save it under WEB-INF/componentDefinitions.xml (You can erase any existing file with this name if any).

Write or copy following line of code :

<!-- html definition Mappings  -->

 

<component-definitions>

 

  <!-- Definition description  -->

  <definition name="myFirstDefinition" path="/layout/classicLayout.jsp">

         <put name="title"  value="My First Definition Page" />

         <put name="header" value="/common/header.jsp" />

         <put name="footer" value="/common/footer.jsp" />

         <put name="menu"   value="/common/menu.jsp" />

         <put name="body"   value="/basic/hello.jsp" />

  </definition>

 

</component-definitions>

This declares a definition called myFirstDefinition, using component /layout/classicLayout.jsp.

Definition declaration syntax is nearly the same as including a component with parameters. You must specify a name, and the path of the component that you defined. After that, you can add all parameters that you need. Here, we pass all required parameters, but it is possible to pass only some of them.

5.2      Use Definitions

To use a definition in a web page, you include it with the insert tag.

You will see later that you can also use definitions as component parameters or as forward in the struts-config file.

5.2.1      Insert Definition

Create a new file, and save it under definitionPage.jsp.

Write following lines :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<comp:insert definition="myFirstDefinition" flush="true" />

These lines include specified component definition.

Web server look in its definitions list declaration for requested definition, and then call this definition.

In order to work, the definitions list must be initialized. You will learn how in a few moment.

5.2.2      Override Parameters

You can override any parameters of a definition. For example, override the title parameter as following :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<comp:insert definition="myFirstDefinition" flush="true" >

  <comp:put name="title" value="My First Definition With Overloaded Title" />

</comp:insert>

In fact, overriding a parameter as the same syntax as passing parameter.

Overriding parameter is often used to specify the body and title used by a new page.

Overriding parameter can also be done in the definition description file.

5.3      Set Web Application Configuration

Before using definitions in a page, you need to load the definitions list in your application. Using a special servlet, extending the Struts ?action servlet?, can do this.

Edit the WEB-INF/web.xml file, and add following lines :

   ? 

<!-- Action Servlet Configuration -->

  <servlet>

    <servlet-name>action</servlet-name>

    <servlet-class>s1.struts.component.ActionComponentServlet</servlet-class>

    <init-param>

      <param-name>definitions-config</param-name>

      <param-value>/WEB-INF/componentDefinitions.xml</param-value>

    </init-param>

    <init-param>

      <param-name>definitions-debug</param-name>

      <param-value>1</param-value>

    </init-param>

    <init-param>

      <param-name>config</param-name>

      <param-value>/WEB-INF/action.xml</param-value>

    </init-param>

    <init-param>

      <param-name>debug</param-name>

      <param-value>2</param-value>

    </init-param>

    <init-param>

      <param-name>detail</param-name>

      <param-value>2</param-value>

    </init-param>

    <load-on-startup>2</load-on-startup>

  </servlet>

   ?

If you already have a servlet called ?action?, replace it with the one provided.

These lines declare a servlet called action, which is a definition of ?s1.struts.component.ActionComponentServlet?. This servlet extends Struts servlet by adding definitions capabilities. All struts parameters still work. There is  additional optional parameters :

  • ?definitions-config?, which specifies the name of the definitions file. If not specified, ?/WEB-INF/componentDefinitions.xml? file will be used, if exist.
  • ?definitions-debug?, which specifies debug level. ?0? (default) means no debug information will be output, ?1? means debug information.

Now you can try your first definition page : restart the web server, and point your browser on definitionPage.jsp.

Warning : in the current version (010429), the definition description file is not automatically reloaded. This mean that you have to restart the server each time you change the description file. This will change in future versions.

5.4      Definitions as Component Parameters

A definition name can be used as parameter of a component, as long as this parameter is used to include something.

As an example, we will rewrite our previous portal page entirely by using definitions, with some passed as component parameters.

We first need to declare the portal definition, and then describe the menu and the portal body.

5.4.1      Portal Definition

Definition declaration is done in the componentDefinitions.xml file. Declare the portal definition as following :

  ?

 <!-- Main Layout Definition description  -->

  <definition name="mainLayout" path="/layout/classicLayout.jsp">

         <put name="title"  value="World Financial Online" />

         <put name="header" value="/common/header.jsp" />

         <put name="footer" value="/common/footer.jsp" />

         <put name="menu"   value="menu.main" />

         <put name="body"   value="main.portal.body" />

  </definition>

  ?

You can note that values of menu and body attributes are not URLs. They are definition names that we now need to define.

5.4.2      Portal Body Definition

You can write the portal body definition as following :

   ?

   <!-- Portal Body declaration-->

  <definition name="main.portal.body" path="/layout/columnsLayout.jsp">

         <put name="numCols" value="2" />

         <putList name="list0" >

           <add value="/portal/login.jsp" />

           <add value="/portal/messages.jsp" />

           <add value="/portal/newsFeed.jsp" />

           <add value="/portal/advert2.jsp" />

         </putList>

         <putList name="list1" >

           <add value="/portal/advert3.jsp" />

           <add value="/portal/stocks.jsp" />

           <add value="/portal/whatsNew.jsp" />

           <add value="/portal/personalLinks.jsp" />

           <add value="/portal/search.jsp" />

         </putList>

  </definition>

   ?

 This declares a definition of columnsLayout, with specified parameters. You can see that the syntax is similar as the declaration in the jsp file.

5.4.3      Menu Definitions

You will now rewrite menu as definitions. Remember : the main menu is made of logo menu, links menu and sources menu. Links menu uses submenu.jsp components, and sources menu uses menuViewSrc.jsp component.

Main Menu

Following is the code of definition :

  ?

  <!-- Main menu definition -->

<definition name="menu.main" path="/layout/vboxLayout.jsp" >

  <putList name="componentsList" >

    <add value="menu.logo" />

    <add value="menu.links" />

    <add value="menu.src" />

  </putList>

</definition>

  ?

Again, definition declaration is similar to declaration in the jsp file. But now, you don?t need the intermediate component anymore.

Menu Logo

Following is the code of definition :

  ?

  <!-- menu logo definition -->

<definition name="menu.logo" path="/common/menu/menuLogo.jsp" />

  ?

Here, we include the menuLogo.jsp file. Note that there are no parameters.

In fact it is possible to specify directly the file to use in the menu.main definition.

Another possibility is to define a component taking an image URL as parameter, and showing this image. Try to write it as an example !

Menu Links

Here again, definition code is similar as component code :

  ?

  <!-- menu logo definition -->

<definition name="menu.links" path="/common/submenu.jsp" >

  <put name="title" value="Main Menu" />

  <putList name="items" >

    <add value="Home" />

    <add value="Basic Page" />

    <add value="First Portal" />

    <add value="First Definition" />

    <add value="Overloaded Definition" />

    <add value="Extended Definition" />

  </putList>

  <putList name="links" >

    <add value="index.jsp" />

    <add value="basicPage.jsp" />

    <add value="portalPage.jsp" />

    <add value="firstDefinition.jsp" />

    <add value="overloadedDefinitionParameters.jsp" />

    <add value="extendedDefinition.jsp" />

  </putList>

</definition>

  ?

If you want to add entry, you need to add entry name, and corresponding URL.

Menu Sources

Following is an abstract of the menu source definition :

   ?

  <!-- Menu sources definition -->

<definition name="menu.src" path="/common/menuSrc.jsp" >

  <putList name="list" >

    <add value="index.jsp" />

    <add value="basicPage.jsp" />

    <add value="portalPage.jsp" />

    <add value="firstDefinition.jsp" />

    <add value="overloadedDefinitionParameters.jsp" />

    <add value="extendedDefinition.jsp" />

    <add value="/WEB-INF/componentDefinitions.xml" />

 

    <add value="/basic/myLayout.jsp" />

   

    <add value="/layout/classicLayout.jsp" />

    <add value="/layout/columnsLayout.jsp" />

    <add value="/layout/vboxLayout.jsp" />

  

  </putList>

</definition>

   ?

You can add entry by adding its URL.

5.4.4      Try Your Definition

You are now ready to try your definition :

Write a JSP page including it, restart the server, and point your browser on the page.

Create a new file and save it under index.jsp :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<comp:insert definition="mainLayout" flush="true" />

5.5      Extended Definitions

You can do inheritance with definitions. This means that a definition can extends another definition, inheriting all attributes defined in the parent. Of course, child can overload any of the attributes.

As an example, you will extend the mainLayout definition, changing the body and the title. As body, you will use one of the portal components.

Your definition declaration looks like following :

  ?

  <!-- Extended definition example -->

<definition name="extended.definition.example" extends="mainLayout" >

  <put name="title" value="Extended Definition" />

  <put name="body"  value="/portal/newsFeed.jsp" />

</definition>

  ?

You declare a definition, specifying its name, and the name of  the definition that it extends. For that, you use extends=?definitionName?.

To try your extended definition, you need to create a web page including the definition. Create a new file and save it under extendedDefinition.jsp :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<comp:insert definition="extended.definition.example" flush="true" />

5.6      Definitions as Forward

Definitions can be used as forward targets in the struts-config.xml file.

As an example, you will write a page with two buttons : success and failure. A form, associated to a Struts action, surrounds these buttons. The Struts action forwards to a logical name, success or failure.

5.6.1      Form page

You first need to write the form page. In fact, you will write the body, declare a definition, and write a page including this definition.

Body

Create a new file and save it under forward/forwardBody.jsp :

<form action="forwardExampleAction.do">

Select an action :

<br><input type="submit" name="success" value="success">

<br><input type="submit" name="failure" value="failure">

</form>

This file contains a form with two buttons. You can use Struts tag form instead.

Definition

Declare a new definition including this body :

  ?

  <!-- Struts forward definition example -->

<definition name="forward.example.choice.page" extends="mainLayout" >

  <put name="title" value="Struts Forward Test" />

  <put name="body"  value="/forward/forwardBody.jsp" />

</definition>

  ?

Page

Write a page including this definition.

Create a new file and save it under /strutsForward.jsp :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<comp:insert definition="forward.example.choice.page" flush="true" />

You can try the page, but you still need to write the Struts action before submitting !

5.6.2      Struts Action

Struts action is a java class. Following is an abstract of the code of this class :

public class ForwardExampleAction extends Action {

 

    public ActionForward perform(

                            ActionMapping mapping,

                            ActionForm form,

                            HttpServletRequest request,

                            HttpServletResponse response)

       throws IOException, ServletException

    {

    String success = request.getParameter( "success" );

    if( success != null )

           return (mapping.findForward("success"));

 

    return (mapping.findForward("failure"));

    }

 

 }

You can find complete code in documentation. For now, you have nothing particular to do, because compile class is included in components.jar.

5.6.3      Struts Configuration File

You need to setup the Struts configuration file, in order to register the new action.

Add something like following in the action.xml or struts-config.xml :

  <!-- Global Forward Declarations -->

    <forward   name="failure" path="forward.example.failure.page"/>

 

  <!-- struts forward example -->

  <action     path="/forwardExampleAction"

       actionClass="s1.struts.example.tutorial.ForwardExampleAction">

      <forward name="success" path="forward.example.success.page"/>

  </action>

  ?

If you use the struts-config.xml file, you need to put the global forward between <global-forwards> and </global-forwards>.

You can note that the forwards? paths specified definitions, rather than URLs.

Now you need to declare these two definitions.

5.6.4      Definition Declarations

Declare the success and failure definitions :

  <!-- Struts forward definition example -->

<definition name="forward.example.success.page" extends="mainLayout" >

  <put name="title" value="Struts Forward to 'success'" />

  <put name="body"  value="/forward/successBody.jsp" />

</definition>

 

  <!-- Struts forward definition example -->

<definition name="forward.example.failure.page" extends="mainLayout" >

  <put name="title" value="Struts Forward to 'failure'" />

  <put name="body"  value="/forward/failureBody.jsp" />

</definition>

  ?

Write the corresponding bodies.

Create a new file and save it under /forward/successBody.jsp :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

  Struts forward to ?success?.

 <br>

<comp:insert page="/forward/forwardBody.jsp" flush="true" />

Create a new file and save it under /forward/failureBody.jsp :

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

  Struts forward to 'failure'.

 <br>

<comp:insert page="/forward/forwardBody.jsp" flush="true" />

 Note that you don?t need to write pages including the success or failure definitions. Inclusion is done directly by the value returned by Struts action.

5.6.5      Try Your Page

You can now try the new page. Restart the web server to reload definitions.

Point your browser on /strutsForward.jsp, and click on one button.

6         Write More Complex Components

It?s now time to write more complex components. You have already used such components : classicLayout, submenu, viewSrc, ?

Such components are intelligent components containing some logic. You can put logic inside a component, as long as it is UI logic. You must avoid some business logic inside a component.

6.1      Submenu Component

Covered topics : dynamic component, passing list as parameters, using list in components, using conditional tags.

 

Submenu takes as parameters : a list of items, a list of links corresponding to items, a title and value of selected item. It shows the title, followed by items. When you click on an item, you follow corresponding link. If selected value correspond to one item, this item is disable (no link).

Create a new file and save it under common/submenu.jsp.

6.1.1      Iterate on List

First, you will show the list of items. Create a table with two rows. In the first row, write the title parameter. Around the second row, place ?iterate? tags, and write the iteration value in the row.

Code is as following :

<%@ taglib uri="/WEB-INF/struts.tld" prefix="struts" %>

<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

<%@ page import="java.util.Iterator" %>

 

 

<%-- Push component attributes in page context --%>

<comp:importAttribute />

 

<table>

<tr bgcolor="blue">

  <td width="120" valign="top" colspan="2">

    <bean:write name="title"/>

  </td>

</tr>

 

<%-- Prepare the links list to be iterated --%>

<bean:define id="links" name="links" type="java.util.List" scope="page" />

<% Iterator i = links.iterator(); %>

 

<%-- iterate on items list --%>

<logic:iterate id="item" name="items" type="String" >

<tr>

  <td width="10" valign="top" ></td>

  <td valign="top"  >

    <font size="-1">

      <a href="<%=request.getContextPath()%>/<%=i.next()%>"><%=item%></a>

    </font>

  </td>

</tr>

</logic:iterate>

 

</table>

You start by importing components attributes (items, links, title, selected) to the page context. This allows you to use such attributes.

Then, you show the title, and you iterate on each items. As you can iterate only on one list with the iteration tag, you need to iterate yourself on second list. It is why you declare an ?Iterator i?.

6.1.2      Conditional code

One specification is to disable link on selected item.

You need to check if an item is equal to ?selected? value, and write appropriate value.

Your code become :

   ?

<%-- iterate on items list --%>

<logic:iterate id="item" name="items" type="String" >

<tr>

  <td width="10" valign="top" ></td>

  <td valign="top"  >

    <%-- check if selected --%>

       <logic:notEqual name="selected" value="<%=item%>">

         <font size="-1">

            <a href="<%=request.getContextPath()%>/<%=i.next()%>"><%=item%></a></font>

          </logic:notEqual>

       <logic:equal name="selected" value="<%=item%>">

         <font size="-1" color="fuchsia"><%=item%></font>

       </logic:equal>

  </td>

</tr>

</logic:iterate>

   ?

 

6.1.3      Check Parameters Presence

The specification says that title and selected are optional. So, you need to check their presence. For that, you use Struts tags ?present? and ?notPresent?.

Check for title presence, and show it only if present.

Check for selected presence, and declare a dummy selected variable if not.

Your code must be changed to :

 ?

<table>

<logic:present name="title">

<tr bgcolor="blue">

  <td width="120" valign="top" colspan="2">

    <bean:write name="title"/>

  </td>

</tr>

</logic:present>

 

<logic:notPresent name="selected" >

  <% pageContext.setAttribute( "selected", "" ); %>

</logic:notPresent>

 ?

 

6.2      View Sources Component

[to do 001115]

You can check code in   /common/menuViewSrc.jsp. Nearly the same as submenu.

6.3      Body Including Twice the Same Component

Covered topics : use of sub-component in a component.

 

In this chapter you will learn how to write components that can be reused more than one time in a page. As example, we develop an ?address? component, included two times in an ?invoice?.

Problems come when you have input fields in the address component : how to have two different names while using one component description ? As a solution, you will provide names prefixed with a component?s name. This later is passed as a parameter of the component.

Second difficulty is how to retrieve data to be shown in the address component ? Here, you will pass a Java object of class ?Address?, and deal with it in the address component.

All Java classes are already written and compiled for you. You can check sources from the Component Library distribution, under directory src/s1/example/invoice.

6.3.1      Address Component

Create a new file and save it under invoice/editAddress.jsp.

In this file, create a table with two columns : one containing fields names, one containing html input fields. Use Struts tags ?text? for the input fields.

Following is the code for this component :

<%@ taglib uri="/WEB-INF/components.tld"    prefix="comp" %>

<%@ taglib uri="/WEB-INF/extensions.tld"    prefix="ext" %>

<%@ taglib uri="/WEB-INF/struts.tld" prefix="struts" %>

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

 

<%-- Edit an Address object

  @param address An address object to edit.

  @param compName UI Component name. Use as prefix for html fields and sub-components

--%>

<%-- Retrieve parameters from component context, and declare them as page variable --%>

<comp:useAttribute id="addr" name="address" scope="page"/>

<comp:useAttribute id="prefix" name="compName" classname="String"/>

<%-- Add a separator tothe component name, in order to have html fields prefix name : 'compName.'--%>

<% prefix = prefix + "."; %>

 

<table border="0" width="100%">

 

  <tr>

    <th align="right" width="30%">

      Street

    </th>

    <td align="left">

         <%-- Declare an html input field.                                                                    --%>

         <%-- We use a tag that extends Struts 'text' tag. This extension add            --%>

         <%-- attribute 'prefix', allowing to give a prefix to the normal name    --%>

         <ext:text name="addr" prefix="<%=prefix%>" property="street1" size="50"/>

    </td>

  </tr>

 

  <tr>

    <th align="right">

      Street (con't)

    </th>

    <td align="left">

        <ext:text prefix="<%=prefix%>" name="addr" property="street2" size="50"/>

    </td>

  </tr>

 

  <tr>

    <th align="right">

      City

    </th>

    <td align="left">

        <ext:text prefix="<%=prefix%>" name="addr" property="city" size="50"/>

    </td>

  </tr>

 

  <tr>

    <th align="right">

      Country

    </th>

    <td align="left">

        <ext:text prefix="<%=prefix%>" name="addr" property="country" size="50"/>

    </td>

  </tr>

 

  <tr>

    <th align="right">

      Zip code

    </th>

    <td align="left">

         <ext:text prefix="<%=prefix%>" name="addr" property="zipCode" size="50"/>

    </td>

  </tr>

 

</table>

In this code, Struts ?struts:text? tags are replaced by ?ext:text? tags. This new tag is an extension of struts one, allowing addition of a prefix to the html input name. This tag will be integrated to Struts one when the Component Library will be.

Prefix is computed at the beginning of the component, just after parameters retrieval.

Name of generated html input tag will be ?compName.fieldname?. This will allows to retrieve value in the controller.

6.3.2      Invoice Component

Create a new file and save it under invoice/editInvoice.jsp.

This invoice contains two times the address component, and two html input fields :

<%@ page language="java" %>

<%@ taglib uri="/WEB-INF/components.tld"    prefix="comp" %>

<%@ taglib uri="/WEB-INF/struts.tld" prefix="struts" %>

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

 

<struts:errors/>

 

<struts:form action="editInvoice.do" name="invoiceForm"

             type="s1.struts.example.invoice.InvoiceForm">

 

<bean:define id="invoiceForm" name="invoiceForm" type="s1.struts.example.invoice.InvoiceForm" />

<h1>Edit Customer Informations</h1>

                       

<table border="0" width="100%">

 

  <tr>

    <th align="right" width="30%">

      First Name

    </th>

    <td align="left">

        <struts:text property="firstname" size="50"/>

    </td>

  </tr>

 

  <tr>

    <th align="right">

      Last Name

    </th>

    <td align="left">

         <struts:text property="lastname" size="50"/>

    </td>

  </tr>

 

 

  <tr>

    <th align="right" >

      Shipping Address

    </th>

    <td align="left">

         &nbsp;

    </td>

  </tr>

  <tr>

    <td align="center" colspan="2">

         <%-- Include an "address editor" component.                 --%>

         <%-- Pass the component name and component value as parameter      --%>

         <comp:insert page="/invoice/editAddress.jsp" >

           <comp:put name="compName" value="shippingAddress" />

           <comp:put name="address" value="<%=invoiceForm.getShippingAddress()%>" />

         </comp:insert>

    </td>

  </tr>

 

  <tr>

    <th align="right" >

      Billing Address

    </th>

    <td align="left">

         &nbsp;

    </td>

  </tr>

  <tr>

    <td align="center" colspan="2">

  <comp:insert page="/invoice/editAddress.jsp" >

    <comp:put name="compName" value="billAddress" />

    <comp:put name="address" value="<%=invoiceForm.getBillAddress()%>" />

  </comp:insert>

    </td>

  </tr>

 

  <tr>

    <td align="right">

        <struts:submit>

          save

        </struts:submit>

        <struts:submit>

          confirm

        </struts:submit>

    </td>

    <td align="left">

        <struts:reset>

          reset

        </struts:reset>

      &nbsp;

      <struts:cancel>

        cancel

      </struts:cancel>

    </td>

  </tr>

</table>

                       

</struts:form>

You include an address component where you want it to reside. You pass it its name, and the Java object containing values. This object comes from ?invoiceForm? object, and is retrieved using getter method. Don?t forget to provide two different name for each component included !

6.3.3      Try Your Page

You can use your edit invoice form in a page using main layout.

Create a new file and save it under invoice/index.jsp.

<%@ taglib uri="/WEB-INF/components.tld" prefix="comp" %>

 

<comp:insert definition="mainLayout" flush="true">

  <comp:put name="body" value="/invoice/editInvoice.jsp" />

</comp:insert>

 

7         Internationalization (i18n)

Covered topics : use of i18n description files.

 

Components Library allows having different copies of a component, each one suited for a language or locale. When the component is included, the appropriate copy is chosen.

Now come the problems : where to put copies ? There are two main approaches :

  • Put them in the same directory that the component, and add language code as suffix (_fr, _en, ?).
  • Put them in a separate directory, named with the language code (/fr/., /en/., ?).

Each approach has advantage and drawbacks, depending of your application. So we have chosen to let yourself determine where to place copies.

The Component i18n mechanism let you write different definitions file, one for each language. Choice of the appropriate definition file is done following the same rules as the Java properties bundle, adding language suffix to file name. You must write a default definition file, and you can write copies of this file, each copy name suffixed by the language code.

In a copy, you don?t need to rewrite all definition descriptions : you just rewrite definitions that differ. All copies automatically inherit from the default definition file.

 

This i18n mechanism is intended to be a complement of the key-properties bundle provided by Struts. You should use it when you have big components to internationalize. If you have only small sentences or words, use the key mechanism. Both mechanisms can be used in one site.

Let see how all this work on an example : you will add a new menu giving choice between several languages. When you change language, the menu change, displaying only the other possible languages. Titles of some pages also change. This is not a real i18n example : it just illustrates how we can do.

You will start by writing the new menu, and add it to the main menu. This menu is linked to a Struts action switching the user Locale object. Then, you will write copies of the definitions file.

7.1      Select Language Menu

This menu shows different available languages. You will write it has a definition using a submenu component :

  <!-- -->

<definition name="menu.lang" path="/common/submenu.jsp" >

  <put name="title" value="Langue" />

  <putList name="items" >

    <add value="Francais" />

    <add value="English" />

    <add value="Deutch" />

  </putList>

  <putList name="links" >

    <add value="lang.do?language=FR" />

    <add value="lang.do?language=UK" />

    <add value="lang.do?language=DE" />

  </putList>

</definition>

 

You specify the item names, and the corresponding URLs. Here, items are linked to a Struts action switching the current language.

Don?t forget to add the new sub-menu to the main menu definition :

  <!-- Main menu definition -->

<definition name="menu.main" path="/layout/vboxLayout.jsp" >

  <putList name="componentsList" >

    <add value="menu.logo" />

    <add value="menu.links" />

    <add value="menu.src" />

    <add value="menu.lang" />

  </putList>

</definition>

7.2      Select Language Action

The action Java code is as follow :

public final class SelectLocaleAction extends Action {

 

    public ActionForward perform(

                            ActionMapping mapping,

                            ActionForm form,

                            HttpServletRequest request,

                            HttpServletResponse response)

       throws IOException, ServletException {

 

       // Extract parameters we will need

    String requested = (String)request.getParameter( "language" );

 

    if( requested == null )

           return (mapping.findForward("failed"));

    if( requested.equalsIgnoreCase( "FR" ) )

      setLocale( request, Locale.FRANCE );

    if( requested.equalsIgnoreCase( "UK" ) )

      setLocale( request, Locale.UK );

    if( requested.equalsIgnoreCase( "DE" ) )

      setLocale( request, Locale.GERMAN );

 

    return (mapping.findForward("success"));

    }

 

    protected void setLocale( HttpServletRequest request, Locale locale )

      {

      HttpSession session = request.getSession(false);

      if (session != null)

        session.setAttribute(Action.LOCALE_KEY, locale);

      }

}

It could certainly be improved, but it is not the purpose of this tutorial. It simply checks requested language, and set the user locale attribute appropriately (under the name defined by Action.LOCALE_KEY).

You can now try your pages, but nothing new happens because you need to define localized copies of definitions description file.

7.3      Localized Definition Descriptions Files

You can write a definitions file for each of your languages. Remember that you must have a default file (with no language code suffix).

It is better to start from a new empty file, as you don?t need to rewrite all definitions.

Create a new file and save it under WEB-INF/componentDefinitions_fr.xml.

Copy the menu.lang definition from the default file. Translate title value and erase the ?French? items and its link.

Also copy the mainLayout definition from the default file. Translate title, and change footer value to ?/fr/common/footer.jsp?. Also write such file.

Your definition description file should looks like :

<!-- html definition Mappings  -->

<component-definitions>

 

  <!-- Main Layout Definition description  -->

  <definition name="mainLayout" path="/layout/classicLayout.jsp">

         <put name="title"  value="Le Monde Financier En Ligne" />

         <put name="header" value="/common/header.jsp" />

         <put name="footer" value="/fr/common/footer.jsp" />

         <put name="menu"   value="menu.main" />

         <put name="body"   value="main.portal.body" />

  </definition>

 

  <!-- select language menu -->

<definition name="menu.lang" path="/common/submenu.jsp" >

  <put name="title" value="Langue" />

  <putList name="items" >

    <add value="English" />

    <add value="Deutch" />

  </putList>

  <putList name="links" >

    <add value="lang.do?language=UK" />

    <add value="lang.do?language=DE" />

  </putList>

</definition>

 

</component-definitions>

Do the same for others language.

7.4      Try Your Pages

You can now try your i18n pages. Point your browser on the index.jsp page, and select another language. Watch the window title, and the footer.

In the menu, select a page extending the mainLayout definition, like ?Extended Definition?. Check the footer : it is the one defined by mainLayout definition in the localized description file because shown definition extends mainLayout.

8         Multi-Channels

The same mechanism than i18n can be used for channels (wml, different browser support, ?). Each channel components are written under a different directory.

Work in progress. Example available in comps-channel.war.

The idea for channel system is to write another definition factory that will choose the component to insert according to the provided definition name, and a channel key extracted from wherever you want (value from session, , ?). Actually, factory implementation is clearly separated from the rest. If you are interested, you can write your own factory. It needs to implement ComponentDefinitionsFactory.java (1 method). You can let ComponentActionServlet create your factory by setting the servlet init parameter definitions-factory-class to the name of your factory. You can also define init parameters for your factory. They will be passed in a Map. Again, check example in comps-channel.war.

 

 

 


Copyright © 2000, Apache Software Foundation
and S1 Corporation