ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Learning Jakarta Struts, Part 3
Pages: 1, 2, 3

Having another abstract method here is useful so you can do things such as logging, as shown below:



{
ActionForward forward = null;
// Simple log to the servlet log for informational purposes

getServlet().log("AbstStrutsActionBase.perform() [Action Class: "+this.getClass().getName()+" ]");
getServlet().log("AbstStrutsActionBase.perform() [Form Class : "+(form == null ? "null" : form.getClass().getName())+" ]");
}

Each Action class would extend the AbstStrutsActionBase and implement their own perform method specific to the tasks of that action. If we look at the LoginAction, we can see how this is applied.

package com.oreilly.actions;
import java.io.IOException;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import com.oreilly.forms.LoginForm;

/*

LoginAction demonstrates how an Action class is called within the Struts framework. For the purposes of this sample, we simply demonstrate how the perform is called, a sample action, and a return.

*/

public class LoginAction extends AbstStrutsActionBase 
{

This is a blackbox method used to authenticate a user. There would typically be a bean (or EJB) here that actually does the work. A lookup would be done (as shown in the base class) and create an interface to authenticate the user against some backend database.

  • Param String of username.
  • Param String of password.
  • Return boolean where true equals authenticated, false equals not authenticated.
public boolean authenticate(String username, String password)
{

Here, do the appropriate lookup and calls. That code is not provided as part of this sample. Instead, it is just to demonstrate the interaction of the action class with business logic tier.

return(true);
}

Override base class with specific perform implementation for this class.

  • Param mapping: The ActionMapping used to select this instance.
  • Param actionForm: The optional AbstActionFormBase bean for this request (if any).
  • Param request: The HTTP request we are processing.
  • Param response: The HTTP response we are creating.
  • Exception IOException: if an input/output error occurs.
  • Exception ServletException: if a servlet exception occurs.

public ActionForward perform(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{

// Assume that the login fails, so that the login page is redisplayed
// if the user isn't authenticated

boolean validLogin=false;
ActionForward actionForward = mapping.findForward(LOGIN);

// Create the container for any errors that occur

ActionErrors errors = new ActionErrors();

// Extract attributes and parameters we will need from the incoming
// form.

LoginForm loginForm = (LoginForm) form;
String userName = null;
String password = null;
if (loginForm != null){
userName = loginForm.getUserName();
password = loginForm.getPassword();
validLogin = authenticate(userName, password);
}

if (validLogin){

// Forward control to the specified 'success' URI specified in the structs-config.xml

actionForward = mapping.findForward(SUCCESS);

// Save something into the session for later use.

request.getSession(true).setAttribute("USERNAME", userName);
} else {
errors.add("login", new ActionError("error.login.authenticate"));
}

// If any messages is required, save the specified error messages keys

// into the HTTP request for use by the <struts:errors> tag.

if (!errors.empty()) {
saveErrors(request, errors);
}

// Forward control to the appropriate URI as determined by the action.

return (actionForward);
}

}

Remember, the LoginAction is defined as the instance of the login action in the struts-config.xml file. When the class is instantiated, the Struts framework calls the perform method. The method signature

Related Reading

Java Servlet Programming, 2nd EditionJava Servlet Programming, 2nd Edition
By Jason Hunter with William Crawford
Table of Contents
Index
Sample Chapter
Full Description

public ActionForward perform(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException

includes: mapping, a mechanism to locate the available action mappings, the form that is providing data for this action, and the standard HttpServletRequest and HttpServletResponse.

With this information, an Action can gather any information it needs to perform its task. In our sample, the necessary information is pulled from the form, mainly the username and password. This is needed in order to authenticate the user. The authenticate method call is the sole point of the business logic for this application. Within the authenticate method would typically be the lookup of an EJB, or a database access. You can see now why I included a simple lookup method in the AbstStrutsActionBase class -- this lookup could be used by all Action classes if this were an EJB-based system.

Based on the return value, the action will take the appropriate steps. If the user was authenticated, then we are good to go, so we save some info in the request for use later, and return a success forward. This forward is used by the ActionMapping in the struts-config.xml file to determine where to go next. If we look back at the ActionMapping for login, success will bring us to Welcome.jsp. On failure, an error is set, and the appropriate error page will be displayed.

Develop the application business logic

In a real application, this is where you would incorporate your business logic. In our sample, that would include writing the EJB that is called in the authenticate method of the LoginAction. As you can see, it's possible to get things up and running by "blackboxing" the true application logic. I actually recommend getting your application framework up and running first, and then going back and doing the development for the logic tier. It's just one less thing to debug if you know that your framework is set up correctly. We are going to skip over the business logic because it's beyond the scope of this article, but I'm sure you get the picture.

Create JSPs to match the workflows using the ActionMappings

Here is where all of the pieces should start to fall into place. Using the struts-config.xml file, you want to make sure that there is a JSP for one defined in the ActionMappings. In our case, these are Login.jsp, Welcome.jsp, and Errorpage.jsp. It's important to note that even though I've had the forward map to a JSP, it is perfectly logical and necessary in a real application to map to other actions. Our simple Login.jsp looks like:

<%@ page language="java" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-form.tld" prefix="form" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

<html>
<head>
<title><bean:message key="login.title"/></title>
</head>
<body>
<html:errors/>
<h3>Enter your username and password to login:</h3>
<html:form action="login.action" focus="userName" >
<html:text property="userName" size="30" maxlength="30"/>
<html:password property="password" size="16" maxlength="16" redisplay="false"/>
<html:submit property="submit" value="Submit"/>
<html:reset/>
</html:form>
</body>
</html>

Struts provides a comprehensive tag library (based on the JSP custom tag libraries). These tag libraries make it easy to construct the user interface. The advantage of using these tag libraries is that they provide some additional functionality. For example, the following snippet may be found in an JSP form:

<input type="text" name="userName" value="">

Using Struts custom tag libraries, the above would become:

<html:text property ="userName">

An example of a Struts tag library is defined by the statement

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>.

While I'm not going to go into details on all of the available tags in the various Struts taglibs, I've used a few in this sample. If you are going to be building complicated JSPs, I suggest that you familiarize yourself with what's available. They can prove very helpful and save a lot of time. You can find more details in the Struts Developers Guides.

Pages: 1, 2, 3

Next Pagearrow