Error setting expression 'spa.amount' with

2020-02-06 12:49发布

问题:

I am trying following code to get data in spa object fields. Thus, I am using the following code but it is showing null values and giving the following error

Error setting expression 'spa.amount' with value '[Ljava.lang.String;@10dd65e'
ognl.OgnlException: target is null for setProperty(null, "amount", [Ljava.lang.String;@10dd65e) 

Jsp code:

<s:form action="UpdatedPaid" method="post">  
        <s:if test="paidList.size >  0"> 
            <s:iterator value="paidList" var="pdlst">
                <div class="box">
                    <span class="label">Amount</span>
                    <span class="ib"> 
                        <s:hidden name="spa.id" id="paidId">
                            <s:param name="value">
                                <s:property value="paidId"/>
                            </s:param>
                        </s:hidden>
                        <s:textfield name="spa.amount" id="amount">
                            <s:param name="value">
                                <s:property value="amount"/>
                            </s:param>
                        </s:textfield>
                    </span>
                </div>
                <div class="box">
                    <span class="label">Payment Date</span>
                    <span class="ib"> <s:textfield name="spa.paymentDate" id="paymentDate">
                            <s:param name="value">
                                <s:property value="paymentDate"/>
                            </s:param>
                        </s:textfield>
                    </span>
                </div>
                <div class="box">
                    <span class="label">Payment Mode</span>
                    <span class="ib">
                        <s:textfield name="spa.paymentMode" id="payment_mode" readonly="true">
                            <s:param name="value">
                                <s:property value="payment_mode"/>
                            </s:param>
                        </s:textfield>
                    </span>
                </div>
            </s:iterator>
        </s:if>
    </s:form>

My Action Class

package iland.payment;

import static com.opensymphony.xwork2.Action.SUCCESS;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import iland.hbm.SupplierPaidDetails;

public class hbmCashAction extends ActionSupport implements ModelDriven<SupplierPaidDetails> {

    SupplierPaidDetails spa = new SupplierPaidDetails();

    public SupplierPaidDetails getSpa() {
        return spa;
    }

    public void setSpa(SupplierPaidDetails spa) {
        this.spa = spa;
    }

    public String update() {
        System.out.println("--------");
        System.out.println(spa.getId() + " " + spa.getPaymentMode() + " " + spa.getAmount());
        System.out.println("--------");
        return SUCCESS;
    }

    @Override
    public SupplierPaidDetails getModel() {
        return spa;
    }

}

SupplierPaidDetails

public class SupplierPaidDetails  implements java.io.Serializable {


     private Long id;
     private SupplierPaymentDetails supplierPaymentDetails;
     private Float amount;
     private String paymentMode;
     private Date paymentDate;
     private Date addDate;
     private String status;
     private Set supplierPaidOnlines = new HashSet(0);
     private Set supplierPaidCashes = new HashSet(0);
     private Set supplierPaidChecks = new HashSet(0);

    public SupplierPaidDetails() {
    }


    public SupplierPaidDetails(SupplierPaymentDetails supplierPaymentDetails, Date addDate) {
        this.supplierPaymentDetails = supplierPaymentDetails;
        this.addDate = addDate;
    }
    public SupplierPaidDetails(SupplierPaymentDetails supplierPaymentDetails, Float amount, String paymentMode, Date paymentDate, Date addDate, String status, Set supplierPaidOnlines, Set supplierPaidCashes, Set supplierPaidChecks) {
       this.supplierPaymentDetails = supplierPaymentDetails;
       this.amount = amount;
       this.paymentMode = paymentMode;
       this.paymentDate = paymentDate;
       this.addDate = addDate;
       this.status = status;
       this.supplierPaidOnlines = supplierPaidOnlines;
       this.supplierPaidCashes = supplierPaidCashes;
       this.supplierPaidChecks = supplierPaidChecks;
    }

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }
    public SupplierPaymentDetails getSupplierPaymentDetails() {
        return this.supplierPaymentDetails;
    }

    public void setSupplierPaymentDetails(SupplierPaymentDetails supplierPaymentDetails) {
        this.supplierPaymentDetails = supplierPaymentDetails;
    }
    public Float getAmount() {
        return this.amount;
    }

    public void setAmount(Float amount) {
        this.amount = amount;
    }
    public String getPaymentMode() {
        return this.paymentMode;
    }

    public void setPaymentMode(String paymentMode) {
        this.paymentMode = paymentMode;
    }
    public Date getPaymentDate() {
        return this.paymentDate;
    }

    public void setPaymentDate(Date paymentDate) {
        this.paymentDate = paymentDate;
    }
    public Date getAddDate() {
        return this.addDate;
    }

    public void setAddDate(Date addDate) {
        this.addDate = addDate;
    }
    public String getStatus() {
        return this.status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
    public Set getSupplierPaidOnlines() {
        return this.supplierPaidOnlines;
    }

    public void setSupplierPaidOnlines(Set supplierPaidOnlines) {
        this.supplierPaidOnlines = supplierPaidOnlines;
    }
    public Set getSupplierPaidCashes() {
        return this.supplierPaidCashes;
    }

    public void setSupplierPaidCashes(Set supplierPaidCashes) {
        this.supplierPaidCashes = supplierPaidCashes;
    }
    public Set getSupplierPaidChecks() {
        return this.supplierPaidChecks;
    }

    public void setSupplierPaidChecks(Set supplierPaidChecks) {
        this.supplierPaidChecks = supplierPaidChecks;
    }
}

Edit i want to set all fields of SupplierPaidDetailsincluding set(supplierPaidOnlines,supplierPaidCashes,supplierPaidChecks these can contains many instances) and supplierPaymentDetails from jsp

How to resolve above errors.

回答1:

According to the error

Error setting expression 'spa.amount' with value '[Ljava.lang.String;@10dd65e'

seems that OGNL is trying to set a value of type String[] to amount property of spa bean.

Reading further

ognl.OgnlException: target is null for setProperty(null, "amount", [Ljava.lang.String;@10dd65e)  

looks like spa reference is null, so OGNL is unable to set a value to a null because it will throw a null pointer exception.

To resolve the issue you should initialize the reference of spa.

Next the problem arises because you use a model driven. The model driven interceptor pushes a model on top of the value stack, which is an OGNL root. And you have initialized the instance of spa. Seems that OGNL even if searches from the top of the value stack down the stack can't find the instance of spa. So, to access action properties directly you can use technique described in this answer Passing parameters to action through ModelDriven in Struts 2.3.16.

The method expected by OGNL on reference of spa is

public void setAmount(String[] amounts) {
   this.amounts = amounts;
}

You don't have such method and you probably not expected to receive an array of strings. But the problem is that you are doing it. Because parameters with the same name are packaged into String[]. To have different names corresponding to each iterated object you should use indexed property names. You can find an example if indexed properties in this answer Repopulate an ArrayList from JSP with Struts 2.

Your properties are available directly from the model because your action is model driven and it should have a List<SupplierPaymentDetails> paidList that is iterated. You can use this property to populate the submitted values or use another with the same type.

ModelDriven example you can learn, but it doesn't use indexed properties. To use it properly you can use this answer How to pass a Map<ObjectA, List<ObjectB>> to action in Struts 2.