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

Author : Cedric Dumoulin

Date : 22 Sep. 2000

Rev : 16 Nov. 2000

 

Warning : This document is not ?up to date?. Start with the tutorial instead.

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

 

1         Goals

We want to be able to build web pages by assembling components. There are two kinds of components : coarse grain components and fine grain components. Coarse grain components are components made of several html instructions. For example, a component rendering an address or a header is a coarse grain component. Examples of fine grain components are an input/output field performing I18n formatting, a popup menu, ... For now, we only focus on coarse grain components.

Following are the main goals that we want to reach :

  • Reusable : it must be possible to write component that are reused in different pages
  • Independent : A component must be, as much as possible, independent from its ?parent? (the entity that use the component).
  • Build complex pages (like portal) by assembling components. 
    • Divide the complexity of the page in smaller components
    • Focus on each component independently, without care on other components.
    • Focus on assembling, or layout, components without care on component content.
  • Have consistent web site ?look and feel? by providing some common ?layout components?, and assembling common components like header, menu, footer, ?
  • Perform changes on all pages by only changing concerned component.
    • For example, change all menus or headers by only changing the concerned component. No need changes in each page.
  • Be able to modify pages composition, or components content from a central point, like a description file.
  • Have a library of common components. Don?t rewrite them (or copy/paste) each time.
    • Improvement in one component will be propagated to all pages using this component (not so easy with copy/paste).
  • A component can be made by assembling other component.
  • Simple to understand and use
    • Preferably, component is describe in a JSP file.
  • Fit in JSP and Struts philosophy.

 

 

2         Proposed Architecture

 

Following illustrate how we want to build a page by assembling components :

 

The page is made of a header, a menu and a body. Body itself is made of two others components. This is a simple example, and we want to be able to build more complex pages.


The servlet ?include? mechanism already responds to some of our goals. But, in order to reach them completely, we need some additional materials.

Basically, a component is a JSP file that will be included in another file or component. We associate to component a ?component context?, helping passing parameters. Component contexts, and parameters, are only visible inside the components. They are not visible by others sub-components, neither by parents.

Coarse grain component can be seen like a java method : you include / call the component, passing it some parameters. Unlike method, component can?t return something.

A component can be developed independently from its caller. You just have to specify which parameters are needed. This independence allows developing reusable components.

2.1      Why adding a Context ?

Component context contains properties associated to component, and only accessible by this component. Parent including a component can set properties.

Context is needed in order to be able to have independent component : like this, you don?t have to care if a component attribute (parameter) has the same name as another JSP attribute.

One can say that component context is the same as the jsp ?page scope?. This is partially true : jsp ?page scope? doesn?t allows addition of  attributes outside the page, which forbid passing parameters from parent.

Furthermore, context will be used for future features, like associating JavaScript to a component.

 

3         Usage

3.1      Writing a Component

As a component is a JSP file, all facilities provided by JSP can be used to write the component. In addition, the component can access its parameters, provided by its ?parent?.

Following is an example of component :

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

 

<br> This is a component

<br> It uses properties passed by its parent

<br> title = <comp:getAttribute name=?title? />

<br> This component has index number <comp:getAttribute name=?index? />

<br> That?s all folks !

This example is not very useful, it just illustrate how component work.

[todo : write a more realistic example]

3.2      Including a Component

A component can be included anywhere in a page or in another component. You need to use a special include tag, allowing passing parameters.

For example, to include previous component, write something like that :

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

   ?

<comp:include page=?comp.jsp?>

  <comp:putAttribute name=?title? value=?Welcome?>

  <comp:putAttribute name=?index? value=?3?>

</comp:include>

   ?

 

3.3      Assembling Components : Layout Containers

There is nothing special to assemble components : you do it by including each component where you want it to reside.

A component used to layout other components can be call a ?Layout Container?. We will define a set of basic layout containers, and reuse them whenever needed.

Examples of layout containers are :

o       Header-menu-footer-body container

o       Define a classical page

o       Grid container

o       Layout components in a fixed grid (table ?).

o       Box container

o       Components are ?stacked? (horizontally or vertically)

o       Flow container

o       Components are rendered one after the other.

o       Columns container

o       Layout components in columns. You need to provide lists of components and the number of columns.

o       ?

Following is the code for the header-menu-footer-body container. Note that in this file, we only focus on the layout of components, not on their contents.

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

 

<%--   parameters : title, header, menu, body, footer

--%>

<comp:useAttribute name="title" classname="String" />

<HTML>

  <HEAD>

    <title<comp:include attribute='title'/></title>

  </HEAD>

 

<body>

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

<tr><td colspan="2"><comp:include attribute="header" /></td></tr>

<tr><td colspan="2"><hr></td></tr>

<tr>

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

    <comp:include attribute='menu'/>

  </td>

  <td valign="top">

    <comp:include attribute='body' />

  </td>

</tr>

<tr><td colspan="2"><hr></td></tr>

<tr><td colspan="2"><comp:include attribute="footer" /></td></tr>

</table>

</body>

</html>

To use this container/component, include it and pass needed parameters, as in the example :

<%@ page language="java" %>

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

 

<comp:include component="/layout/classicLayout.jsp" flush="true">

  <comp:putAttribute name="title"  value="index.title" />

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

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

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

  <comp:putAttribute name="body"   value="/bodies/index.jsp" />

</comp:include> 

 

3.4      Instances

Components usually require some arguments to work properly. We provide a way to associate predefined arguments to a component. This association is a kind of ?instance? of a component. Such instance is referenced by a name which can be used in include tags or in forward directives in struts-config.xml.

It is possible to declare a component instance, and use the same instance at different place.

3.4.1      Instances Declarations

All component instance declarations are done in a XML file. Syntax is similar as the one used in include tag. Following is an example of declaration :

  <component-instances>

 

  <!? Page instance description  -->

  <instance name="portal" path="classicLayout.jsp">

    <putAttribute name="title"  value="Welcome to our Portal Demo" />

    <putAttribute name="header" value="header.jsp" />

    <putAttribute name="footer" value="footer.jsp" />

    <putAttribute name="menu"   value="menu.jsp" />

    <putAttribute name="body"   value="body.jsp" />

  </instance>

  ?

</component-instances>

 

 You can see that the declaration is very similar than including a component. The declared name will be the instance name, and will allow you to identify the instance.

One XML file can contains several declarations. This allows easy modification of your instances.

3.4.2      Instance Inclusion

Using a component instance is similar as using a component : you specify where you want to include your instance, like in the following example :

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

 

<%-- Example of instance inclusion --%>

<comp:include instance="portal" flush="true"/>

In the include tag, you specify the name of the instance you want to include.

3.4.3      Incomplete Instance

In the instance description file, you can partially instanciate a component, specifying only some of the parameters. Others parameters must be passed when including component.

You can also provide parameters in the description file, and override them while including instance. This gives default parameters for an instance.

In the following example, we override the title parameter :

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

 

<%-- Example of component instanciation, passing directly parameters --%>

<comp:include instance="portal" flush="true">

  <comp:putAttribute name="title"  value="Overridden title" />

</comp:include>

3.4.4      Instance Name as Parameter

It is possible to pass the name of an instance as another instance parameter.

In following example, portal?s menu is itself an instance of menu.jsp.

<component-instances>

   ?

  <!-- Page instance description  -->

  <instance name="portal" path="classicLayout.jsp">

    <putAttribute name="title"  value="Welcome to our Portal Demo" />

    <putAttribute name="header" value="header.jsp" />

    <putAttribute name="footer" value="footer.jsp" />

    <putAttribute name="menu"   value="portalMenu" />

    <putAttribute name="body"   value="body.jsp" />

  </instance>

   ?

  <!-- Component instance description  -->

  <instance name="portalMenu" path="menu.jsp">

    <putAttribute name="index" value="2" />

    <putAttribute name="title" value="Portal Menu" />

  </instance>

</component-instances>

 

With this mechanism, we can have a ?more generic? menu, requiring more parameters (menu title, index), and have specific instance of this component (portalMenu, userMenu, ?).

3.4.5      Instances and Struts

Struts allows to specify ?forward pages? to be called after a struts action is executed. It could be interesting to be able to specify also component instances.

For that, we provide a servlet extending the original struts servlet, and taking in charge forwarding request to instances, rather than to page. If no instance is found, servlet behavior is the same as the struts one.

To be able to specify instances or pages in ?struts action forward?, simply use the new servlet. In your application web.xml, change your action servlet declaration with something like following :

  <!-- Action Servlet Configuration -->

  <servlet>

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

    <servlet-class>ui.jsp.components.ActionInstancesServlet</servlet-class>

    <init-param>

      <param-name>instances</param-name>

      <param-value>>/WEB-INF/componentInstances.xml </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>

 

 Notes : All struts parameters can still working.

3.4.6      Instances as URL target

Component Instances can describe a final web page, containing <body>?</body> tags. It could be interesting to associate an instance to an URL, allowing all requests sent to this URL to be forwarded to the instance.

3.4.6.1  Simple Approach

The simplest way to do that is to have a jsp file corresponding to the URL, and containing an include tag.

Following is an example including a defined instance.

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

 

<%-- include a component --%>

<comp:include instance="main" flush="true"/>

This example work well, but it need to have the defined instances table initialized (see Include tag syntax).

Next example do the same thing, but instance parameters are defined in the include tag.

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

 

 

<%-- Example of component instanciation, passing directly parameters --%>

<comp:include component="classicLayout.jsp" flush="true">

  <comp:putAttribute name="title"  value="Welcome to our demo" />

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

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

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

  <comp:putAttribute name="body"   value="body.jsp" />

</comp:include>

Comments :

  • Both approaches do the same thing. One require the declared instance table to be initialized.

Advantages :

  • No need for extra mechanism to perform mapping between URL and component instances

Drawbacks :

  • Need to define one jsp file for each URL.

3.4.6.2  Servlet Approach

Another approach consists to have a servlet taking in charge mapping between URLs and Instances.

This servlet could be initialized with a description file, describing mappings, like in following example :

<component-instances>

 

  <!? Url mapping -->

  <mapping url=?index.jsp" instance="main">

</component-instances>

In this approachs, we also need to redirect concerned URL to the servlet. This is done in the application description file (web.xml). Care must be taken to redirect only concerned URLs, and not ?all? urls. For example, one can thing to specify ?*.jsp? while deploying the servlet. This is possible, but need some care : if you do so, all URLs ending in ?.jsp? are sent to the servlet, even those that are forwarded inside the servlet itself ! This could result in an endless recursive call. To avoid this you need, inside servlet, to forward to the original servlet serving ?.jsp?. This is feasible, but is not guaranteed to be portable across jsp servers.

Need more investigation to have a better solution.

4         Examples

4.1      Portal

See example in the portal application

[to do : complete this example]

Following is an example of a Portal  Page made by assembling components.


 


4.2      Include Twice the Same Component

See example in the portal application

[to do : complete this example]

Following schema illustrate how we can build a component or page by including twice the same component.


 


4.3      Struts Example Revisited

See example in the comp-struts and comp-struts-instance application

[to do : complete this example]

5         Installation

See the installation page for detailed installation guide.

Also refer to the Struts framework installation for more helps.

5.1      Requirements

  • Following libraries are required :
    • jaxp.jar, parser.jar, struts.jar, components.jar
  • struts.jar version must be greater than the 0.5 release. Distribution includes a compatible release.
  • Refer to Struts framework installation for others requirements.

5.2      Install Examples

  • Examples come in Web Application Archive (war files). You can install these web applications on any servlet container.
  • For example, with Tomcat, install war files in the webapps directory.
  • Start with ?comp-struts-portal/index.jsp? page.

5.3      Component Instances Installation

All tags using components instances need to find the instances list. Search for the list is done in following order : page, request, session, and then application. You must put the instances list in one of this scope before using such tags.

Usually, list is placed in the application scope, at initialization time.

Typical code look like this :

  String fileName = "/WEB-INF/instances.xml";

  try

    {

    InputStream input = pageContext.getServletContext().getResourceAsStream(fileName);

    if(input == null )

      throw new JspException( "Can't open '"+ fileName + "'");            

    instances = new ComponentInstances( input );

    }

   catch( Exception ex )

    {

    ex.printStackTrace();

    throw new JspException( "Error while creating instances. See console" );

    }

  pageContext.setAttribute(ComponentConstants.COMPONENT_INSTANCES, instances                                                          
                           pageContext.APPLICATION_SCOPE );                                                                      

One possibility is to have an initialization servlet doing that. You can use the provided servlet ComponentActionServlet instead of the Struts original one. See installation page for details.

Another possibility is to use a miscellaneous tag, checking and loading requested list if necessary.

<comp:initComponentInstances file=?instances.xml? scope=?application? />

 

 


Copyright © 2000, Apache Software Foundation
and S1 Corporation