I have an action class that implements ModelDriven interface. This ModelDriven is a regular POJO, the problem is that one of its properties is another object.
Imagine that my ModelDriven is a object called Person and my person has an attribute called Address that is another object. Address has regular properties such as String, Long and etc.
In the JSP when I submit the form, all the regular properties used such as String, int, long in Person are mapped correctly, but all the data that should be mapped to address are not.
<s:textfield name="name" id="name" size="25" maxlength="15" />
<s:textfield name="address.zipcode" id="zipcode" size="25" maxlength="15" />
That's how I try mapping the properties. The name property I can get it right, but when it comes to map the properties in the person's address this approach does not work.
What am I doing wrong?
In time, my Address property is declared in Person instantiating the object, so it's never null.
EDIT: As requested, here the action source and the DTOs:
The Action:
@Controller
@Scope("request")
public class AnAction extends BaseAction implements ModelDriven<FakeDTO> {
private static final long serialVersionUID = 8238033889271514835L;
@Autowired
private FakeFacade facade;
private FakeDTO fakeDTO = new FakeDTO();
public String action01() {
return Action.SUCCESS;
}
public String action02() {
this.fakeDTO.setAnswer(this.fakeFacade.fakeFacadeMethod(this.fakeDTO.getComplexObject()));
return Action.SUCCESS;
}
@Override
public FakeDTO getModel() {
return this.fakeDTO;
}
}
The main DTO:
public class FakeDTO implements BaseDTO {
private static final long serialVersionUID = -2093038083351846003L;
private FakeFilterDTO filter = new FakeFilterDTO();
private String name;
public FakeDTO() {
super();
}
@Override
public FakeFilterDTO getFilter() {
return this.filter;
}
public void setFilter(final FakeFilterDTO filterParam) {
this.filter = filterParam;
}
public String getName() {
return this.name;
}
public String setName(final String nameParam) {
this.name = nameParam;
}
}
The FakeFilterDTO:
public class FakeFilterDTO extends BaseFilterDTO {
private static final long serialVersionUID = 4528040257605851210L;
private Date aDate;
private Long aLong;
private Integer anInteger;
private String aString;
public Date getADate() {
return this.aDate;
}
public void setDataInicial(final Date aDateParam) {
this.aDate = aDateParam;
}
public Long getALong() {
return this.aLong;
}
public void setALong(final Long aLongParam) {
this.aLong = aLongParam;
}
public Integer getAnInteger() {
return this.anInteger;
}
public void setAnInteger(final Integer anIntegerParam) {
this.anInteger = anIntegerParam;
}
public String getAString() {
return this.aString;
}
public void setAString(final String aStringParam) {
this.aString = aStringParam;
}
}
The struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
"http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>
<include file="META-INF/bsad/struts2/struts-config.xml" />
<package name="reports" namespace="/reports" extends="project-default">
<action name="anAction" class="anAction" method="action01">
<result>/WEB-INF/pages/success.jsp</result>
<result name="input">/WEB-INF/pages/input.jsp</result>
</action>
<action name="generateReport" class="anAction" method="action02">
<result>/WEB-INF/pages/reportGenerated.jsp</result>
</action>
</package>
</struts>
The project-default is placed in the include struts-config.xml and extends struts-default package that contains the ModelDrivenInterceptor. I can assure that because I placed a break point in this interceptor and its passing through there.
The JSP that I used as an example before would become as follows:
<s:textfield name="name" id="name" size="25" maxlength="15" />
<s:textfield name="filter.aString" id="zipcode" size="25" maxlength="15" />
For company policies I'm not allowed to copy/paste the actual Objects and its names. But that's the idea.
In the
fakeDTO
that is your model you should have a propertyaddress
which should return an object likeAddressDTO
in this object there should be a propertyzipcode
.as you haven't posted
struts.xml
your action configuration should includemodelDriven
interceptor which include in thedefaultStack
by default is used when you extendstruts-default
package. See example of model driven. The model is pushed to thetop
of thevalueStack
by the interceptor, so the object likeaddress
should be available if it has a default constructor it will be created by the OGNL andzipcode
set there. When you display the fields in the JSP theaddress.zipcode
is evaluated as an OGNL expression and retrievezipcode
from the address bean if the model is initialized that bean and zipcode itself. All beans referenced in OGNL expression should be initialized and have getter/setter properties.