Software By JeffMain Page | About | Help | FAQ | Special pages | Log in
The Free Encyclopedia
Printable version | Disclaimers

Struts Webserver Configuration

From Software By Jeff

Starting with Struts - Setting Up Struts - Struts Webserver Configuration - Our Struts Classes - Our Struts Web Pages - Struts Server Deployment - Making Struts Projects in IDEs


Not meant to be a comprehensive how-to for integrating Java or Struts into a web server, but instead a brief discussion of what the Java Servlet or Application server expects, this section will introduce a handful of configuration files necessary to get your web server to serve Struts.

Struts is entirely Java. The classes used by Struts and written by you need to be Java, well, initially. The server you use needs to serve Java. For ease, we'll assume you've got a Tomcat server set up. You may have this as part of a JBoss installation, or even as a back-end for an Apache web server installed. You might torture yourself and integrate this with Microsoft's IIS server, or you might disregard the suggestion and use something like Sun's application server or even a commercial server like IBM's WebSphere. Fundamentally, the configuration is the same to get our application served.

At the root of our application we need to have a directory structure in place. This is defined by the Servlet API, and is what you'll find wherever you get a WAR or have to do this for other people.

Table of contents

WEB-INF

The root of your application contains a directory named WEB-INF. OK, that's pretty much it. The WEB-INF directory contains the things your application needs, like library archive, resource, and configuration files. When your server is asked for a file, it starts looking up the directory tree until it finds a directory with the WEB-INF directory in it. It then uses the settings and objects within that directory to control the application. Curiously, this means you can have nested applications. This is frowned upon, so be careful to avoid this situation.

Other directories can be added to the WEB-INF directory as you find necessary. It might be useful, for example, to spread out various configuration files in a structure mimicking your application's directory structure. You may find it useful to store other data in the WEB-INF directory, but be sure to consider what belongs in the application directory structure instead. For example, images would be better stored in an images directory outside the WEB-INF directory than in it. Generally this is because you have to refer to the WEB-INF explicitly in your web pages and classes to access the items. As a good rule of thumb, if it isn't referenced in a configuration file, it belongs out of the WEB-INF directory.

For now we'll discuss the directories we expect to be in the WEB-INF directory of our application.

classes

The WEB-INF may contain a directory named classes, in which you'd store compiled, but not archived classes. Often, if this is the application you're developing, this is where your compiled code would go. Another use of this directory is to extract archives that won't play nice with the automatic archive loading features of our server. We discuss that below.

Initially we won't have any .class files in the classes directory. As we add action and bean classes, though, unless we archive them we'll put them in this directory. In our IDEs we will make sure this is the directory configured for our compiler target.

lib

The WEB-INF may contain a directory named lib, in which you store the Java Archive files that will be automatically added to your classpath. Note that typically only .jar files are automatically added; if you provide an archive with .zip as its extension, it will not be automatically added. These .zip files can be added in the command-line arguments to start the server, or in the server's configuration file. Generally, you should find it possible to rename .zip files to .jar files without incurring any ill effects; the Java archiver will use the correct method for extracting the information within the archive. If you can neither successfully add the .zip files to the server's start-up classpath or rename them to .jar files, you can either unzip and jar them yourself, or unzip them entirely in the WEB-INF's classes directory.

Since we're making a Struts application we know we'll have a lib directory. Simply put the struts.jar and the Apache commons*.jar files that come in the Struts archive downloaded from the Apache website in the lib directory. These are the foundations for Struts and are required to make it work.

web.xml

Fundamentally, the WEB-INF is required to have only one XML file within it to be considered an application; the web.xml. If there are no supporting files or classes, the lib and classes directories are unnecessary. It is possible to write an application entirely in JavaScript, for example, in which case you'd be able to pass even the the web.xml, but we anticipate a little more complex site if you're interested in using Struts.

The web.xml file contains information about the files and servlets in your application. For our Struts discussion, we'll pare down the file into the bare minimum to make Struts work for us. In the following example web.xml we describe only one servlet and related mapping, allowing us to get our server to serve pages using Struts.

<?xml version="1.0" encoding="UTF-8"?>
<!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 id="WebApp">
  <display-name>App Name</display-name>
  <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>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

What does this mean?

Let's start from the outside and work our way in, top to bottom. The heading of the XML simply describes the XML and document model we'll be following. The Document Type Descriptor (http://java.sun.com/dtd/web-app_2_3.dtd) defines what XML elements are expected and even required. The descriptor is downloadable at the URL in the header, and is subject to change with different versions of the web-app API. More documentation exists within the descriptor, so for a deep understanding of that, we defer to the document itself. The web.xml file must contain the DOCTYPE line with the description and URL, as above, in order to comply with the spec.

The web-app is the root of our XML. This needs to wrap the guts of our application's configuration. Within this wrapper come the other elements require for our operation.

servlet

Here we define the servlet that will be handling our Struts application.

The servlet-name provides a mechanism in which we can refer to this servlet in this configuration file and in URLs, if we were to so choose. It provides a quick translation layer from the nearly always longer class name and a simple-to-remember key name. Since we're defining the actions that we'll be writing, we choose the title of action.

The servlet-class defines the class that will be used when the servlet-name is encountered. We choose the Struts class org.apache.struts.action.ActionServlet, which is the "controller" of the MVC view that Struts enables. For us, that means that the ActionServlet classes will be the ones that fire and do the logic behind our scenes. This is simply telling the server that we're using Struts.

The servlet-class allows us to configure bits for the servlet to use using the init-param portion of the XML. This is entirely servlet dependent, and the XML won't care if the parameters are there, or if the ones that are there are useful to the servlet.

Since we're using Struts, we provide the Struts servlet a configuration file name through the config parameter name, or param-name. The parameter value, or param-value is the path and file name to the Struts configuration file. The path is relative to the location of the application, or the parent of this web.xml's WEB-INF directory, thus the example has WEB-INF. The path can be absolute, but you need to be sure the web server can read the path and file; it's a good practice to keep these configuration files in your WEB-INF directory.

A quick aside while we're discussing the configuration file.

The config outlines a module in Struts. Everything contained within the struts-config.xml file is configured as one module. The bean names, the validators, the actions, and all the rest that we haven't yet discussed. Generally everything defined in a directory structure will be matched with the corresponding module. If a directory is not found, its parent is searched for, until the default module is found and used at the root of the directory structure for the application; the one defined simply as config, like we have. Any subdirectory we add to our application will use this configuration, unless we define a different module.

To facilitate this, Struts allows you to add to the config parameter name in such a way as to define a module. To do this, simply provide another init-param to the same servlet block.

<init-param>
  <param-name>config/moduleName</param-name>
  <param-value>/WEB-INF/moduleName/struts-config.xml</param-value>
</init-param>

This means that anything under the moduleName subdirectory of our application will use this configuration, and not that of our default. Any subdirectories of the moduleName directory would use this same configuration, unless we again explicitly defined another module.

Note that we followed our earlier suggestion of mimicking a directory structure; the bits of JSP rekated to this module would be in a moduleName subdirectory of your application, so we reproduce this in the file name for the configuration. This is not required in the param-value; we could have easily said WEB-INF/moduleName-config.xml and kept the module's config file in the same directory as this web.xml and the other struts-config.xml. Note that it is a good practice to keep the Struts modules in a directory structure like your site would be.

Additionally, we're not required to have the "default" configuration, as we describe in our web.xml file. We could have only module definitions. This is dependent entirely on your site organization, but it is a good practice to have a default, even if you don't facilitate any Struts use in the root of your application.

Finally, in the servlet element we have a load-on-startup element with an order number. The elements will be gathered and started by the Servlet server first by the order number, then the order in the grouping; that is, if you care which Servlets are started first, take care with this parameter, otherwise the server will decide and start all of the zeroes before all of the ones before all of the twos... If the Servlet is not required to be started by the server at startup, put a negative number in the parameter and the servlet won't be started until it is first called upon. Since we're only hosting one Servlet here, the number is not important, but we want our Servlet instantiated to speed start-up.

What this does for us is instantiate our Servlet's class, and calls its init() method. Whatever that method does is what happens next. For us, the Struts ActionServlet will read the configuration files and be prepared to handle action requests.

servlet-mapping

While not funamentally required, we use the servlet-mappping to describe URL elements that will be forwarded to our servlet. This allows us to have URLs other than simply calling our servlet. Since we've defined *.do as our mapping, any URL that ends in .do (before any optional query string) will be handled by the named servlet, in our case the action servlet, which we defined above.

You can choose a different servlet-name than action if you named the servlet different in the servlet element. Choose your own name. Largely this will only be known by you as it will only be used in the web.xml file. For Struts, anyway, we won't be calling the servlet directly; we'll be defining URLs using the .do extension.

The extension name can also be changed, if you don't want .do to be used. Change it in the url-pattern parameter. Whatever the URL pattern matches will be disregarded and the rest will be passed to the Struts ActionServlet to find a corresponding action. That is, if you choose the pattern of /*.do and the request comes for /page.do the .do will be disregarded, and page will be used to find an action; similarly, if you named /do/* as the mapping, then /do/page would find the page action. This also means that with /*.do that path/page.do would be mapped to the path/page action. We'll discuss the action mapping in a bit.

Note also that Struts only supports one servlet-mapping per Servlet instance. As a tricky work-around, if you want more than one, you can define more than servlet and servlet-mapping "pair", even using the same configuration files or other resources. Note that these will be two instances of the Servlet running on the server, and that the in order for the instances to directly share information takes some advanced programming. This trick can be used to isolate multiple Struts "applications" on the same server. More acceptable, however, is to define multiple modules.

welcome-file-list

While not required for Struts to work, the welcome-file-list element adds a default home page to our application so that we don't have to hand out explicit pages in our URLs. This allows us to put a file, in this case default.jsp in a directory and have the URL end at the path containing that file; like http://server.name/path.

We can make this a Struts-aware page, allowing us to jump right into our Struts application, but that's a little more advanced than we want to discuss right now.

Simply provide a list of file names in welcome-file elements and they will be treated, in order, as the default pages. That is, if our directory contained both an index.jsp and a default.jsp and our list contained both as welcome files, the order entered in the list would be the order in which they'd be accepted. If no file is found from the list, then the server will respond as directed; either with an error or a list of files in the directory.

struts-config.xml

For our purposes we'll start with a very rudimentary struts-config.xml that describes the action, bean, and forward for one simple page. The goal is to lay out what needs to be done, and build from that to understand what can be done.

The rudimentary struts-config.xml looks like this.

<?xml version="1.0" encoding="UTF-8"?>
<!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>
  <!-- Data Sources -->
  <data-sources />

  <!-- Form Beans -->
  <form-beans />

  <!-- Global Exceptions -->
  <global-exceptions />

  <!-- Global Forwards -->
  <global-forwards />

  <!-- Action Mappings -->
  <action-mappings />

  <!-- Controller -->
  <controller />

  <!-- Message Resources -->
  <message-resources /> 

  <!-- Plug-ins -->
  <plug-in />
</struts-config>

What does this all mean?

The XML Document Type Descriptor is available from Apache (http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd), and it defines the bits we want or need to have. What we have provided is a selection of all of the available elements, although none have any details provided. This is a good place to start, as it gives the skeleton from which we can build. Quite technically, we don't need anything between the struts-config element tags.

For our purposes, we'll go with the following, and describe the details below.

<?xml version="1.0" encoding="UTF-8"?>
<!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>
  <!-- Form Beans -->
  <form-beans>
    <form-bean name="exampleForm" type="package.ExampleForm" />
  </form-beans>

  <!-- Action Mappings -->
  <action-mappings>
    <action path="/default" forward="default.jsp" />
    <action path="/example" type="package.ExampleAction" 
      name="exampleForm" scope="request">
	<forward name="success" path="/example.jsp" />
	<forward name="failure" path="/default.do" />
    </action>
  </action-mappings>
</struts-config>

Here we've trimmed out the un-used elements for brevity. It's a good practice to leave them in, even if nothing is defined, as it provides a reminder for what can be done.

form-beans

In the form-beans section we have defined a single form-bean. A form bean is a predefined JavaBean that extends the org.apache.struts.action.ActionForm class. The form beans are generally no-logic data place-holder classes, with private data members and public accessor methods (getters and setters), in normal bean fashion.

Our configuration defines one form-bean, the exampleForm. Of course, this name is completely up to the web developer. The name of the bean is used both in the struts-config.xml to help relate beans to actions, and also within JSP pages to use the data in the bean. The type of the bean is the fully-qualified package and class name of the Java object that will be used when this bean is called for.

action-mappings

The action-mappings element is the guts of the layer between the URL requested and the Struts Action that will do the requested work. Any number of action elements can be inside the action-mappings, each corresponding to a URL-to-class mapping.

action

The action element defines the individual action handlers. The example we have shows two action elements to give a simple example, and a more common, slightly more complex example.

The first example is for the /default action, as indicated by the path attribute. As we look at our WEB-INF/web.xml file we see that we're using /*.do as our servlet-mapping url-pattern. This action will be triggered when the URL /default.do is sent from the web server. Note that this does not mean that when the web server receives a /default.jsp URL that it will call this action. It means that when we get a /default action we'll also use the default.jsp. The name of the action must be unique within the module. Other modules can have actions with the same name. Of course, the action's name is up to the developer.

The forward attribute tells Struts what will process this request. In our example we're telling Struts to use the default.jsp page, which must exist in the root of this module. More correctly, for our value, the page must exist in the root of our module; the value is relative to the module's root, and since we put only default.jsp we're saying that JSP will be in the root. Since we provide no other information to the action, there are no other assumptions we can make when working on that JSP page; most specifically, we have not provided it with a bean to use. The forward does not need to be unique; many actions may use the same forward as their target.

The second example action is named /example, and like the /default example above, this will answer to /example.do URL requests. Unlike the previous example, this one uses a class to do the work, and then based on the results of the work, it can choose which forward to use.

The type attribute describes the fully-qualified package and class of the Struts Action that will peform the work for this request. This class must extend org.apache.struts.action.Action. By default, the Action class' doAction() method will be called. Later we'll discuss a way to use the parameter of the action to define different methods to call.

Our action defines a bean to be used as part of the Struts activity. The action name attribute must match one of the form-bean definitions above. This bean will then be passed to the doAction() method in the ActionForm parameter.

Our action restricts the scope of our bean to the request. This means that when the action is initiated, it has a new bean full of information from the JSP that is intiating our request. The alternative is to define the bean as session, which would mean that the same bean would be used throughout the user's visit to the site, even if they navigate away from actions that use the bean. By using request we can be certain that the information in the bean is from the JSP. We can populate additional information in the bean as we pass it to the JSP, which it can then use to prepare its presentation, but whatever we've put in the bean will be missing, unless the JSP puts it back...we'll try to make that more clear as we go through the Action in a minute.

forward

Our second example action also defines a couple of forward mappings. These mappings allow us to decide within our action what to do under certain cases.

The forward element has a name attribute that can be used inside our Action class to find the intended target for the action under this case. The name is chosen by the user, and has no special meaning within Struts. We've chosen success and failure as easy to understand concepts. The path attribute of the forward tells Struts which page will handle the results of our Action. In the case we choose to use the success mapping, we'll end up at the /example.jsp in the root of our module (again, as above the page is relative to the module root). If we choose the failure mapping we'll be sent to our /default.do at the root of our module, which will actually return through the previous action we mapped.

Digesting the struts-config.xml

In our simple example, we can infer that we may go from the default.jsp by way of an /example.do URL. Within the Action processing behind the /example action, we may find ourselves at either an example.jsp or back to the default.jsp, depending on the outcome of the ExampleAction.

Retrieved from "http://www.swbyjeff.com/index.php/Struts_Webserver_Configuration"

This page has been accessed 6560 times. This page was last modified 19:52, 13 Jan 2006.


Find
Browse
Main Page
Community portal
Current events
Recent changes
Random page
Help
Edit
Edit this page
Editing help
This page
Discuss this page
Post a comment
Printable version
Context
Page history
What links here
Related changes
My pages
Create an account or log in
Special pages
New pages
Image list
Statistics
Bug reports
More...