Search code examples
jspjakarta-eestruts-1

why is my form throwing a No Bean Specified error in Struts on submit?


I have a dynaAction form setup that is submitted to a lookupDispatchAction. The problem is that the page loads fine but on submit the application throws a [BeanUtils.populate] with root cause java.lang.IllegalArgumentException: No bean specified that for the moment I cannot seem to catch the stack dump doesn't indicate where in code this is being caused. It was only through undoing the modified code that I was able to identify the cause as the part of code in the jsp printed below. At the moment I am trying to see if I can get more info from the debugger but so far research has hinted at probable causes none of which has helped. Below are the relevant parts of code (with the stack trace skipped to keep this post reasonable: struts-config.xml:

 <form-bean name="MonthlyInvoiceForm" type="com.myapp.form.accounting.MonthlyInvoiceForm">
                <form-property name="idMonthInvoice" type="java.lang.Long"/>
                <form-property name="creationDate" type="java.util.Date"/>
                <form-property name="adresse" type="com.myapp.model.component.CustomerAddress"/>
                <form-property name="extras" type="com.myapp.accounting.customer.ExtraInvoiceForm[]"/>
                <form-property name="creationLoc" initial="Home" type="java.lang.String"/>
                <form-property name="totalHT" type="java.math.BigDecimal"/>
                <form-property name="totalTTC" type="java.math.BigDecimal"/>
                <form-property name="prefix" type="java.lang.Integer"/>
                <form-property name="number" type="java.lang.String"/>
                <form-property name="person" type="java.lang.String"/>
                <form-property name="strTotalHT" type="java.lang.String"/>
                <form-property name="strTotalTTC" type="java.lang.String"/>
                <form-property name="customerName" type="java.lang.String"/>
                <form-property name="strIdCustomer" type="java.lang.String"/>
                <form-property name="strCreationDate" type="java.lang.String"/>
        </form-bean> 

And the form itself has the following setup:

public class MonthlyInvoiceForm extends BaseDynaForm implements ModelForm<MonthlyInvoice>{

@Override
public void reset(ActionMapping mapping, HttpServletRequest request) {
    ExtraInvoiceForm[] extraForms = new ExtraInvoiceForm[1];
    this.set("extras", extraForms);

    CustomerAddress caddress = new CustomerAddress();
    this.set("adresse", caddress);

    BigDecimal tmpTRD = new BigDecimal(BigInteger.ZERO);
    this.set("totalHT", tmpTRD);


    BigDecimal tmpTRM = new BigDecimal(BigInteger.ZERO);
    this.set("totalTTC", tmpTRM);
}

@Override
public ActionErrors validate(ActionMapping actionMapping, HttpServletRequest request) {
    ActionErrors errors = new ActionErrors();

    ExtraInvoiceForm[] extraInvoiceForms = (ExtraInvoiceForm[]) this.get("extras");
    LinkedList<String> credits = new LinkedList<String>(); 
    LinkedList<String> reductions = new LinkedList<String>(); 

    for(ExtraInvoiceForm eif: extraInvoiceForms) {
        eif.validate(errors);

        if(!eif.isBlank()) {
            if(eif.getOperation().equals(ExtraCostInvoice.CREDITOPERATION)) {
                if(credits.contains(eif.getDescription()))
                    errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("invoice.duplicate.credit", eif.getDescription()));
                else
                    credits.add(eif.getDescription());
            } else {
                if(reductions.contains(eif.getDescription()))
                    errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("invoice.duplicate.reduction", eif.getDescription()));
                else
                    reductions.add(eif.getDescription());
            }
        }
    }


    if (StringUtils.isEmpty(this.get("strCreationDate").toString()))
        errors.add("strCreationDate",new ActionError("field.required"));

    if (StringUtils.isEmpty(this.get("creationLoc").toString()))
        errors.add("creationLoc",new ActionError("field.required"));



    return errors;
}

@Override
public void populateModel(MonthlyInvoice model) throws Exception {
    DateTimeFormatter fmt = DateTimeFormat.forPattern("dd MMMM yyyy");
    DateTime crDate;


    crDate = new DateTime(fmt.withLocale(Locale.FRENCH).parseDateTime(this.get("strCreationDate").toString()));
    this.set("creationDate",BaseForm.jodaToSqlDate(crDate));

    PropertyUtils.copyProperties(model, this);
}

The jsp:

<html:form action="/toInvoiceCustomerMissions"> 
/*This is the part of code in the jsp which causes the error*/
<c:forEach var="extras" items="${MonthlyInvoiceForm.map.extras}" varStatus="vs">
                    <tr>
                        <td align="center">
                                                    <html:text indexed="true" name="extras" property="description" size="40" maxlength="100" /></td>
                        <td align="center">
                                                    <html-el:radio indexed="true" name="extras" property="operation"
                            value="<%= ExtraCostInvoice.CREDITOPERATION %>"
                            onclick="setPercentSymbol(${vs.index}, false); calcCustomerAmount();" />Déduction
                                                    <html-el:radio indexed="true" name="extras" property="operation"
                            value="<%= ExtraCostInvoice.REDUCTIONOPERATION %>"
                            onclick="setPercentSymbol(${vs.index}, true); calcCustomerAmount();" />Réduction
                                                    <html-el:radio indexed="true" name="extras" property="operation"
                            value="<%= ExtraCostInvoice.SUPPLEMENTOPERATION %>"
                            onclick="setPercentSymbol(${vs.index}, false); calcCustomerAmount();" />Supplément
                        </td>
                        <td align="center">
                                                    <html:text indexed="true" name="extras"
                            property="strAmount" size="7" maxlength="6" onchange="calcCustomerAmount();" />
                                                    <input type="text" id="extraSymbol<c:out value='${vs.index}'/>" value="&euro;"
                            readonly="readonly" size="1" style="border: none">
                                                </td>
                    </tr>
                </c:forEach>
</html:form>

Thanks in advance


Solution

  • Solved it. Turns out that you also need to iterate through every element of the allocated array and initialise it in the reset method; in this case the ExtraInvoiceForm[] extraInvoiceForms had to have every element initialised.