I'm populating an <s:select>
from database. The action class is model-driven.
@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value="struts-default")
public final class TestAction extends ActionSupport implements Serializable, ValidationAware, Preparable, ModelDriven<Transporter>
{
@Autowired
private final transient SharableService sharableService=null;
private static final long serialVersionUID = 1L;
private Transporter transporter; //Getter and setter
private Long transporterId; //Getter and setter.
private List<Transporter> transporters; //Getter only.
@Action(value = "Test",
results = {
@Result(name=ActionSupport.SUCCESS, location="Test.jsp"),
@Result(name = ActionSupport.INPUT, location = "Test.jsp")},
interceptorRefs={@InterceptorRef(value="defaultStack", params={"validation.validateAnnotatedMethodOnly", "true", "validation.excludeMethods", "load"})})
public String load() throws Exception
{
return ActionSupport.SUCCESS;
}
@Validations(
requiredFields={@RequiredFieldValidator(fieldName="transporterId", type= ValidatorType.FIELD, key = "transporter.required")})
@Action(value = "testInsert",
results = {
@Result(name=ActionSupport.SUCCESS, location="Test.jsp", params={"namespace", "/admin_side", "actionName", "Test"}),
@Result(name = ActionSupport.INPUT, location = "Test.jsp")},
interceptorRefs={@InterceptorRef(value="defaultStack", params={"validation.validateAnnotatedMethodOnly", "true"})})
public String insert() {
System.out.println("Selected item in the drop box : "+transporterId);
return ActionSupport.SUCCESS;
}
@Override
public void prepare() throws Exception {
transporters=sharableService.getTransporterList();
}
@Override
public Transporter getModel() {
return transporter;
}
}
and the following is <s:select>
:
<s:select id="transporterId"
name="transporterId"
list="transporters"
value="transporterId"
listKey="transporterId"
listValue="transporterName"
headerKey="" headerValue="Select"
listTitle="transporterName"/>
This works perfectly.
I need this <s:select>
in another action class which implements ModelDriven<ZoneTable>
.
The table structure is simple, transporter->zone_table->country->state->city
. There exists a one-to-many relationship between these tables.
How can we have a model driven action class implementing ModelDrven<ZoneTable>
in which Transporter
can be mapped to <s:select>
, something like?
@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value="struts-default")
public final class ZoneAction extends ActionSupport implements Serializable, ValidationAware, Preparable, ModelDriven<ZoneTable>
{
@Autowired
private final transient ZoneService zoneService=null;
@Autowired
private final transient SharableService sharableService=null;
private ZoneTable entity=new ZoneTable(); //Getter and setter.
private Long transporterId; //Getter and setter.
private List<Transporter> transporters; //Getter only.
@Override
public ZoneTable getModel() {
return entity;
}
@Override
public void prepare() throws Exception {
transporters=sharableService.getTransporterList();
}
}
Doing like this doesn't work. It doesn't set the value of transporterId
upon submission, since the action class is implementing ModelDriven<ZoneTable>
and not ModelDriven<Transporter>
like the first case.
Is this possible using the model driven approach?
EDIT:
ZoneTable.java
public class ZoneTable implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "zone_id", nullable = false)
private Long zoneId;
@Column(name = "zone_name", length = 45)
private String zoneName;
@JoinColumn(name = "transporter_id", referencedColumnName = "transporter_id")
@ManyToOne(fetch = FetchType.LAZY)
private Transporter transporterId;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "zoneTable", fetch = FetchType.LAZY)
private Set<ZoneCharge> zoneChargeSet;
@OneToMany(mappedBy = "zoneId", fetch = FetchType.LAZY)
private Set<Country> countrySet;
//Getters and setters + constructors.
}
Zone.jsp
<s:form namespace="/admin_side" action="Zone" validate="true" id="dataForm" name="dataForm" cssClass="search_form general_form">
<s:label key="label.zone.name" for="zone"/>
<s:textfield id="zoneName" name="zoneName" cssClass="validate[required, maxSize[45], minSize[2]] text-input text"/>
<s:fielderror fieldName="zoneName"/>
<s:label key="label.transporter.name" for="transporterId"/>
<s:select id="transporterId" name="transporterId" list="transporters" value="transporterId" listKey="transporterId" listValue="transporterName" headerKey="" headerValue="Select" listTitle="transporterName"/>
<s:fielderror fieldName="transporterId"/>
<s:text name="label.submit"/>
<s:submit id="btnSubmit" name="btnSubmit" value="Submit" action="AddZone"/>
</s:form>
Since this post has already a lot of code, I'm not posting the action class ZoneAction.java
here. In case, it is needed, it is available here.
You need a converter to convert
transporterId
toTransporter
Object. It goes like this:The next thing to do is to map this class in a file called
xwork-conversion.properties
. This file must reside in your classpath i.e. inclasses
directory. Enter the following entries inxwork-conversion.properties
I have not tested it, but I think it should work.
If you need more information on how type converters work, follow this url.