Author : Cedric Dumoulin
Date : 14 Nov. 2000
Table of Content
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:
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.
Your first page is a simple page that will be improved later in this tutorial.
Your first page look like the following picture :
It is divided in header, footer, menu and body. Such division identifies our main components :
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.
Covered topics : write simple components; the “html link” problem.
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 :
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.
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 :
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]
The footer contains company copyrights.
Create a new file, and save it under common/footer.jsp.
Write copyrights notice, as in following :
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 :
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 :
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.
To pass parameters to the component that will do the layout, you write something like that :
Or like the following, which is the same, but looks like more familiar to people already using Struts Template :
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.
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 :
Note : This layout contains <html>, <head> and <body> tags. This component is used to define the html page.
Now, you will insert (include) components by using special tags.
Put the following code at the beginning of your page :
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 :
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 :
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 :
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.
Following is the complete code for your first layout component :
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.
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.
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 :
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 !
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.
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” ).
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 :
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).
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 :
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.
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.
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 :
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.
Following is the code of this component :
Following is the code of this component :
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
Following is the code of this component :
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/.
You can now use your new menu.
Edit the /portalPage.jsp , and specify the path to your new menu :
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.
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 :
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.
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 :
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.
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.
Create a new file, and save it under definitionPage.jsp.
Write following lines :
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.
You can override any parameters of a definition. For example, override the title parameter as following :
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.
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 :
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 :
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.
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.
Definition declaration is done in the componentDefinitions.xml file. Declare the portal definition as following :
You can note that values of menu and body attributes are not URLs. They are definition names that we now need to define.
You can write the portal body definition as following :
This declares a definition of columnsLayout, with specified parameters. You can see that the syntax is similar as the declaration in the jsp file.
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.
Following is the code of definition :
Again, definition declaration is similar to declaration in the jsp file. But now, you don’t need the intermediate component anymore.
Following is the code of definition :
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 !
Here again, definition code is similar as component code :
If you want to add entry, you need to add entry name, and corresponding URL.
Following is an abstract of the menu source definition :
You can add entry by adding its URL.
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 :
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 :
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 :
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.
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.
Create a new file and save it under forward/forwardBody.jsp :
This file contains a form with two buttons. You can use Struts tag form instead.
Declare a new definition including this body :
Write a page including this definition.
Create a new file and save it under /strutsForward.jsp :
You can try the page, but you still need to write the Struts action before submitting !
Struts action is a java class. Following is an abstract of the code of this class :
You can find complete code in documentation. For now, you have nothing particular to do, because compile class is included in components.jar.
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 :
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.
Declare the success and failure definitions :
Write the corresponding bodies.
Create a new file and save it under /forward/successBody.jsp :
Create a new file and save it under /forward/failureBody.jsp :
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.
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.
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.
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.
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 :
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”.
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 :
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 :
[to do 001115]
You can check code in /common/menuViewSrc.jsp. Nearly the same as submenu.
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.
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 :
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.
Create a new file and save it under invoice/editInvoice.jsp.
This invoice contains two times the address component, and two html input fields :
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 !
You can use your edit invoice form in a page using main layout.
Create a new file and save it under invoice/index.jsp.
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 :
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.
This menu shows different available languages. You will write it has a definition using a submenu component :
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 :
The action Java code is as follow :
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.
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 :
Do the same for others language.
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.
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.