My app is deployed on
Tomcat 5.5. This is my first
struts app.
In an Action class I�m setting an ArrayList into the session object like this:
arrayList = db.getStateList();
request.getSession(false).setAttribute("stateList", arrayList);
//print session id for later comparison
System.out.println("session = " + request.getSession(false).getId());
Then I forward to a .jsp like this:
return (mapping.findForward("success"));
If I run this app from the same machine that�s running Tomcat, everything is fine. If I run it from another machine on my LAN, when I get to the .jsp, I have a different session id and (of course) all my session attributes are gone.
javax.servlet.http.HttpSession sess = session;
System.out.println("session = " + sess.getId());
THINGS I THINK I�VE RULED OUT:
I invoking this app w/ a URL like
http://win2003_server:8080/MyApp/ (not an IP addr) � I read posts where folks were using an IP addr and it was getting translated to a machine name based on an entry in a hosts file and Tomcat thought it was a different host and created a new session.
I�m using a <html:form> tag � I read posts where people were using a regular old <form> tag in a struts app an having problems.
I can�t imagine it would be a session timeout problem because my Action forwards straight to the .JSP. My whole
test takes about 30 seconds.
I believe I�ve enabled cookies properly. In my browser (IE) menu under Tools-Internet Options->Privacy->Advanced I checked �Override automatic cookie handling�, clicked �Accept First-party cookies�, �Accept third-party cookies�, and checked �Always allow session cookies�.
Like I said, this is my first struts app and my first time administering Tomcat, so don�t hesitate to point out things that may seem obvious.
Thanks.
Steve
For what it�s worth, here�s my entire Action class:
package com.lyonsvalley.custcompass;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.Action;
import com.lyonsvalley.custcompass.LoginActionForm;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Iterator;
import java.util.Date;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.File;
import java.util.Properties;
import java.net.URL;
import com.reportmill.base.*;
public class LoginAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
/**@todo Need some kind of global error logging to table or file, and/or
* need to find out where servlet.log goes.
*/
LoginActionForm loginActionForm = (LoginActionForm) form;
// mapping.findForward("rptTrial");
// getServletContext().getRequestDispatcher("/CustCompass/RptTrial").forward(req, res);
/* Load application.properties */
String dbURL;
String displaySql = "false";
try {
Properties appProps = new Properties();
//This will look for properties file in the same path where this .class file is located
// InputStream in = this.getClass().getResourceAsStream("/ApplicationResources.properties");
//This will look for properties file in the root context for the web app (C:\SK_Files\jbproject\CustCompass\CustCompass\ on dev machine)
//Hopefully this will allow us to keep it outside of the .war file so we can change it without recompiling or redeploying the app
InputStream in = request.getSession().getServletContext().getResourceAsStream("/CustCompass.properties");
appProps.load(in);
// appProps.list(System.out);
dbURL = appProps.getProperty("dburl");
displaySql = appProps.getProperty("displaysql");
in.close();
} catch (FileNotFoundException e) {
request.setAttribute("errorMessage", "Can't find CustCompass.properies file in LoginAction: " + e.getMessage());
return (mapping.findForward("error"));
} catch (IOException e) {
request.setAttribute("errorMessage", "IOException reading CustCompass.properies file in LoginAction: " + e.getMessage());
return (mapping.findForward("error"));
}
// dbURL = "jdbc
dbc
RIVER={Microsoft Access Driver (*.mdb)};DBQ=C:\\SK_Files\\jbproject\\CustCompass\\custCompass.mdb";
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con = DriverManager.getConnection(dbURL, "Admin", "");
// DAOAccess db = new DAOAccess(con);
DAOAncestor db = new DAOAccess(con);
if(displaySql.equalsIgnoreCase("true") || displaySql.equalsIgnoreCase("yes")){
db.setDisplaySQL(true);
} else {
db.setDisplaySQL(false);
}
request.getSession().setAttribute("db", db);
String user = loginActionForm.getUserName();
String pw = loginActionForm.getPassword();
Staff staff = db.authenticateStaff(user, pw);
request.getSession().setAttribute("operatorStaff", staff);
db.setOperatorStaff(staff); //This will be useful if we need to default fields to the curr operator (i.e. notes)
if (staff != null) {
String currDate = db.getServerDateTime();
staff.setLastLoginDt(currDate);
db.updateStaff(staff);
// if (loginActionForm.getUserName().equalsIgnoreCase("aaa") && loginActionForm.getPassword().equalsIgnoreCase("bbb")) {
} else {
request.setAttribute("errorMessage", "Invalid username/password in LoginAction.");
return (mapping.findForward("error"));
}
ArrayList materials = db.getGenericTableList("material_vt");
request.getSession().setAttribute("materialList", materials);
//Moved retrieval or these lists from custSearchAction because
//user could login, drill into note on Inbox, and then start
//working on cust sheet
ArrayList arrayList = db.getOrgList();
request.getSession().setAttribute("orgList", arrayList);
arrayList = db.getProductList();
request.getSession().setAttribute("productList", arrayList);
arrayList = db.getGenericTableList("industry_vt");
request.getSession().setAttribute("industryList", arrayList);
arrayList = db.getGenericTableList("customer_status_vt");
request.getSession().setAttribute("custStatusList", arrayList);
arrayList = db.getGenericTableList("customer_type_vt");
request.getSession().setAttribute("custTypeList", arrayList);
arrayList = db.getGenericTableList("customer_source_vt");
request.getSession().setAttribute("custSourceList", arrayList);
arrayList = db.getGenericTableList("phone_type_vt");
request.getSession().setAttribute("phoneTypeList", arrayList);
arrayList = db.getGenericTableList("street_suffix_vt");
request.getSession().setAttribute("streetSuffixList", arrayList);
arrayList = db.getGenericTableList("country_vt");
request.getSession().setAttribute("countryList", arrayList);
arrayList = db.getStateList();
// request.getSession().setAttribute("stateList", arrayList);
request.getSession(false).setAttribute("stateList", arrayList);
// Get all session-scoped attributes
javax.servlet.http.HttpSession sess = request.getSession(false);
String allSessAtts = "Session Attributes: \r\n";
if (sess != null) {
java.util.Enumeration attEnum = sess.getAttributeNames();
for (; attEnum.hasMoreElements(); ) {
String name = (String)attEnum.nextElement();
Object value = sess.getAttribute(name);
allSessAtts += name + ": " + value + " \r\n";
}
}
System.out.println("session = " + request.getSession(false).getId());
System.out.println("In LoginAction");
System.out.println(allSessAtts);
arrayList = db.getGenericTableList("address_type_vt");
request.getSession().setAttribute("addrTypeList", arrayList);
arrayList = db.getGenericTableList("email_type_vt");
request.getSession().setAttribute("emailTypeList", arrayList);
arrayList = db.getGenericTableList("payment_method_vt");
request.getSession().setAttribute("creditCardTypeList", arrayList);
//Prune query CSV output files
String maxFileAge = db.getParmValue("max_age_of_temp_files_in_days");
String tempFileDest = db.getParmValue("temp_file_destination");
int maxFileAgeDays = Integer.parseInt(maxFileAge);
if (maxFileAgeDays >= 0) {
pruneTempFiles(tempFileDest, maxFileAgeDays);
}
} catch (ClassNotFoundException e) {
request.setAttribute("errorMessage", "ClassNotFoundException error has occured in LoginAction: " + e.getMessage());
return (mapping.findForward("error"));
} catch (SQLException e) {
request.setAttribute("errorMessage", "SQLException error has occured in LoginAction: " + e.getMessage());
return (mapping.findForward("error"));
} catch (FileNotFoundException e) {
request.setAttribute("errorMessage", "FileNotFoundException error has occured in LoginAction: " + e.getMessage());
return (mapping.findForward("error"));
}
return (mapping.findForward("success"));
}
private void pruneTempFiles(String startingDirString, int daysOld) throws java.io.FileNotFoundException {
long pruneThreshold = new Date().getTime() - (daysOld * 24 * 60 * 60 * 1000);
File startingDir = new File(startingDirString);
validateDirectory(startingDir);
File[] filesAndDirs = startingDir.listFiles(new FileListFilter("compass_", "csv"));
List filesDirs = Arrays.asList(filesAndDirs);
Iterator filesIter = filesDirs.iterator();
File file = null;
System.out.println("Prune Threshold: " + new Date(pruneThreshold));
while ( filesIter.hasNext() ) {
file = (File) filesIter.next();
if (file.isFile() && file.lastModified() < pruneThreshold) {
//delete file
System.out.println("Deleting File: " + file.getName() + " Last Modified: " + new Date(file.lastModified()));
file.delete();
}
}
}
/**
* Directory is valid if it exists, does not represent a file, and can be read.
*/
private void validateDirectory (File aDirectory) throws FileNotFoundException {
if (aDirectory == null) {
throw new IllegalArgumentException("Directory should not be null.");
}
if (!aDirectory.exists()) {
throw new FileNotFoundException("Directory does not exist: " + aDirectory);
}
if (!aDirectory.isDirectory()) {
throw new IllegalArgumentException("Is not a directory: " + aDirectory);
}
if (!aDirectory.canRead()) {
throw new IllegalArgumentException("Directory cannot be read: " + aDirectory);
}
}
}
---------------------------------------------------------------------------------------
Here�s my entire .jsp:
---------------------------------------------------------------------------------------
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/struts-nested.tld" prefix="nested" %>
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<%
String searchSource = request.getParameter("searchSource");
System.out.println("searchSource = " + searchSource);
// Get all session-scoped attributes
// javax.servlet.http.HttpSession sess = request.getSession(false);
javax.servlet.http.HttpSession sess = session;
System.out.println("session = " + sess.getId());
String allSessAtts = "Session Attributes: \r\n";
if (sess != null) {
java.util.Enumeration attEnum = sess.getAttributeNames();
for (; attEnum.hasMoreElements(); ) {
String name = (String)attEnum.nextElement();
Object value = sess.getAttribute(name);
allSessAtts += name + ": " + value + " \r\n";
}
}
System.out.println("In custSearch-body.jsp");
System.out.println(allSessAtts);
%>
<script type="text/javascript">
/* The SMK_KeyPress function (SMK = Select Match Keystrokes) provides keystroke matching
for SELECT controls. The SELECT element declaration should direct the onkeypress event
to this function, and declare two expandos: smk_keystrokes and smk_lastpresstime.
*/
function SMK_KeyPress() {
var sndr = window.event.srcElement;
var key = window.event.keyCode;
var char = String.fromCharCode(key);
var sysdate = new Date();
// if the last key press was more than 2 seconds ago, reset the keystrokes
if(sndr.smk_lastpresstime=="" || sysdate.getTime()-sndr.smk_lastpresstime>2000 || key==8) {
sndr.smk_keystrokes = "";
}
sndr.smk_lastpresstime = sysdate.getTime();
// set up a regular expression for comparing with list box entries
var re = new RegExp("^" + sndr.smk_keystrokes + char, "i"); // "i" -> ignoreCase
// check each list box item for a match
for(var i=0; i<sndr.options.length; i++) {
if(re.test(sndr.options[i].text)) {
sndr.options[i].selected=true;
sndr.smk_keystrokes += char;
break;
}
}
// sink the keypress, ie don't pass it on to Windows or anything else
window.event.returnValue = false;
}
//-------
//
Java Script to Handle AutoSearch
function selectKeyDown() {
// alert("in selectKeyDown");
// Delete Key resets previous search keys
if(window.event.keyCode == 46)
clr();
}
function selectKeyPress() {
// alert("in selectKeyPress");
// Notes:
// 1) previous keys are cleared onBlur/onFocus and with Delete key
// 2) if the search doesn't find a match, this returns to normal 1 key
// search setting returnValue = false below for ALL cases will
// prevent default behavior
//TODO:
// 1) add Netscape handling
var sndr = window.event.srcElement;
var pre = this.document.all["keys"].value;
var key = window.event.keyCode;
var char = String.fromCharCode(key);
// "i" -> ignoreCase
var re = new RegExp("^" + pre + char, "i");
for(var i=0; i<sndr.options.length; i++) {
if(re.test(sndr.options[i].text)) {
sndr.options[i].selected=true;
document.all["keys"].value += char;
window.event.returnValue = false;
break;
}
}
}
function clr() {
document.all["keys"].value = "";
}
</script>
</head>
<body bgcolor="#ffffff">
<h3>
Enter customer search criteria:
</h3>
<!-- Experimenting w/ having target="_new" so that chooseCust and custInfo open in a new browser window -->
<!-- html:form action="/custSearchAction.do" method="post" target="_new" -->
<html:form action="/custSearchAction.do" method="post">
<table cellpadding="3">
<tr><td>Cust ID: </td><td><html:text property="custID" size="8"/></td></tr>
<tr><td>Last Name: </td><td><html:text property="lastName"/> First Name: <html:text property="firstName"/></td></tr>
<tr><td>Phone: </td><td><html:text onkkeyup="return autoTab(this, 3, event);" property="areaCd" size="3" maxlength="3"/><html:text onkkeyup="return autoTab(this, 3, event);" property="phonePrefix" size="3" maxlength="3"></html:text><html:text onkkeyup="return autoTab(this, 4, event);" property="phoneSuffix" size="4" maxlength="4"></html:text></td></tr>
<tr><td>City: </td><td><html:text property="city" size="8"></html:text> State:
<html:select property="state"><html
ption value=" "></html
ption><html
ptions collection="stateList" property="stateCd" labelProperty="description"/></html:select>
Zip: <html:text property="zip" maxlength="5" size="4"></html:text> <html:text property="zipPlus4" maxlength="4" size="4"></html:text></td></tr>
</table>
<br>
<html:hidden property="searchSource" value="<%=searchSource %>"/>
<html:submit value="Search" property="button"/>
<html:submit value="New" property="button"/>
<html:reset value="Reset" property="button"/>
</html:form>
---------------------------------------------------------------------------------------
Here�s my entire struts-config.xml file:
---------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
<form-beans>
<form-bean name="loginActionForm" type="com.lyonsvalley.custcompass.LoginActionForm" />
<form-bean name="custSearchActionForm" type="com.lyonsvalley.custcompass.CustSearchActionForm" />
<form-bean name="custSaveActionForm" type="com.lyonsvalley.custcompass.CustSaveActionForm" />
<form-bean name="getContactsForCustActionForm" type="com.lyonsvalley.custcompass.GetContactsForCustActionForm" />
<form-bean name="genericTableMaintSaveDynaActionForm" type="com.lyonsvalley.custcompass.GenericTableMaintSaveDynaActionForm">
<form-property name="effDt" type="java.lang.String" />
<form-property name="expDt" type="java.lang.String" />
<form-property name="Id" type="java.lang.String" />
<form-property name="desc" type="java.lang.String" />
<form-property name="parentKey" type="java.lang.String" />
<form-property name="tier1_min_sale_price" type="java.lang.String" />
<form-property name="addr1" type="java.lang.String" />
<form-property name="addr2" type="java.lang.String" />
<form-property name="city" type="java.lang.String" />
<form-property name="state" type="java.lang.String" />
<form-property name="zip" type="java.lang.String" />
<form-property name="zip4" type="java.lang.String" />
<form-property name="country" type="java.lang.String" />
<form-property name="webSite" type="java.lang.String" />
<form-property name="tier2_min_sale_price" type="java.lang.String" />
<form-property name="par_sale_price" type="java.lang.String" />
<form-property name="company_cost" type="java.lang.String" />
<form-property name="tier1_commission" type="java.lang.String" />
<form-property name="tier2_commission" type="java.lang.String" />
<form-property name="par_commission" type="java.lang.String" />
</form-bean>
<form-bean name="savePhoneActionForm" type="com.lyonsvalley.custcompass.SavePhoneActionForm" />
<form-bean name="saveAddressActionForm" type="com.lyonsvalley.custcompass.SaveAddressActionForm" />
<form-bean name="saveEmailActionForm" type="com.lyonsvalley.custcompass.SaveEmailActionForm" />
<form-bean name="staffSearchActionForm" type="com.lyonsvalley.custcompass.StaffSearchActionForm" />
<form-bean name="getOrdersForCustActionForm" type="com.lyonsvalley.custcompass.GetSalesForCustActionForm" />
<form-bean name="saveOrderActionForm" type="com.lyonsvalley.custcompass.SaveOrderActionForm" />
<form-bean name="getNotesForCustActionForm" type="com.lyonsvalley.custcompass.GetNotesForCustActionForm" />
<form-bean name="saveOrderProductActionForm" type="com.lyonsvalley.custcompass.SaveOrderProductActionForm" />
<form-bean name="saveNoteActionForm" type="com.lyonsvalley.custcompass.SaveNoteActionForm" />
<form-bean name="saveNoteTextActionForm" type="com.lyonsvalley.custcompass.SaveNoteTextActionForm" />
<form-bean name="getCustsForHouseholdActionForm" type="com.lyonsvalley.custcompass.GetCustsForHouseholdActionForm" />
<form-bean name="getMailingsForCustActionForm" type="com.lyonsvalley.custcompass.GetMailingsForCustActionForm" />
<form-bean name="querySearchActionForm" type="com.lyonsvalley.custcompass.QuerySearchActionForm" />
<form-bean name="querySaveActionForm" type="com.lyonsvalley.custcompass.QuerySaveActionForm" />
<form-bean name="querySpecPromptActionForm" type="com.lyonsvalley.custcompass.QuerySpecPromptActionForm" />
<form-bean name="saveQueryMaterialActionForm" type="com.lyonsvalley.custcompass.SaveQueryMaterialActionForm" />
<form-bean name="fileImportActionForm" type="com.lyonsvalley.custcompass.FileImportActionForm" />
<form-bean name="staffSaveActionForm" type="com.lyonsvalley.custcompass.StaffSaveActionForm" />
<form-bean name="staffRoleSaveActionForm" type="com.lyonsvalley.custcompass.StaffRoleSaveActionForm" />
</form-beans>
<global-forwards>
<forward name="error" path="/error.jsp" />
</global-forwards>
<action-mappings>
<action input="/index.jsp" name="loginActionForm" path="/loginAction" scope="request" type="com.lyonsvalley.custcompass.LoginAction">
<forward name="error" path="/error.jsp" />
<forward name="success" path="/inbox.jsp" />
</action>
<action input="/custSearch.jsp" name="custSearchActionForm" path="/custSearchAction" scope="request" type="com.lyonsvalley.custcompass.custSearchAction">
<forward name="multFound" path="/chooseCust.jsp" />
<forward name="oneFound" path="/custInfo.jsp" />
<forward name="error" path="/error.jsp" />
<forward name="changeCustHousehold" path="/changeCustHouseholdAction.do" />
</action>
<action path="/inboxAction" type="com.lyonsvalley.custcompass.InboxAction" />
<action input="/custInfo.jsp" name="custSaveActionForm" path="/saveCustAction" scope="request" type="com.lyonsvalley.custcompass.SaveCustAction" validate="true">
<forward name="error" path="/error.jsp" />
<forward name="success" path="/inbox.jsp" />
</action>
<action input="/common/custSheetMenuBar.jsp" name="getContactsForCustActionForm" path="/getContactsForCustAction" scope="request" type="com.lyonsvalley.custcompass.GetContactsForCustAction">
<forward name="error" path="/error.jsp" />
<forward name="success" path="/custContacts.jsp" />
</action>
<action name="genericTableMaintSaveDynaActionForm" path="/genericTableMaintSaveAction" scope="request" type="com.lyonsvalley.custcompass.GenericTableMaintSaveAction" />
<action name="savePhoneActionForm" path="/savePhoneAction" scope="request" type="com.lyonsvalley.custcompass.SavePhoneAction">
<forward name="success" path="/custContacts.jsp" />
</action>
<action name="saveAddressActionForm" path="/saveAddressAction" scope="request" type="com.lyonsvalley.custcompass.SaveAddressAction">
<forward name="success" path="/custContacts.jsp" />
</action>
<action name="saveEmailActionForm" path="/saveEmailAction" scope="request" type="com.lyonsvalley.custcompass.SaveEmailAction">
<forward name="success" path="/custContacts.jsp" />
</action>
<action name="staffSearchActionForm" path="/staffSearchAction" scope="request" type="com.lyonsvalley.custcompass.StaffSearchAction">
<forward name="multFound" path="/chooseStaff.jsp" />
<forward name="oneFound" path="/staffInfo.jsp" />
</action>
<action name="getOrdersForCustActionForm" path="/getOrdersForCustAction" scope="request" type="com.lyonsvalley.custcompass.GetOrdersForCustAction">
<forward name="success" path="/custOrders.jsp" />
</action>
<action name="saveOrderActionForm" path="/saveOrderAction" scope="request" type="com.lyonsvalley.custcompass.SaveOrderAction">
<forward name="success" path="/getOrdersForCustAction.do" />
</action>
<action name="getNotesForCustActionForm" path="/getNotesForCustAction" scope="request" type="com.lyonsvalley.custcompass.GetNotesForCustAction">
<forward name="success" path="/custNotes.jsp" />
</action>
<action input="/editOrderProduct.jsp" name="saveOrderProductActionForm" path="/saveOrderProductAction" type="com.lyonsvalley.custcompass.SaveOrderProductAction">
<forward name="success" path="/editOrder.jsp" />
</action>
<action input="/editNote.jsp" name="saveNoteActionForm" path="/saveNoteAction" type="com.lyonsvalley.custcompass.SaveNoteAction">
<forward name="success" path="/getNotesForCustAction.do" />
<forward name="inbox" path="/inbox.jsp" />
</action>
<action input="/editNoteText.jsp" name="saveNoteTextActionForm" path="/saveNoteTextAction" type="com.lyonsvalley.custcompass.SaveNoteTextAction">
<forward name="success" path="/editNote.jsp" />
<forward name="successNoCust" path="/editNoteNoCust.jsp" />
</action>
<action input="/common/custSheetMenuBar.jsp" name="getCustsForHouseholdActionForm" path="/getCustsForHouseholdAction" type="com.lyonsvalley.custcompass.GetCustsForHouseholdAction">
<forward name="success" path="/custHousehold.jsp" />
</action>
<action path="/changeCurrCustAction" type="com.lyonsvalley.custcompass.ChangeCurrCustAction">
<forward name="success" path="/custInfo.jsp" />
<forward name="addCustToHousehold" path="/custSearch.jsp?searchSource=household" />
</action>
<action path="/changeCustHouseholdAction" type="com.lyonsvalley.custcompass.ChangeCustHouseholdAction">
<forward name="success" path="/getCustsForHouseholdAction.do" />
</action>
<action path="/removeCustHouseholdAction" type="com.lyonsvalley.custcompass.RemoveCustHouseholdAction">
<forward name="success" path="/getCustsForHouseholdAction.do" />
</action>
<action input="/common/custSheetMenuBar.jsp" name="getMailingsForCustActionForm" path="/getMailingsForCustAction" type="com.lyonsvalley.custcompass.GetMailingsForCustAction">
<forward name="success" path="/custMailings.jsp" />
</action>
<action input="/querySearch-body.jsp" name="querySearchActionForm" path="/querySearchAction" type="com.lyonsvalley.custcompass.QuerySearchAction">
<forward name="multFound" path="/chooseQuery.jsp" />
<forward name="oneFound" path="/queryInfo.jsp" />
</action>
<action input="/queryInfo-body.jsp" name="querySaveActionForm" path="/saveQueryAction" scope="request" type="com.lyonsvalley.custcompass.SaveQueryAction" validate="true">
<forward name="prompt" path="/querySpecPrompts.jsp" />
<forward name="success" path="/inbox.jsp" />
</action>
<action input="/querySpecPrompts-body.jsp" name="querySpecPromptActionForm" path="/reportmillservlet" scope="request" type="com.lyonsvalley.custcompass.ReportMillServlet" validate="true" />
<action input="/querySpecPrompts-body.jsp" name="querySpecPromptActionForm" path="/executeQueryAction" type="com.lyonsvalley.custcompass.ExecuteQueryAction">
<forward name="adhocOutput" path="/queryResults.jsp" />
</action>
<action path="/getMaterialsForQueryAction" type="com.lyonsvalley.custcompass.GetMaterialsForQueryAction">
<forward name="success" path="/querySpecMaterials.jsp" />
</action>
<action name="saveQueryMaterialActionForm" path="/saveQueryMaterialAction" type="com.lyonsvalley.custcompass.SaveQueryMaterialAction">
<forward name="success" path="/getMaterialsForQueryAction.do" />
</action>
<action path="/removeQueryMaterialAction" type="com.lyonsvalley.custcompass.RemoveQueryMaterialAction">
<forward name="success" path="/getMaterialsForQueryAction.do" />
</action>
<action input="/fileImport-body.jsp" name="fileImportActionForm" path="/fileImportAction" type="com.lyonsvalley.custcompass.FileImportAction">
<forward name="success" path="/fileImportResults.jsp" />
</action>
<action input="/staffInfo-body.jsp" name="staffSaveActionForm" path="/staffSaveAction" type="com.lyonsvalley.custcompass.StaffSaveAction">
<forward name="success" path="/inbox.jsp" />
</action>
<action path="/getRolesForStaffAction" type="com.lyonsvalley.custcompass.GetRolesForStaffAction">
<forward name="success" path="/staffRoles.jsp" />
</action>
<action input="/staffRoles-body.jsp" name="staffRoleSaveActionForm" path="/staffRoleSaveAction" type="com.lyonsvalley.custcompass.StaffRoleSaveAction">
<forward name="success" path="/getRolesForStaffAction.do" />
</action>
</action-mappings>
<message-resources null="false" parameter="ApplicationResources" />
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" />
</plug-in>
<plug-in className="org.apache.struts.tiles.TilesPlugin">
<set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" />
</plug-in>
</struts-config>