I have a List in a controller that has one ClientMapping Object. I am trying to gather that data in the JSP form and then send back to another controller.
Here is the controller code
@RequestMapping("/chooseMappingValues")
public ModelAndView chooseMappingValues() {
ModelAndView mav = new ModelAndView();
ClientMapping clientMappingChoices = new ClientMapping();
clientMappingChoices.setMappingName("MyMapping");
clientMappingChoices.setSchemaNameCoderepeaper("reference_tables");
List<ClientMapping> cmList = new ArrayList<ClientMapping>();
cmList.add(clientMappingChoices);
Map<String, String> databases = lookupService.getLookup("DatabaseVendor");
Map<String, String> tableNames = lookupService.getLookup("TableName");
mav.addObject("tableNames", tableNames);
mav.addObject("databaseVendor", databases);
mav.addObject("message", "Enter Mapping Name. Choose Target Database Type, Schema Name and Table for Mapping.");
mav.addObject("clientMappingChoices", cmList);
mav.setViewName("mappingtool/chooseMappingValues");
return mav;
}
ANd here is the JSP
<div class="card-body justify-content-md-center"
style="background-color: darkgray;">
<form:form action="${pageContext.request.contextPath}/mappingtool/gatherMappingDetails"
method="POST" modelAttribute="clientMappingChoices">
<c:forEach items="${clientMappingChoices}" var="cm" varStatus="status">
<div class="table-responsive">
<table
class="table table-responsive table-striped table-hover table-sm"
id="viewTable">
<tbody>
<tr>
<td colspan="2" class="fw-bolder justify-content-md-center"><h2
class="text-primary">${message}</h2>
<tr>
<td class="fw-bolder"><label for="mappingName"
class="form-label"> Client Mapping Name:</label> <label
class="text-danger"> Required</label></td>
<td class="fw-bolder"><form:input
class="form-control form-control-sm" id="mappingName"
path="${cm}.mappingName" cssStyle="width:200px;" /> <form:errors
path="${cm}.mappingName" /></td>
<tr>
<td> </td>
<td><input class="btn btn-danger my-2 my-sm-0" id="save"
type="submit" value="Save" /></td>
</tr>
</tbody>
</table>
</div>
</c:forEach>
</form:form>
I have tried to setup the path of the spring form a bunch of ways but can't seem to get the syntax correct.
Here is the error message from the code above:
2025-01-02 16:17:45,985 TRACE o.s.w.s.DispatcherServlet [http-nio-80-exec-5] Failed to complete request
org.apache.jasper.JasperException: An exception occurred processing [/WEB-INF/pages/mappingtool/chooseMappingValues.jsp] at line [151]
148: class="form-label"> Client Mapping Name:</label> <label
149: class="text-danger"> Required</label></td>
150: <td class="fw-bolder">
151: <form:input class="form-control form-control-sm" id="mappingName"
152: path="${cm}.mappingName" cssStyle="width:200px;" /> <form:errors
153: path="${cm}.mappingName" /></td>
154: </tr>
Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'ClientMapping [idPk=null, clientId=null, mappingName=MyMapping, schemaNameClient=null, schemaNameCoderepeaper=reference_tables, tableNameClient=null, tableNameCodereaper=null, columnNameClient=null, columnNameCodereaper=null, dataType=null, created=null, createdBy=null, updated=null, updatedBy=null]' of bean class [java.util.ArrayList]: Bean property 'ClientMapping [idPk=null, clientId=null, mappingName=MyMapping, schemaNameClient=null, schemaNameCoderepeaper=reference_tables, tableNameClient=null, tableNameCodereaper=null, columnNameClient=null, columnNameCodereaper=null, dataType=null, created=null, createdBy=null, updated=null, updatedBy=null]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:627) ~[spring-beans-6.1.13.jar:6.1.13]
at org.springframework.beans.AbstractNestablePropertyAccessor.getNestedPropertyAccessor(AbstractNestablePropertyAccessor.java:856) ~[spring-beans-6.1.13.jar:6.1.13]
at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyAccessorForPropertyPath(AbstractNestablePropertyAccessor.java:831) ~[spring-beans-6.1.13.jar:6.1.13]
at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:615) ~[spring-beans-6.1.13.jar:6.1.13]
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:158) ~[spring-webmvc-6.1.13.jar:6.1.13]
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:178) ~[spring-webmvc-6.1.13.jar:6.1.13]
I have a List in a controller that has one ClientMapping Object. I am trying to gather that data in the JSP form and then send back to another controller.
Here is the controller code
@RequestMapping("/chooseMappingValues")
public ModelAndView chooseMappingValues() {
ModelAndView mav = new ModelAndView();
ClientMapping clientMappingChoices = new ClientMapping();
clientMappingChoices.setMappingName("MyMapping");
clientMappingChoices.setSchemaNameCoderepeaper("reference_tables");
List<ClientMapping> cmList = new ArrayList<ClientMapping>();
cmList.add(clientMappingChoices);
Map<String, String> databases = lookupService.getLookup("DatabaseVendor");
Map<String, String> tableNames = lookupService.getLookup("TableName");
mav.addObject("tableNames", tableNames);
mav.addObject("databaseVendor", databases);
mav.addObject("message", "Enter Mapping Name. Choose Target Database Type, Schema Name and Table for Mapping.");
mav.addObject("clientMappingChoices", cmList);
mav.setViewName("mappingtool/chooseMappingValues");
return mav;
}
ANd here is the JSP
<div class="card-body justify-content-md-center"
style="background-color: darkgray;">
<form:form action="${pageContext.request.contextPath}/mappingtool/gatherMappingDetails"
method="POST" modelAttribute="clientMappingChoices">
<c:forEach items="${clientMappingChoices}" var="cm" varStatus="status">
<div class="table-responsive">
<table
class="table table-responsive table-striped table-hover table-sm"
id="viewTable">
<tbody>
<tr>
<td colspan="2" class="fw-bolder justify-content-md-center"><h2
class="text-primary">${message}</h2>
<tr>
<td class="fw-bolder"><label for="mappingName"
class="form-label"> Client Mapping Name:</label> <label
class="text-danger"> Required</label></td>
<td class="fw-bolder"><form:input
class="form-control form-control-sm" id="mappingName"
path="${cm}.mappingName" cssStyle="width:200px;" /> <form:errors
path="${cm}.mappingName" /></td>
<tr>
<td> </td>
<td><input class="btn btn-danger my-2 my-sm-0" id="save"
type="submit" value="Save" /></td>
</tr>
</tbody>
</table>
</div>
</c:forEach>
</form:form>
I have tried to setup the path of the spring form a bunch of ways but can't seem to get the syntax correct.
Here is the error message from the code above:
2025-01-02 16:17:45,985 TRACE o.s.w.s.DispatcherServlet [http-nio-80-exec-5] Failed to complete request
org.apache.jasper.JasperException: An exception occurred processing [/WEB-INF/pages/mappingtool/chooseMappingValues.jsp] at line [151]
148: class="form-label"> Client Mapping Name:</label> <label
149: class="text-danger"> Required</label></td>
150: <td class="fw-bolder">
151: <form:input class="form-control form-control-sm" id="mappingName"
152: path="${cm}.mappingName" cssStyle="width:200px;" /> <form:errors
153: path="${cm}.mappingName" /></td>
154: </tr>
Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'ClientMapping [idPk=null, clientId=null, mappingName=MyMapping, schemaNameClient=null, schemaNameCoderepeaper=reference_tables, tableNameClient=null, tableNameCodereaper=null, columnNameClient=null, columnNameCodereaper=null, dataType=null, created=null, createdBy=null, updated=null, updatedBy=null]' of bean class [java.util.ArrayList]: Bean property 'ClientMapping [idPk=null, clientId=null, mappingName=MyMapping, schemaNameClient=null, schemaNameCoderepeaper=reference_tables, tableNameClient=null, tableNameCodereaper=null, columnNameClient=null, columnNameCodereaper=null, dataType=null, created=null, createdBy=null, updated=null, updatedBy=null]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:627) ~[spring-beans-6.1.13.jar:6.1.13]
at org.springframework.beans.AbstractNestablePropertyAccessor.getNestedPropertyAccessor(AbstractNestablePropertyAccessor.java:856) ~[spring-beans-6.1.13.jar:6.1.13]
at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyAccessorForPropertyPath(AbstractNestablePropertyAccessor.java:831) ~[spring-beans-6.1.13.jar:6.1.13]
at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:615) ~[spring-beans-6.1.13.jar:6.1.13]
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:158) ~[spring-webmvc-6.1.13.jar:6.1.13]
at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:178) ~[spring-webmvc-6.1.13.jar:6.1.13]
I resolved this by doing the following:
created a top level object that has a List of ClientMpping objects.
Pojo below
public class ClientMappingForm {
private List<ClientMapping> dynamicRow =
LazyList.decorate(new ArrayList<ClientMapping>(), FactoryUtils.instantiateFactory(ClientMapping.class));
public ClientMappingForm() {
// TODO Auto-generated constructor stub
}
public List<ClientMapping> getDynamicRow() {
return dynamicRow;
}
public void setDynamicRow(List<ClientMapping> dynamicRow) {
this.dynamicRow = dynamicRow;
}
}
Controller for this as follows
@RequestMapping("/chooseMappingValues")
public ModelAndView chooseMappingValues() {
ModelAndView mav = new ModelAndView();
ClientMappingForm form = new ClientMappingForm();
ClientMapping cm = new ClientMapping();
cm.setMappingName("MyMapping");
cm.setSchemaNameCoderepeaper("reference_tables");
List<ClientMapping> cmList = new ArrayList<ClientMapping>();
cmList.add(cm);
form.setDynamicRow(cmList);
Map<String, String> databases = lookupService.getLookup("DatabaseVendor");
Map<String, String> tableNames = lookupService.getLookup("TableName");
mav.addObject("tableNames", tableNames);
mav.addObject("databaseVendor", databases);
mav.addObject("message", "Enter Mapping Name. Choose Target Database Type, Schema Name and Table for Mapping.");
mav.addObject("clientMappingForm", form);
mav.setViewName("mappingtool/chooseMappingValues");
return mav;
}
And finally the JSP
<div class="card-body justify-content-md-center"
style="background-color: darkgray;">
<form:form action="${pageContext.request.contextPath}/mappingtool/gatherMappingDetails"
method="POST" modelAttribute="clientMappingForm">
<div class="table-responsive">
<table class="table table-responsive table-striped table-hover table-sm" id="viewTable">
<tbody>
<tr>
<td colspan="2" class="fw-bolder justify-content-md-center"><h2
class="text-primary">${message}</h2>
<tr>
<td class="fw-bolder"><label for="mappingName"
class="form-label"> Client Mapping Name:</label> <label
class="text-danger"> Required</label></td>
<td class="fw-bolder"><form:input
class="form-control form-control-sm" id="mappingName"
path="dynamicRow[0].mappingName" cssStyle="width:200px;" /> <form:errors
path="dynamicRow[0].mappingName" /></td>
</tr>
<tr>
<td class="fw-bolder"><label for="user.lastname"
class="form-label">Client Schema Name:</label> <label
class="text-danger"> Required</label></td>
<td class="fw-bolder"><form:input
class="form-control form-control-sm" id="schemaNameClient"
path="dynamicRow[0].schemaNameClient" cssStyle="width:200px;" /> <form:errors
path="dynamicRow[0].schemaNameClient" /></td>
</tr>
<tr>
<td class="fw-bolder">Table Type: <label
class="text-danger"> Required</label></td>
<td class="fw-bolder"><form:select
id="tableNameCodereaper" path="dynamicRow[0].tableNameCodereaper">
<form:option value="" label="--- Select ---" />
<form:options items="${tableNames}" />
</form:select> <form:errors path="dynamicRow[0].tableNameCodereaper" /></td>
</tr>
<tr>
<td class="fw-bolder">Database Type: <label
class="text-danger"> Required</label></td>
<td class="fw-bolder"><form:select id="databaseVendor"
path="dynamicRow[0].databaseVendor">
<form:option value="" label="--- Select ---" />
<form:options items="${databaseVendor}" />
</form:select> <form:errors path="dynamicRow[0].databaseVendor" /></td>
</tr>
<tr>
<td class="fw-bolder">Client Tablename: <label
class="text-danger"> Required</label></td>
<td class="fw-bolder"><form:input
class="form-control form-control-sm" id="tableNameClient"
path="dynamicRow[0].tableNameClient" cssStyle="width:200px;" /> <form:errors
path="dynamicRow[0].tableNameClient" /></td>
</tr>
<tr>
<td> </td>
<td><input class="btn btn-danger my-2 my-sm-0" id="save"
type="submit" value="Save" /></td>
</tr>
</tbody>
</table>
</div>
</form:form>
<div>
<jsp:directive.include
file="/WEB-INF/sitemesh-common/empireidsfooter.jsp" />
</div>
</div>