Recipe2.1.Using Plug-ins for Application Initialization


Recipe 2.1. Using Plug-ins for Application Initialization

Problem

You want to load initial data into the application context when your application starts up.

Solution

Create a class that implements the org.apache.struts.action.PlugIn interface and specify the plug-in element in the struts-config.xml. The following XML fragment shows a plug-in declaration and a nested set-property element for setting a custom property:

<plug-in className="com.oreilly.strutsckbk.CustomPlugin" >   <set-property property="customData"                    value="Hello from the plugin"/> </plug-in>

Discussion

Struts provides a PlugIn interface you can use to create custom services that are initialized on application startup. The Java source for the PlugIn interface is shown in Example 2-1. (For clarity, the JavaDoc documentation has been removed from this listing.)

Example 2-1. The Struts PlugIn interface
package org.apache.struts.action; import javax.servlet.ServletException; import org.apache.struts.config.ModuleConfig; public interface PlugIn {     public void destroy( );     public void init(ActionServlet servlet, ModuleConfig config)         throws ServletException; }

To implement a plug-in, you only need to implement this interface and declare the plug-in implementation in the struts-config.xml file. The two methods that must be implemented, init() and destroy( ), are called during the lifecycle of the plug-in. Struts calls the init( ) method after it instantiates the plug-in on startup of the ActionServlet. Struts calls the destroy() method when the ActionServlet is destroyed, usually on shutdown of the application server. At first, this plug-in feature may seem simplistic and limited. However, by utilizing another feature of Struts, the set-property element, you can pass ad hoc information to the plug-in. This capability enhances the flexibility of these classes.

The set-property element is supported by most all of the elements that define Struts entities such as form-bean, action-mapping, action, and plug-in. The set-property element takes two attributes: name and value. Struts calls the setter method for the property identified by the value of the name attribute, setting the property to the String value of the value attribute.


All set-property elements for a given plug-in will be processed prior to calling the plug-in's init( ) method. This allows the plug-in to use the value of the properties in the init( ) method.

If you are using multiple set-property elements for a plug-in, Struts can't guarantee the order in which they will be called. Each setter method should be independent of any other methods.


Struts passes references to the ActionServlet and the plug-in's ModuleConfig as arguments to the init( ) method. The ActionServlet allows access to the ServletContext for storing application-scoped objects. The ActionServlet gives you access to more advanced container-managed J2EE components, such as data sources and message queues. The ModuleConfig gives you access to the Struts configuration of the module in which the plug-in is defined.

Every Struts application has at least one module: the default module. If you are unfamiliar with modules, you can read more about them in Recipe 2.5.


To make this more concrete, consider a simple, yet relevant example. You want to define a plug-in that lets you to determine when your application was started, and how long it has been up and running. You can use the class shown in Example 2-2 to track and report on your application's uptime.

Example 2-2. Application uptime tracker object
package com.oreilly.strutsckbk; import java.util.Date; public class TimeTracker {   private long startUpTimeMillis;   private Date startedOn;   public TimeTracker( ) {      startUpTimeMillis = System.currentTimeMillis( );      startedOn = new Date( );    }   public long getUptime( ) {     return System.currentTimeMillis( ) - startUpTimeMillis;   }   public Date getStartedOn( ) {     return startedOn;   } }

Create an implementation of the PlugIn interface, like the one shown in Example 2-3, that instantiates the TimeTracker. The plug-in stores the TimeTracker instance in the ServletContext using the value of a plug-in property. You can use this value to retrieve the TimeTracker instance from the servlet context. Though this value could have been hard-coded, using a property provides greater flexibility.

Example 2-3. Time tracker plugin
package com.oreilly.strutsckbk; import javax.servlet.ServletException; import org.apache.struts.action.ActionServlet; import org.apache.struts.action.PlugIn; import org.apache.struts.config.ModuleConfig; public class TimeTrackerPlugin implements PlugIn {     private String contextKey;        public void setContextKey(String key) {        this.contextKey = key;    }        public void init(ActionServlet servlet, ModuleConfig conf)          throws ServletException {       servlet.getServletContext( ).setAttribute(contextKey, new TimeTracker( ));    }    public void destroy( ) {     } }

Now that you have the Java classes created for the plug-in, you can integrate them into your Struts application by adding the plug-in element to the struts-config.xml file:

<plug-in className="com.oreilly.strutsckbk.TimeTrackerPlugin">     <set-property property="contextKey" value="timeTracker"/> </plug-in>

The plug-in stores the time tracker object in the servlet context. You can access the TimeTracker to display information about your application's uptime as in the following JSP snippet:

<h4>Continuously running since      <bean:write name="timeTracker"              property="startedOn"                format="MM/dd/yyyy HH:mm"/> for     <bean:write name="timeTracker"              property="uptime"/> milliseconds! </h4>

You can use a servlet to load initial data like a Struts plug-in. A servlet with the load-on-startup initialization parameter set to a low number, such as 1, will be loaded on application startup. The container will call the servlet's init( ) method after instantiating the servlet. But the Struts plug-in approach has several advantages. First, most Struts applications don't require changes to the web.xml file once it's initially setup. Having to declare additional servlets in web.xml means an extra file to be maintained. Second, the PlugIn interface provides access to Struts-specific information if needed. Finally, since the lifecycle of the plug-in follows the lifecycle of the ActionServlet, you are guaranteed that the data will be available when needed by your Struts application.

See Also

Recipe 2.8 shows another usage of the set-property element. The Struts documentation on plug-ins can be found at http://jakarta.apache.org/struts/userGuide/building_controller.html#plugin_classes.

You can use a Servlet context listener to load initial data.



    Jakarta Struts Cookbook
    Jakarta Struts Cookbook
    ISBN: 059600771X
    EAN: 2147483647
    Year: 2005
    Pages: 200

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net