title: Struts 1 ActionForm - retrieving a collection from pure HTML
body: <p>Hi all I have (just like the rest) inherited some struts 1 code. I have had need to add a few more pages to this project. </p>
  
  <p><strong>What I cannot figure out is how to map several distinct but similarly natured input elements to my ActionForm.</strong></p>
  
  <p>Let me elaborate. I create a new <code>&lt;Input&gt;</code> element dynamically as the user inputs more and more items (I use the YUI autocomplete form element and for each entered input I add it as an input element to my form and draw a new YUI autocomplete - complex sounding, I know)</p>
  
  <p>So... My form looks a bit like (... after some prettifying and some such...):</p>
  
  <pre><code>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&gt;
  &lt;html&gt;
      &lt;head&gt;
          &lt;meta http-equiv="content-type" content="text/html; charset=utf-8"&gt;
          &lt;title&gt;My Cool App - Test Case Builder&lt;/title&gt;  
  
          &lt;link rel="stylesheet" type="text/css" href="../script/yui/fonts/fonts-min.css" /&gt;
          &lt;link rel="stylesheet" type="text/css" href="../skins/myCoolApp/button/button.css" /&gt;
          &lt;link rel="stylesheet" type="text/css" href="../script/yui/autocomplete/assets/skins/sam/autocomplete.css" /&gt;
          &lt;link rel="stylesheet" type="text/css" media="screen" href="../skins/myCoolApp/testcase.css" /&gt;
  
  
          &lt;!-- YUI JAVA SCRIPTS --&gt;
          &lt;script type="text/javascript" src="../script/yui/yahoo-dom-event/yahoo-dom-event.js"&gt;&lt;/script&gt;
          &lt;script type="text/javascript" src="../script/yui/element/element-min.js"&gt;&lt;/script&gt;
          &lt;script type="text/javascript" src="../script/yui/button/button-min.js"&gt;&lt;/script&gt;
          &lt;script type="text/javascript" src="../script/yui/datasource/datasource-min.js"&gt;&lt;/script&gt;
          &lt;script type="text/javascript" src="../script/yui/autocomplete/autocomplete-min.js"&gt;&lt;/script&gt;
  
  
          &lt;!-- APP JAVA SCRIPTS --&gt;
          &lt;script type="text/javascript" src="../script/myCoolApp/myCoolApp.js" &gt;&lt;/script&gt;
          &lt;script type="text/javascript" src="../script/myCoolApp/stack.js" &gt;&lt;/script&gt;
          &lt;script type="text/javascript" src="../script/myCoolApp/testcase/testcase.js"&gt;&lt;/script&gt;
          &lt;script type="text/javascript" src="../script/myCoolApp/testcase/default-data.js" &gt;&lt;/script&gt;
          &lt;script type="text/javascript" src="../script/myCoolApp/testcase/data-structs.js" &gt;&lt;/script&gt;
          &lt;script type="text/javascript" src="../script/myCoolApp/testcase/ui-elements.js" &gt;&lt;/script&gt;
  
  
      &lt;/head&gt;
      &lt;body class="cf010"&gt;
          &lt;div id="wrap"&gt;
              &lt;div id="header"&gt;
                  &lt;div id="main-header"&gt;
                      COOL APP
                  &lt;/div&gt;                
              &lt;/div&gt;
              &lt;div id="main-body"&gt;
                  &lt;div id="content"&gt;
                      &lt;div class="col main"&gt;
                          &lt;div id="main"&gt;
                              &lt;form method="post" id="testcaseForm" class="typea" action=""&gt;
                                  &lt;fieldset&gt;
                                      &lt;legend&gt;Test Case Builder&lt;/legend&gt;
                                      &lt;div id="tk1" class="tabcontrol"&gt;
                                          &lt;ul class="tabs"&gt;
                                              &lt;li class="first active"&gt;
                                                  &lt;a href="#"&gt;
                                                      &lt;span&gt;General&lt;/span&gt;
                                                  &lt;/a&gt;
                                              &lt;/li&gt;
                                              &lt;li class="last"&gt;
                                                  &lt;a href="#"&gt;
                                                      &lt;span&gt;Parameters&lt;/span&gt;
                                                  &lt;/a&gt;
                                              &lt;/li&gt;
                                          &lt;/ul&gt;
                                          &lt;div id="tab0" class="tc-panel"&gt;
                                              &lt;dl class="cls9"&gt;
                                                  &lt;dt&gt;
                                                      &lt;label for="scenario"&gt;Choose Scenario:&lt;/label&gt;
                                                  &lt;/dt&gt;
                                                  &lt;dd&gt;
                                                      &lt;input type="text" id="scenario" name="scenario" class="text" /&gt;
                                                      &lt;span id="scenarioToggle"&gt;&lt;/span&gt;
                                                      &lt;div class="auto-complete" id="scenarioContainer"&gt;&lt;/div&gt;
                                                  &lt;/dd&gt;
                                                  &lt;dt&gt;
                                                      &lt;label for="ruleID"&gt;Choose Rule ID:&lt;/label&gt;
                                                  &lt;/dt&gt;
                                                  &lt;dd&gt;
                                                      &lt;input type="text" id="ruleID" name="ruleID" class="text" /&gt;
                                                      &lt;span id="ruleIDToggle"&gt;&lt;/span&gt;
                                                      &lt;div class="auto-complete" id="ruleIDContainer"&gt;&lt;/div&gt;
                                                  &lt;/dd&gt;
                                                  &lt;dt&gt;
                                                      &lt;label for="Test Case Name" accesskey="t"&gt;&lt;span class="accesskey"&gt;T&lt;/span&gt;est Case Name:&lt;/label&gt;
                                                  &lt;/dt&gt;
                                                  &lt;dd&gt;
                                                      &lt;input type="text" id="testCaseName" name="testCaseName" class="text" /&gt;
                                                  &lt;/dd&gt;
                                              &lt;/dl&gt;
                                          &lt;/div&gt;
                                          &lt;div id="tab1" class="tc-panel hidden"&gt;
                                              &lt;div class="toolbar" id="action-bar"&gt;
                                                  &lt;ul&gt;
                                                      &lt;li class="first"&gt;
                                                         &lt;a title="select all" href="#" id="btmSelectAll" class="button"&gt;
                                                             &lt;span&gt;select all&lt;/span&gt;
                                                         &lt;/a&gt;
                                                      &lt;/li&gt;
                                                      &lt;li&gt;
                                                         &lt;a title="remove row" href="#" id="btmRemove" class="button"&gt;
                                                             &lt;span&gt;remove row&lt;/span&gt;
                                                         &lt;/a&gt;
                                                      &lt;/li&gt;
                                                      &lt;li&gt;
                                                         &lt;a title="undo last" href="#" id="btmRollBack" class="button disabled"&gt;
                                                             &lt;span&gt;undo last&lt;/span&gt;
                                                         &lt;/a&gt;
                                                      &lt;/li&gt;
                                                      &lt;li class="last"&gt;
                                                         &lt;a title="accept row" href="#" id="btmAccept" class="button disabled"&gt;
                                                             &lt;span&gt;accept row&lt;/span&gt;
                                                         &lt;/a&gt;
                                                      &lt;/li&gt;
                                                  &lt;/ul&gt;
                                              &lt;/div&gt;
                                              &lt;div id="param.list" class="gridclip"&gt;
                                                  &lt;table id='param.list.tbl' class='grid modela' &gt;
                                                      &lt;caption&gt;Test Case Summary&lt;/caption&gt;
                                                      &lt;col/&gt;&lt;col/&gt;&lt;col/&gt;          
                                                      &lt;thead&gt;
                                                          &lt;tr&gt;
                                                              &lt;th class='hl center first'&gt;
                                                                  &lt;input class='grid-select-all' type='checkbox' /&gt;
                                                              &lt;th&gt;
                                                              &lt;th scope='col'&gt;Row&lt;/th&gt;
                                                              &lt;th scope='col'&gt;Parameter&lt;/th&gt;
                                                              &lt;th scope='col' class='last'&gt;Value&lt;/th&gt;
                                                          &lt;/tr&gt;
                                                      &lt;/thead&gt;
                                                      &lt;tfoot&gt;
                                                          &lt;tr&gt;
                                                              &lt;th scope='row'&gt;Total&lt;/th&gt;
                                                              &lt;td colspan='3'&gt;2 parameters as Test Case input&lt;/td&gt;
                                                          &lt;/tr&gt;
                                                      &lt;/tfoot&gt;
                                                      &lt;tbody id='param.list.tbl.body'&gt;               
                                                          &lt;tr class='odd'&gt;
                                                              &lt;td class='rowcheck center first'&gt;
                                                                  &lt;input value='param1###value1' id='cb1' name='SelectedRows' class='grid-select-row' type='checkbox'/&gt;
                                                              &lt;/td&gt;
                                                              &lt;td class='id'&gt;1&lt;/td&gt;
                                                              &lt;td&gt;param1&lt;/td&gt;
                                                              &lt;td class='last'&gt;value1&lt;/td&gt;
                                                          &lt;/tr&gt;
                                                          &lt;tr class='even'&gt;
                                                              &lt;td class='rowcheck center first'&gt;
                                                                  &lt;input value='param2###value2' id='cb2' name='SelectedRows' class='grid-select-row' type='checkbox'/&gt;
                                                              &lt;/td&gt;
                                                              &lt;td class='id'&gt;2&lt;/td&gt;
                                                              &lt;td&gt;param2&lt;/td&gt;
                                                              &lt;td class='last'&gt;value2&lt;/td&gt;
                                                          &lt;/tr&gt;
                                                          &lt;tr class='odd'&gt;               
                                                              &lt;td class='rowcheck center first' /&gt;
                                                              &lt;td class='id'&gt;&lt;em&gt;new&lt;/em&gt;&lt;/td&gt;
                                                              &lt;td&gt;
                                                                  &lt;dl class='clsTable'&gt;
                                                                      &lt;dt&gt;
                                                                          &lt;input type='text' id='param' name='param' class='text paramInput' /&gt;
                                                                      &lt;/dt&gt;
                                                                      &lt;dd&gt;
                                                                          &lt;span id='paramToggle' /&gt;
                                                                      &lt;/dd&gt;
                                                                      &lt;div class='auto-complete' id='paramContainer' /&gt;
                                                                  &lt;/dl&gt;
                                                              &lt;/td&gt;
                                                              &lt;td class='last'&gt;
                                                                  &lt;dl class='clsTable'&gt;
                                                                      &lt;dt&gt;
                                                                          &lt;input type='text' id='value' name='value' class='text valueInput' /&gt;
                                                                      &lt;/dt&gt;
                                                                  &lt;/dl&gt;
                                                              &lt;/td&gt;
                                                          &lt;/tr&gt;
                                                      &lt;/tbody&gt;
                                                  &lt;/table&gt;
                                              &lt;/div&gt;
                                           &lt;/div&gt;
                                      &lt;/div&gt; &lt;!-- tabcontrol --&gt;
                                  &lt;/fieldset&gt;
                                  &lt;div class="submit-box"&gt;
                                      &lt;input type="submit" name="formRun" id="formRun" class="form-save"
                                          value="Execute" accesskey="x" title="Run: Press Alt + [Shift] + x" /&gt;
                                      &lt;input type="submit" name="formSave" id="formSave"
                                          value="Save" accesskey="s" title="Save: Press Alt + [Shift] + s" /&gt;
                                      &lt;input type="submit" name="formLoad" id="formLoad"
                                          value="Load" accesskey="l" title="Load: Press Alt + [Shift] + l" /&gt;
                                      &lt;input type="submit" name="formCancel" id="formCancel" class="form-cancel"
                                          value="Cancel" accesskey="c"  title="Cancel: Press Alt + [Shift] + c" /&gt;
                                  &lt;/div&gt;
                              &lt;/form&gt;
                          &lt;/div&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>As you can see the following is pretty much a duplicate:</p>
  
  <pre><code>&lt;tr class='odd'&gt;
      &lt;td class='rowcheck center first'&gt;
          &lt;input value='param1###value1' id='cb1' name='SelectedRows' class='grid-select-row' type='checkbox'/&gt;
      &lt;/td&gt;
      &lt;td class='id'&gt;1&lt;/td&gt;
      &lt;td&gt;param1&lt;/td&gt;
      &lt;td class='last'&gt;value1&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr class='even'&gt;
      &lt;td class='rowcheck center first'&gt;
          &lt;input value='param2###value2' id='cb2' name='SelectedRows' class='grid-select-row' type='checkbox'/&gt;
      &lt;/td&gt;
      &lt;td class='id'&gt;2&lt;/td&gt;
      &lt;td&gt;param2&lt;/td&gt;
      &lt;td class='last'&gt;value2&lt;/td&gt;
  &lt;/tr&gt;
  </code></pre>
  
  <p>The relevant part of my stuts-config.xml file is:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd"&gt;
  &lt;struts-config&gt;
      &lt;data-sources /&gt;
      &lt;form-beans&gt;
          &lt;form-bean name="TestCaseForm"  type="com.blahblah.mycoolapp.forms.TestCaseForm" /&gt;
      &lt;/form-beans&gt;
      &lt;action-mappings&gt;
          &lt;action path="/pages/SaveTestCase" name="TestCaseForm"
              type="org.springframework.web.struts.DelegatingActionProxy" scope="request"&gt;
          &lt;/action&gt;
      &lt;/action-mappings&gt;
      &lt;message-resources parameter="MessageResources" /&gt;
  &lt;/struts-config&gt;
  </code></pre>
  
  <p>I also use spring 2.56 (The relevant part being):</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans
             http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"&gt;
  
      &lt;bean name="/pages/SaveTestCase" class="com.blahblah.mycoolapp.actions.TestCaseBuilderSaveAction" /&gt;
  
  &lt;/beans&gt;
  </code></pre>
  
  <p>My Java ActionForm class (from what I had learned off the net) is:</p>
  
  <pre><code>package com.blahblah.mycoolapp.forms;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import org.apache.struts.action.ActionForm;
  
  public class TestCaseForm extends ActionForm {
  
      private static final long serialVersionUID = 2352146257739099766L;
  
      private String scenario;
      private String ruleID;
      private String testCaseName;
      private List&lt;String&gt; SelectedRows = new ArrayList&lt;String&gt;() ;
  
      public String getScenario() {
          return scenario;
      }
  
      public void setScenario(String scenario) {
          this.scenario = scenario;
      }
  
      public String getRuleID() {
          return ruleID;
      }
  
      public void setRuleID(String ruleID) {
          this.ruleID = ruleID;
      }
  
      public String getTestCaseName() {
          return testCaseName;
      }
  
      public void setTestCaseName(String testCaseName) {
          this.testCaseName = testCaseName;
      }
  
      public List&lt;String&gt; getSelectedRows() {
          return SelectedRows;
      }
  
      public void setSelectedRows(int index, String value) {
          this.SelectedRows.add(value);
      }
  }
  </code></pre>
  
  <p>The question is <strong>why do I get an empty SelectedRows in my TestCaseBuilderSave Action?</strong></p>
  
  <p>Thanks all who have the patience to read such a long question...</p>
  
  <p>and (hopefully) thanks to all you potential saviors :)</p>
  
  <p><strong>EDIT 1:</strong></p>
  
  <p>Due to @ahiru's request I post my action class which - for the time being is just a stripped down. almost do nothing, class:</p>
  
  <pre><code>public class TestCaseBuilderSaveAction extends Action {
  
  
      @Override
      public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
              HttpServletResponse response) throws Exception {
  
          response.setContentType("application/octet-stream");
          response.setHeader("Content-Disposition","attachment;filename=superfish.xml");
  
          try
          {
             ServletOutputStream out = response.getOutputStream();
  
             String contentStr = "&lt;Yaneeve&gt;Has been here...&lt;/Yaneeve&gt;";
             byte[] bytes = contentStr.getBytes();
             out.write(bytes, 0, bytes.length);
             out.flush();
             out.close();
  
          }catch(Exception e){
             e.printStackTrace();
        }
  
        return null;
      }
  }
  </code></pre>