Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Struts 2: updating a list of objects from a form with model driven architecture

I already searched and found several approaches here, but I can't get them working for my project.

I want to show an edit page for a list of objects, which should all be updated at once. I use the model driven architecture approach to achieve this, but I can't get it running properly. I can always display and iterate the list and its values, but I can't modify its values.

So here is what I'm currently doing:

I have a Model 'Teilzeitgrad' in my database, which has some simple attributes with getters and setters.

public class Teilzeitgrad {

    private Date datumAb;
    private Date datumBis;
    private double betrag;

    // ... getters and setters

}

In my Action-Class I implement the ModelDriven Interface with a List of Teilzeitgrad-Objects

public class DienstabschnittViewJahrAction implements ModelDriven<List<Teilzeitgrad>>, Preparable
{
    List<Teilzeitgrad> teilzeitgrads;
    private String tzgTypKey;
    private Integer jahrIndex;

    public String execute() {
        return SUCCESS;
    }

    public List<Teilzeitgrad> getModel()
    {
        if(teilzeitgrads == null) {
            teilzeitgrads = getTeilzeitgradListByTypAndJahr(getTzgTypKey(), getJahrIndex());
        }
        return teilzeitgrads;
    }

    public List<Teilzeitgrad> getTeilzeitgrads()
    {
        return teilzeitgrads;
    }

    public void setTeilzeitgrads(List<Teilzeitgrad> teilzeitgrads)
    {
        this.teilzeitgrads = teilzeitgrads;
    }

    @Override
    public void prepare() throws Exception
    {
        // TODO Auto-generated method stub  
    }

    public String getTzgTypKey()
    {
        return tzgTypKey;
    }

    public void setTzgTypKey(String tzgTypKey)
    {
        this.tzgTypKey = tzgTypKey;
    }

    public Integer getJahrIndex()
    {
        return jahrIndex;
    }

    public void setJahrIndex(Integer jahrIndex)
    {
        this.jahrIndex = jahrIndex;
    }
}

The action mapping in struts.xml is defined as follows:

<action name="*/auth/GroupAdmin/processEditDienstabschnittJahr" method="execute" class="org.hocon.ul.portal.action.DienstabschnittViewJahrAction">
    <result name="success" type="redirect">${referer}</result>
</action>

In my JSP File I'm iterating the model object, displaying its values in textfields or lists as follows:

<ul:form action="auth/GroupAdmin/processEditDienstabschnittJahr">
<s:iterator value="model" status="rowStatus">

<tr>
    <td style="text-align: center;">
        <s:date name="model.get(#rowStatus.index).datumAb" var="datumAb_DE" format="dd.MM.yyyy" />
        <s:textfield style="width:70px;" name="model.get(#rowStatus.index).datumAb" value="%{#datumAb_DE}" label="DatumAb"></s:textfield >
    </td>

    <td style="text-align:center;">
        <s:date name="model.get(#rowStatus.index).datumBis" var="datumBis_DE" format="dd.MM.yyyy" />
        <s:textfield style="width:70px;" name="model.get(#rowStatus.index).datumBis" value="%{#datumBis_DE}" label="DatumBis"></s:textfield >
    </td>

    <td class="currency">
        <s:set var="tzgBetrag">
            <fmt:formatNumber type="NUMBER" maxFractionDigits="0"><s:property value="%{getBetrag()*100}"></s:property></fmt:formatNumber>
        </s:set>
        <s:textfield style="width:30px;" maxlength="3" name="model.get(#rowStatus.index).betrag" value="%{#tzgBetrag}" label="Betrag"></s:textfield >
    </td>
</tr>

</s:iterator>
<s:submit style="width:24px; height:24px;" type="image" src="../../../res/24px/floppy-disk.png" value="Speichern"></s:submit>
</ul:form>

The ul-tag is from a custom taglib, which adds a customer specific url parameter to action path.

So when I display the page it shows all my Teilzeitgrad-records with a row for each entry. But when I submit the form, the list of my models is not populated. The setter setTeilzeitgrads(List<Teilzeitgrad> teilzeitgrads) is not even called at all. I also tried to access the list in array-syntax:

<s:textfield style="width:70px;" name="teilzeitgrads[#rowStatus.index].datumAb" value="%{#datumAb_DE}" label="DatumAb"></s:textfield >

but this did also not work.

Any help solving this case is apreciated! Thanks in advance!

Lenzo

like image 658
Lenz Lüers Avatar asked Nov 03 '22 13:11

Lenz Lüers


1 Answers

Ok - here is a very basic working example of list indexing. The main change is to move the creation of the model from getModel() to prepare(). This is because getModel() is called for every value you need to set the list - so you end up re-creating your model each time overwriting the previous change.

package com.blackbox.x.actions;

import java.util.ArrayList;
import java.util.List;

import com.blackbox.x.actions.ListDemo.ValuePair;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;

public class ListDemo extends ActionSupport implements ModelDriven<List<ValuePair>>, Preparable {


private List<ValuePair> values;

@Override
public List<ValuePair> getModel() {

    return values;

}

public String execute() {

    for (ValuePair value: values) {
        System.out.println(value.getValue1() + ":" + value.getValue2());
    }

    return SUCCESS;
}


public void  prepare() {
    values = new ArrayList<ValuePair>();
    values.add(new ValuePair("chalk","cheese"));
    values.add(new ValuePair("orange","apple"));
}


public class ValuePair {

    private String value1;
    private String value2;

    public ValuePair(String value1, String value2) {
        this.value1 = value1;
        this.value2 = value2;
    }

    public String getValue1() {
        return value1;
    }
    public void setValue1(String value1) {
        this.value1 = value1;
    }
    public String getValue2() {
        return value2;
    }
    public void setValue2(String value2) {
        this.value2 = value2;
    }
}
}

and the corresponding jsp

<%@ taglib prefix="s" uri="/struts-tags" %>    
<html>
<head>


</head>
<body>


<s:form action="list-demo" theme="simple">
<table>
<s:iterator value="model" status="rowStatus">
<tr>
<td><s:textfield name="model[%{#rowStatus.index}].value1" value="%{model[#rowStatus.index].value1}"/></td>
<td><s:textfield name="model[%{#rowStatus.index}].value2" value="%{model[#rowStatus.index].value2}"/></td>
</tr>
</s:iterator>
</table>
<s:submit/>
</s:form>
</body>
</html>
like image 124
user497087 Avatar answered Nov 24 '22 06:11

user497087