1

I am very new to struts. I am creating a sample web application. Below is a JSP page that takes values from the user. "Passengers" refers to the number of rows i want to create and is available on the value stack from the previous action.

<s:form method="post" action="passengerDetailsEntered">
    <tbody>
        <s:iterator begin="0" end="passengers-1">
          <tr>
            <td><s:property value="top+1"/></td>
            <td><s:textfield name="passengerDetails.name"></s:textfield></td>
            <td><s:textfield name="passengerDetails.age"></s:textfield></td>
            <td><s:select list="#{'M':'Male','F':'Female'}" 
                          headerValue="Select" headerKey="-1" 
                          name="passengerDetails.sex"></s:select>
            </td>
          </tr>
        </s:iterator>
        <s:hidden name="totalFare" value="%{totalFare}"/>
        <s:submit value="Submit" id="select"></s:submit>
    </tbody>
</s:form>

So if i want to add details of 3 passengers then value of passengers will be 3. It works fine upto here. Now what my anticipation is when i submit this form, then the iterator itself create a list containing two objects of type PassengerDetails, if value of passengers is 2. "passengerDetails" is an object of type PassengerDetails. Following is my PassengerDetails POJO.

      package com.model;
        import java.io.Serializable;
        import javax.persistence.Column;
        import javax.persistence.Entity;
        import javax.persistence.FetchType;
        import javax.persistence.Id;
        import javax.persistence.JoinColumn;
        import javax.persistence.ManyToOne;
        import javax.persistence.Table;

      @Entity
@Table(name="passengerdetails")
public class PassengerDetails implements Serializable{

    private static final long serialVersionUID = 4786387763215540175L;
    private String name;
    private int age;
    private char sex;
    private TicketDetails ticketDetails;
    @Id
    private int passengerid;

    @Column(name="name")
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @Column(name="age")
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    @Column(name="sex")
    public char getSex() {
        return sex;
    }
    public void setSex(char sex) {
        this.sex = sex;
    }

    @ManyToOne(fetch = FetchType.EAGER)  
    @JoinColumn(name="tid")  
    public TicketDetails getTicketDetails() {
        return this.ticketDetails;
    }
    public void setTicketDetails(TicketDetails ticketDetails) {
        this.ticketDetails = ticketDetails;
    }
}

Following is my action class TicketBookingAction and the method passengerDetails of it is called when action "passengerDetailsEntered" is executed:

    package com.view;

import java.text.ParseException;
import java.util.Calendar;
import java.util.List;
import java.util.Map;

import com.controller.FetchDetailsManager;
import com.controller.PassengerDetailsManager;
import com.controller.TicketDetailsManager;
import com.model.PassengerDetails;
import com.model.ScheduleDetails;
import com.model.TicketDetails;
import com.model.UserDetails;
import com.opensymphony.xwork2.ActionContext;

public class TicketBookingAction{


    private List<PassengerDetails> passengerDetails;
    public List<PassengerDetails> getPassengerDetails() {
        return passengerDetails;
    }
    public void setPassengerDetails(List<PassengerDetails> passengerDetails) {  
        this.passengerDetails=passengerDetails;
    }

    public String passengerDetails()
    {
        System.out.println("Name is");
        System.out.println(getPassengerDetails().get(0).getName());
        System.out.println(getPassengerDetails().get(0).getAge());
        System.out.println(getPassengerDetails().get(0).getSex());
        System.out.println(getPassengerDetails().get(1).getName());
        System.out.println(getPassengerDetails().get(1).getAge());
        System.out.println(getPassengerDetails().get(1).getSex());
        return "passengerDetailsFilled";
    }
}

But it prints the name as null. Age is printed as entered by the user. Sex is printed as some junk character. Can anyone please help me with the concept that lies behind this? And what should i do to get all the values entered by me on the form in my action class. Thanks in advance.

Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
Gaurav Kumar
  • 1,091
  • 13
  • 31

1 Answers1

0

Specify an Index, to reference the right row on each iteration:

<s:iterator begin="0" end="passengers-1" status="stat">
  <tr>
    <td><s:property value="top+1"/></td>
    <td><s:textfield name="passengerDetails[%{#stat.index}].name" /></td>
    <td><s:textfield name="passengerDetails[%{#stat.index}].age" /></td>
    <td><s:select list="#{'M':'Male','F':'Female'}" 
                  headerValue="Select" headerKey="-1" 
                  name="passengerDetails[%{#stat.index}].sex" />
    </td>
  </tr>
</s:iterator>

As a hint, self-close your tags when there is nothing inside. It would be more readable.

Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
  • Does it send a list or an array of PassengerDetails? – Gaurav Kumar Sep 27 '13 at 09:23
  • Both: http://struts.apache.org/release/2.3.x/docs/type-conversion.html#TypeConversion-BuiltinTypeConversionSupport – Andrea Ligios Sep 27 '13 at 09:26
  • Earlier i tried this by writing passengerDetails[%{top}].name and so on to refer to the rows but it didnt serve my purpose. Can you put some light on the difference b/w these two ways? – Gaurav Kumar Sep 27 '13 at 09:42
  • Always use the IteratorStatus instance to do this kind of things. Top is the object (not the counter) subject of the iteration. [Look at the last example in JavaDoc](http://struts.apache.org/release/2.3.x/struts2-core/apidocs/org/apache/struts2/components/IteratorComponent.html) , I guess you should need the value attribute filled with numbers so the object pushed on top of the stack would, coincidentally, be a number. But don't complicate your life, and always follow the KISS paradigm :) – Andrea Ligios Sep 27 '13 at 09:48
  • ligios, it served the purpose. Thanks for the explanation. – Gaurav Kumar Sep 27 '13 at 11:29
  • what if I would be usind javascript to create dynamic row in the table the the name give would be the same as name="passengerDetails[%{#stat.index}].name" – jaskirat Singh May 07 '14 at 04:49
  • You simply have to resolve the numbers by yourself. If you put passengerDetails[0].name it will work... refer at the generated HTML (View Source) to see how the values are generated. You can also append new values with javascript: http://stackoverflow.com/a/15267703/1654265 – Andrea Ligios May 07 '14 at 08:30