Skip to content

1. General Information

The PDF of the document is available |HERE|.

1.1. Objectives

In this article, we will explore a development framework called Struts. Jakarta Struts is a project of the Apache Software Foundation (www.apache.org) designed to provide a standard framework for developing Java web applications based on the MVC (Model-View-Controller) architecture.

1.2. The MVC Model

The MVC model seeks to separate the presentation, processing, and data access layers. A web application adhering to this model will be structured as follows:

This architecture is called a 3-tier or 3-level architecture:

  • the user interface is the V (the view)
  • the application logic is the C (the controller)
  • the data sources are the M (Model)

The user interface is often a web browser, but it can also be a standalone application that sends HTTP requests to the web service over the network and formats the results it receives. The application logic consists of scripts that process user requests. The data source is often a database, but it can also be simple flat files, an LDAP directory, a remote web service, etc. It is in the developer’s best interest to maintain a high degree of independence between these three entities so that if one of them changes, the other two do not have to change, or only minimally.

When applying this model with servlets and JSP pages, the following architecture results:

In the [Application Logic] block, we distinguish

  • the servlet, which is the application’s entry point and is also called the controller
  • the [Business Classes] block, which contains the Java classes necessary for the application’s logic
  • the [Data Access Classes] block, which contains the Java classes needed to retrieve the data required by the servlet, often persistent data (database, files, web service, etc.)
  • the JSP pages block, which constitutes the application’s views.

1.3. An MVC development approach using servlets and JSP pages

We have defined an approach for developing Java web applications that follows the MVC model described above. We will review it here.

  1. We will begin by defining all the application’s views. These are the web pages presented to the user. We will therefore adopt the user’s perspective when designing the views. There are three types of views:
    • the input form, which is used to obtain information from the user. This form typically includes a button to send the entered information to the server.
    • the response page, which serves only to provide information to the user. This often includes a link allowing the user to continue using the application on another page.
    • the mixed page: the servlet has sent the client a page containing information it generated. This same page will be used by the client to provide the servlet with additional information.
  1. Each view will generate a JSP page. For each of these:
    • we will design the page’s layout
    • we will determine which parts of it are dynamic:
      • the information intended for the user, which must be provided by the servlet as parameters to the JSP view
      • the input data that must be transmitted to the servlet for processing. This data must be part of an HTML form.
  1. We can diagram the I/O for each view
    • Inputs are the data that the servlet must provide to the JSP page, either in the request or the session.
    • Outputs are the data that the JSP page must provide to the servlet. They are part of an HTML form, and the servlet will retrieve them using an operation such as request.getParameter(...).
  1. We will write the Java/JSP code for each view. It will most often take the following form:
<%@ page ... %>    // Class imports (most often)
<%!
    // JSP page instance variables (=global)
    // only necessary if the JSP page has methods that share variables (rare)    
    ...    
%>
<%
    // Retrieving data sent by the servlet
    // either in the request or in the session
    ...
%>

<html>
...
        // Here we will aim to minimize the Java code
</html>
  1. We can then move on to the initial tests. The deployment method explained below is specific to the Tomcat server:
    • The application context must be created in Tomcat’s server.xml file. We can start by testing this context. Let C be this context and DC the folder associated with it. We will create a static file named test.html and place it in the DC folder. After launching Tomcat, we will request the URL http://localhost:8080/DC/test.html in a browser.
    • Every JSP page can be tested. If a JSP page is named formulaire.jsp, we will request the URL http://localhost:8080/DC/formulaire.jsp in a browser. The JSP page expects values from the servlet that calls it. Here, we are calling it directly, so it will not receive the expected parameters. To ensure testing is still possible, we will manually initialize the expected parameters in the JSP page using constants. These initial tests verify that the JSP pages are syntactically correct.
  1. Next, we write the servlet code. It has two distinct methods:
    • the init method, which is used to:
      • retrieve the application’s configuration parameters from its web.xml file
      • potentially create instances of business classes that it will need to use later
      • handling any list of initialization errors that will be returned to future users of the application. This error handling may even include sending an email to the application administrator to notify them of a malfunction
    • the doGet or doPost method, depending on how the servlet receives parameters from its clients. If the servlet handles multiple forms, it is a good practice for each form to send information that uniquely identifies it. This can be done using a hidden attribute in the form of the type <input type="hidden" name="action" value="...">. The servlet can start by reading the value of this parameter and then delegate the processing of the request to a private internal method responsible for handling this type of request.
    • You should avoid putting business logic in the servlet as much as possible. That is not what it is designed for. The servlet acts as a sort of team leader (controller) that receives requests from its clients (web clients) and has them executed by the most appropriate entities (the business classes). When writing the servlet, you will define the interface of the business classes to be created (constructors, methods). This applies if these business classes need to be created. If they already exist, then the servlet must adapt to the existing interface.
    • The servlet code will be compiled.
  1. We will write the skeleton of the business classes required by the servlet. For example, if the servlet uses an object of type proxyArticles and this class must have a getCodes method returning a list (ArrayList) of character strings, we can initially simply write:
public ArrayList getCodes(){
    String[] codes = {"code1", "code2", "code3"};
    ArrayList aCodes = new ArrayList();
    for(int i=0;i<codes.length;i++){
        aCodes.add(codes[i]);
    }
        return aCodes;
}
  1. We can now proceed to testing the servlet.
    • The application's web.xml configuration file must be created. It must contain all the information expected by the servlet's init method (<init-param>). Additionally, we set the URL through which the main servlet will be accessed (<servlet-mapping>).
    • All necessary classes (servlet, business classes) are placed in WEB-INF/classes.
    • All necessary class libraries (.jar) are placed in WEB-INF/lib. These libraries may contain business classes, JDBC drivers, etc.
    • The JSP views are placed in the application root or in a dedicated folder. The same applies to other resources (HTML, images, audio, videos, etc.).
    • Once this is done, the application is tested and the initial errors are corrected. At the end of this phase, the application architecture is operational. This testing phase can be tricky since there is no debugging tool available with Tomcat. For this, Tomcat would need to be integrated into a development tool (JBuilder Developer, Sun One Studio, etc.). You can use System.out.println("....") statements, which write to the Tomcat console. The first thing to check is that the init method successfully retrieves all data from the web.xml file. To do this, we can write the values of these parameters to the Tomcat window. We will similarly verify that the doGet and doPost methods correctly retrieve the parameters from the application’s various HTML forms.

We write the business classes required by the servlet. This generally involves the standard development of a Java class, which is usually independent of any web application. It will first be tested outside this environment, for example with a console application. Once a business class has been written, we can integrate it into the web application’s deployment architecture and test its proper integration within it. This process is repeated for each business class.

1.4. The STRUTS Development Approach

The creators of the STRUTS methodology sought to define a standard development method that adheres to the MVC architecture for web applications written in Java. There are two aspects to the STRUTS project:

  • the development method. We will see that it is quite similar to the one described above for servlets and JSP pages
  • the tools that allow us to apply this development method. These are Java class libraries available on the Apache Foundation website (www.apache.org).

1.4.1. The development method

The MVC architecture used by STRUTS is as follows:

  • The controller is the heart of the application. All client requests pass through it. It is a generic servlet provided by STRUTS. In some cases, you may need to extend it. For simple cases, this is not necessary. This generic servlet retrieves the information it needs from a file most often called struts-config.xml.
  • If the client request contains form parameters, these are placed in a Bean object. A class is said to be of the Bean type if it follows construction rules that we will discuss later. The Bean objects created over time are stored in the client’s session or request. This setting is configurable. They do not need to be recreated if they have already been created.
  • In the struts-config.html configuration file, each URL to be processed by the program (and thus not corresponding to a JSP view that could be requested directly) is associated with certain information:
    • the name of the Action-type class responsible for processing the request. Here again, the instantiated Action object can be stored in the session or request.
    • If the requested URL is parameterized (as when a form is submitted to the controller), the name of the bean responsible for storing the form data is specified.
  • Armed with this information provided by its configuration file, upon receiving a URL request from a client, the controller is able to determine whether a bean needs to be created and which one. Once instantiated, the bean can verify whether the data it has stored—which comes from the form—is valid or not. A method of the bean called `validate` is automatically called by the controller. The bean is built by the developer. The developer therefore places the code that verifies the validity of the form data within the validate method. If the data is found to be invalid, the controller will not proceed further. It will pass control to a view whose name it finds in its configuration file. The interaction is then complete. Note that the developer can choose not to have the form’s validity checked. This is also done in the struts-config.html file. In this case, the controller does not call the bean’s validate method.
  • If the bean’s data is correct, or if there is no validation, or if there is no bean, the controller passes control to the Action object associated with the URL. It does this by calling the execute method of that object, passing it the reference to the bean it may have constructed. This is where the developer does what needs to be done: they may need to call business classes or data access classes. At the end of processing, the Action object returns to the controller the name of the view it must send in response to the client.
  • The controller sends this response. The interaction with the client is complete.

The STRUTS development methodology begins to take shape:

  • Defining views. We distinguish between views that are forms and other views.
    • Each form view generates a definition in the struts-config.xml file. The following information is defined there:
      • the name of the Bean class that will contain the form data, as well as an indication of whether the data should be validated or not. If validation is required and the data is found to be invalid, the view to be sent back to the client in this case must be specified.
      • The name of the Action class responsible for processing the form.
      • the names of all views that may be sent to the client once the request has been processed. The Action class will select one of them based on the result of the processing.
    • Each view corresponds to a JSP page. We will see that in views—particularly form views—we sometimes use a library of Struts-specific tags.
  • Writing the JavaBean classes corresponding to the form views
  • Writing the Action classes responsible for processing the forms
  • Writing any business logic or data access classes

1.4.2. STRUTS Development Tools

The Struts project is one of the projects of the Apache Software Foundation. Several of these projects are grouped under the name Jakarta and are available at the URL http://jakarta.apache.org:

Image

It is recommended that you read this page. Many of the projects are of interest to Java developers. If we follow the Struts link above, we arrive at the project’s home page:

Image

Here, too, it is recommended that you read the home page. To download the Struts Java libraries, follow the "Binaries" link above:

Image

For Windows users, use the 1.1.zip link; for Unix users, use the 1.1.tar.gz link (Nov 2003). Once the 1.1.zip file is unzipped, you will see the following directory structure:

Image

This directory structure contains the Java class libraries required for Struts development. These are stored in .jar or .war files, which are similar to .zip files. They can be opened using the same utilities. Most of the necessary libraries are located in the lib folder above:

Image

In addition to the .jar class libraries, there are .dtd (Document Type Definition) files that contain validation rules for XML files. An XML file can reference such a DTD file in its content. The program (called a parser) that analyzes the content of the XML file will use the validation rules found in the referenced DTD file to determine whether the XML file is syntactically correct. For example, the struts-config_1_1.dtd file defines the rules for constructing the struts-config.xml configuration file for Struts version 1.1.

Let’s now look at where to place the various elements of the Struts directory structure to deploy a Struts application on the Tomcat server.

1.5. Deploying a Struts Application

A Struts application is a web application like any other. It therefore follows the deployment rules of the container in which it runs. Here, an application—which we’ll call strutspersonne—will be run by a Tomcat server version 4.x. The deployment procedure for Tomcat version 5.x is included in the appendix. Here, we’ll follow the deployment rules for Tomcat 4.x:

  1. We define the strutspersonne context in Tomcat’s server.xml configuration file:
                <Context path="/strutspersonne" docBase="e:/data/serge/web/struts/personne" />

Once this is done, we restart Tomcat if necessary so that it takes the new context into account. We can verify the validity of the context by requesting the URL http://localhost:8080/strutspersonne:

Image

If we do not get an error page, the context is correct.

  1. We create the WEB-INF subfolder in the physical folder associated with the strutspersonne context.
  2. In the application’s WEB-INF folder, we define the application’s web.xml configuration file:

Image

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
    <servlet>
      <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
        <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
      <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

</web-app>
  • The application's controller (servlet) class is a predefined Struts class called ActionServlet. It is located in the struts.jar file. To ensure Tomcat can find this class, we will place struts.jar in the <tomcat>\common\lib folder, which is one of the folders Tomcat searches when looking for classes. In fact, we will place all the .jar files found in the <struts>\lib folder there, where <struts> is the root folder of the Struts directory tree.

Image

  • We will also place the struts-el.jar and jstl.jar files located in <struts>\contrib\struts-el\lib:

Image

  • Here, we have access to the web server. This is not always the case. If you deploy a web/Java application in a web container that you do not administer yourself, it is best for the application to include all the libraries it needs. These must then be placed in the WEB-INF/lib folder, which you must create.
  • We noted that the controller requires certain information, which it normally finds in a struts-config.xml file located in the same folder as web.xml. In fact, the name of this file is configurable. It is the config parameter, mentioned above, that sets this name.
  • The <servlet-mapping> tag indicates that the controller will be accessed via all URLs ending with the .do suffix. This mapping is required by Struts. These URLs will then be filtered by the controller, which will only accept the URLs declared in its struts-config.xml configuration file

For now, our web.xml file is sufficient.

  1. We will request the URL /main.do from the strutspersonne application. According to the previous web.xml file, this URL will therefore be passed to the org.apache.struts.action servlet. The ActionServlet class will be instantiated and its init method called. This method attempts to read the configuration file defined by the config parameter. This file must therefore exist. We create the following struts-config.xml file:
<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>
    <action-mappings>
      <action
          path="/main"
          parameter="/main.html"
          type="org.apache.struts.actions.ForwardAction"
      />
    </action-mappings>
</struts-config>

Note that the DTD file for struts-config.xml is not the same as that for web.xml, indicating that they do not have the same structure. For each URL that the controller must handle, we need to define an <action> tag. This tag is used to tell the controller what to do when it receives a request for that URL. Here, we specify the following elements:

  1. path="/main": defines the name of the URL configured by the <action> tag. The .do suffix is implicit.
  2. type="org.apache.struts.actions.ForwardAction": defines the name of the Action class that must handle the request. Here, we use a predefined Action class in Struts. It does nothing on its own and forwards the client’s request to the URL specified in the parameter attribute.
  3. parameter="/main.html": the name of the URL to which the request should be forwarded. Here, it is a static HTML file.

In summary, when the user requests the URL /main.do, they will be directed to the URL /main.html.

  1. The main.html file will be as follows:
<html>
    <head>
      <title>Struts application</title>
  </head>
  <body>
      strutspersonne application active ....
  </body>
</html>

This file is located in the strutspersonne/views application folder:

Image

It can be accessed directly via the URL http://localhost:8080/strutspersonne/main.html:

Image

Here, the application’s Struts controller did not intervene, since it only intervenes when a URL of the *.do type is requested. However, in this case, we requested the URL /vues/main.html.

  1. The struts-config.xml file created earlier must be placed in the same WEB-INF folder as the web.xml file:

Image

  1. We will now verify that the strutspersonne application controller is working properly by requesting the URL /main.do after restarting Tomcat if necessary.

Image

Here, the Struts controller intervened since we requested a URL of the *.do type. We successfully obtained the expected page (main.html). We now have the basic components for our application to function: the strutspersonne context, the web.xml and struts-config.xml configuration files, and the Struts libraries.

What would have happened if we had requested a URL like /toto.do? According to the strutspersonne application’s web.xml file, the Struts controller is called to handle it. It then checks its struts-config.html configuration file and finds no configuration for the URL /toto. What does it do then? Let’s try:

Image

We get an error page, which seems normal. We can now move on to writing an application.