使用值“[Ljava.lang.String;@10dd65e"设置表达式“spa.amount"时出错)

2022-01-16 00:00:00 java jsp struts2 ognl model-driven

我正在尝试使用以下代码来获取 spa 对象字段中的数据.因此,我正在使用以下代码,但它显示 null 值并给出以下错误

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 代码:

<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>

我的动作类:

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 类:

SupplierPaidDetails class:

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;
    }
}

我想设置 SupplierPaidDetails 类的所有字段,包括设置 (supplierPaidOnlines,supplierPaidCashes,supplierPaidChecks 这些可以包含许多实例)和来自 JSP 的 supplierPaymentDetails.

I want to set all fields of SupplierPaidDetails class including setting of (supplierPaidOnlines,supplierPaidCashes,supplierPaidChecks these can contains many instances) and supplierPaymentDetails from JSP.

如何解决以上错误?

推荐答案

根据报错

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

似乎 OGNL 正在尝试将 String[] 类型的值设置为 spa bean 的 amount 属性.

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

继续阅读

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

看起来 spa 引用是 null,所以 OGNL 无法为 null 设置值,因为它会抛出空指针异常.

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.

要解决此问题,您应该初始化 spa 的引用.

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

接下来出现问题是因为您使用了模型驱动.模型驱动拦截器将模型推送到值堆栈顶部,这是一个 OGNL 根.你已经初始化了 spa 的实例.似乎OGNL即使从堆栈顶部的值堆栈向下搜索也找不到spa的实例.因此,要直接访问动作属性,您可以使用此答案中描述的技术 Passing parameters to action through ModelDriven in Struts 2.3.16.

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.

OGNL 对 spa 的引用所期望的方法是

The method expected by OGNL on reference of spa is

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

你没有这样的方法,你可能不希望收到一个字符串数组.但问题是你正在这样做.因为同名的参数被打包成String[].要为每个迭代对象设置不同的名称,您应该使用索引属性名称.您可以在此答案中找到索引属性的示例Repopulate an ArrayList from JSP with Struts 2.

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.

您的属性可以直接从模型中获得,因为您的操作是模型驱动的,并且它应该有一个 List<SupplierPaymentDetails>迭代的paidList.您可以使用此属性来填充提交的值或使用另一个具有相同类型的值.

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 示例你可以学习,但它没有't 使用索引属性.要正确使用它,您可以使用此答案 How to pass a Map<ObjectA, List<ObjectB>>在 Struts 2 中执行操作.

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.

相关文章