How can I manage a multidimensional array with Struts Form - java

I'm using Apache Struts 1.3 to render a grid, whitch is a html form embebed in a .jsp. Something like
<html:form action="/MyController.do?action=processForm">
<html:text property="taxation[0][0]" value="" styleClass="gridInputs"></html:text>
<html:text property="taxation[0][1]" value="" styleClass="gridInputs"></html:text>
...
<html:text property="taxation[10][10]" value="" styleClass="gridInputs"></html:text>
MyController is associated to an ActionForm:
public class MyForm extends ActionForm{
protected String taxation[][]= new String [10][10];
public String[] getTaxation() {
return taxation;
}
public void setTaxation(String[][] taxation) {
this.taxation = taxation;
}
The problem arise when I try to retrieve the information submitted by the form. Whithin MyController.class I've a simple dispatcher action
public class MyController extends DispatchAction {
public ActionForward processForm(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
MyForm myform = (MyForm) form;
// Here i can use the getter method to retrieve an array, but
// myform is already wrong populated from struts
}
return mapping.findForward("stage2");
}
I know I can use a Vector (unidimensional array) and It works just fine, but regrettably I need to follow some specs (and the specs force me to use the class MyForm with a 10x10 matrix...). How would be the right way to populated a two dimensional array using struts?
Thank you for the help!

Struts does not support filling of multidimensional array in Form bean. However, it does handle uni-dimensional array of an object. So as a work around if you can create a class (say MatrixRow) which itself contains an Uni-dimensional array and then you can create an Uni-dimensional array of that object in the form bean. Your new class will be look like
public class MatrixRow {
private String matrixCol[] = new String[10];
/**
* #return the matrixCol
*/
public String[] getMatrixCol() {
return matrixCol;
}
/**
* #param matrixCol the matrixCol to set
*/
public void setMatrixCol(String[] matrixCol) {
this.matrixCol = matrixCol;
}
}
Then in your form bean
private MatrixRow[] arrMatrix = new MatrixRow[10];
/**
* #return the arrMatrix
*/
public MatrixRow[] getArrMatrix() {
return arrMatrix;
}
/**
* #param arrMatrix the arrMatrix to set
*/
public void setArrMatrix(MatrixRow[] arrMatrix) {
this.arrMatrix = arrMatrix;
}
and In your JSP, you can use it something like
<html:form action="biArrayTestAction.do">
<table cellpadding="0" cellspacing="0" width="100%">
<logic:iterate id="matrixRows" name="biArrayTestForm"
property="arrMatrix" indexId="sno"
type="logic.MatrixRow" >
<tr>
<td><bean:write name="sno"/></td>
<logic:iterate id="matrixCol" name="matrixRows" property="matrixCol" indexId = "colNo">
<td>
<input type="text" name="arrMatrix[<%=sno %>].matrixCol[<%=colNo %>]">
</td>
</logic:iterate>
</tr>
</logic:iterate>
<tr>
<td align="center" valign="top" colspan="2">
</td>
</tr>
<tr>
<td align="center" valign="top" colspan="2">
<html:submit property="command" value="Test"></html:submit>
</td>
</tr>
</table>
When you submit that form you will get all columns of MatrixRow object filled with the values.
I hope this will help you. I don't find any other way of using multidimensional array in Struts1.

Related

How to call a link with requestparameter inside loop

I want to reference an index in a URL,
for the controller shown below,
such that when the button for first item in the list is clicked,
the corresponding URL to be called is:
/product/detailpage/index/0 ->for the first item
/product/detailpage/index/2 ->for the third item
and so on
How do I modify the code and the <form in code_1 section to satisfy these requirements?
HTML:
<tbody>
<tr th:each="product, iter : ${list}">
<td th:text="*{product.id}"></td>
<td th:text="*{product.name}"></td>
<td style="text-align: right;">
<form action="#{/product/detailpage/index/(idx=${iter.index})}">
<input type="submit" value="Details" />
</form>
</td>
</tr>
</tbody>
Java:
#Controller
#RequestMapping("/product/detailpage")
public class ProductDetailPageController
{
/**
* It is the developer's responsibility to provide code that handles
* the concatenation the correct index to this AttributeName,
* so as to get the the corresponding value from the Model data structure.
* For example, productDetailAtIndex_0,
* productDetailAtIndex_1,
* productDetailAtIndex_n
*/
public static final String sProductDetailPageAttrName = "productDetailAtIndex_";
#Autowired
private ProductService productService;
/**
* Solution-1
*/
#RequestMapping(value = "/index/{idx}", method = RequestMethod.GET)
#ResponseBody
You want to see /product/detailpage/index/0 instead of /product/detailpage/index/?idx=0? You just need to add a placeholder that matches your chosen variable name. Like this:
th:action="#{/product/detailpage/index/{idx}(idx=${iter.index})}"
or for a url
th:url="#{/product/detailpage/index/{idx}(idx=${iter.index})}"

#ModelAttribute is returning null values with thymeleaf

After days of research I have trouble finding a solution for my controller methods. I have two controller methods that seem to be problematic. The savings method is saving null values. I have no clue how to bind the values, that are being typed into the field, to the list /all. One for creating values with input fields and another to save the input values and update a list /all. I want to get the values that I put into the fields of the form and have a updated list /all, with the new values. Note that I am only trying to save two of eleven attributes of the entire class. The class has double values and true/false. Those are being saved into db, except for the important String values. Thanks ahead for the help!
First method:
#GetMapping("/create")
public String showCreateForm(Model model, Branch branch) {
List<Branch> branches = new ArrayList<>();
BranchCreationDto branchesForm = new BranchCreationDto(branches);
for (int i = 1; i <= 1; i++) {
// the input field
branchesForm.addBranch(new Branch());
}
model.addAttribute("form", branchesForm);
return "branches/create";
}
This method is has one input field, where values of Branch can be set.
Second method:
#PostMapping("/saving")
public String saveBranches(#ModelAttribute BranchCreationDto form, Model model, Branch branch) {
// saves null but needs to be saving the values that are being typed into the field
this.branchRepository.saveAll(form.getBranches());
model.addAttribute("branches", branchRepository.findAll());
return "redirect:/all";
}
This method appears to have the problem at
this.branchRepository.saveAll(form.getBranches());
It is returning null values. I have already tried putting branch.getName(), branch.getType() into the parameter. This does not work.
With the method /all the programm is returning the list.
#GetMapping("/all")
public String showAll(Model model) {
model.addAttribute("branches", branchRepository.findAll());
return "branches/all";
}
This is my wrapper class
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
public class BranchCreationDto {
#Autowired
private List<Branch> branches;
public BranchCreationDto(List<Branch> branches) {
this.branches = branches;
}
public BranchCreationDto() {
}
public void addBranch(Branch branch) {
this.branches.add(branch);
}
public List<Branch> getBranches() {
return branches;
}
public void setBranches(List<Branch> branches) {
this.branches = branches;
}
}
And this is the form
<body>
<!-- Save -->
<form action="#" th:action="#{saving}" th:object="${form}"
method="post">
<fieldset>
<input type="submit" id="submitButton" th:value="Save"> <input
type="reset" id="resetButton" name="reset" th:value="Reset" />
<table>
<thead>
<tr>
<th>Branch</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr th:each="branch, itemStat : *{branches}">
<td><input th:field="*{branches[__${itemStat.index}__].branch}" /></td>
<td><input th:field="*{branches[__${itemStat.index}__].type}" /></td>
</tr>
</tbody>
</table>
</fieldset>
</form>
You are doing wrong ,value do not pass from controller to thyme leaf by this way.I ll give you one example.
Example:
Controller:
Model and View model =new Model and View();
model .put ("branches", branch Repository.find All());
return model;
Thyme leaf:
<input id="branches" type="hidden" t h:value="${branches}" />
Now on your value is pass to id branches.
Just add the field as a hidden input and the thymeleaf will send your changes:
<input type="hidden" th:field="*{branches}"/>

Struts 1.3 iterate through dynamic list of questions

Any help would be greatly appreciated:
In my JSP I have a dynamic list of questions with an input field for each question as such:
<logic:iterate name="listOfQuestions" id="listOfQuestionsId" indexId="indexId">
<tr>
<td align="right" width="100%"><bean:message key='<%= "prompt.question" + (indexId.intValue() +1)%>'/>: </td><td width="100%" nowrap="nowrap"><bean:write name="listOfQuestionsId"/></td>
</tr>
<tr align="center">
<td align="right" width="50%"><bean:message key="prompt.answer"/>: </td>
<td align="left" width="50%"><html:password property="questions" size="30" maxlength="40" indexed="true"></html:password></td>
</tr>
</logic:iterate>
The questions and answer fields are being displayed fine.
My only problem, is trying to access the value of the all the input fields in my action class.
Here is my form: MultipleQuestionsForm
public class MultipleQuestionsForm extends ActionForm {
private List<String> questions=null;
/**
* #return the questions
*/
public List<String> getQuestions() {
return questions;
}
/**
* #param questions the questions to set
*/
public void setQuestions(List<String> questions) {
this.questions = questions;
}
//omitted the rest (Validate, constructor, reset method)
}
Here is part of my ActionClass:
getQuestions() returns null
//Use the ValidateInfoForm to get the request parameters
MultipleQuestionsForm validateQuestionsForm = (MultipleQuestionsForm) form;
List<String> listOfquestions = validateQuestionsForm.getQuestions();
for(String s: listOfquestions) System.out.println(s); //nullPointer since getQuestions() doesn't return the input values
How do you expect your questions property should render as List<String> questions from your jsp/view? Have you tried debug your validateQuestionsForm? if so please check your questions property. All you need to do is change your list property into String array. Like this in your MultipleQuestionsForm,
private String[] questions;
And getter setter for this property. Now you can receive as string array and iterate it. Hope this helps.

Spring MVC - Child entity lost after submit

I'm going to try to explain my problem as completely and shortly as I can...
A web application, made on Spring MVC 2.5 + Hibernate + Java 6 (not using annotation!).
I've got a controller extending SimpleFormController and a jsp page that is its formView and successView.
This controller should help me to insert into db an entity PracticeT that has connected (many to one) a lookup entity PracticeConfT (think about it as a "typology"). I need to choose that "typology" through a drop-down menu. In my webapp I need to be able to save data inserted and when I want, to submit the request for approval.
The page has some text fields and that drop-down menu. The bean called as default "command" is NewPracticeBean that has within a reference to an object PracticeT.
THE PROBLEM IS: I fill the form, I select a typology from the drop-down menu, I submit form and save data on DB but when I come back to the view, every property is there but the drop-down menu it is not: it has all the options allowed but no one selected. Some checks revealed that the entity PracticeConfT is null (but it has been recorded on db correctly and debugging it is still there in the model until the very end of the method onSubmit!!!).
I hope someone can help me. Thank you in advance!
Bye,
Dolfiz
Here some useful code:
(I don't think that hibernate config can be the problem, but if you need it, I can post it too)
newPractice.jsp
<form:form id="newPracticeForm" commandName="command">
<input type="hidden" name="action"/>
<spring:nestedPath path="practiceT">
<table class="table-data-form">
<tr>
<td class="left"><spring:message code="" text="Practice type" /></td>
<td>
<form:select path="practiceConfT" multiple="false">
<form:option value="" label="- seleziona -"/>
<form:options items="${practiceTypeList}" itemValue="idPracticeConf" itemLabel="practiceName"/>
</form:select>
</td>
</tr>
<tr>
<td class="left">
<spring:message code="" text="Opzione divisa" />
<br/><form:errors cssClass="errors" path="opzioneDivisa" />
</td>
<td><form:input path="opzioneDivisa" /></td>
</tr>
<tr>
<td colspan="1">
<input type="submit" name="submit" id="submit" value="Save" class="buttonEMS" style="width:100px;" />
</td>
</tr>
</table>
</spring:nestedPath>
</form:form>
NewPracticeBean.java
public class NewPracticeBean implements Serializable{
private PracticeT practiceT;
private String action;
private boolean typeSelected;
public NewPracticeBean(){
super();
this.practiceT = new PracticeT();
}
// getters & setters...
}
PracticeT.java
public class PracticeT implements java.io.Serializable {
private long idPractice;
private PracticeConfT practiceConfT;
private String opzioneDivisa;
// getters & setters...
}
PracticeConfT.java
public class PracticeConfT implements java.io.Serializable {
public static final String PRACTICE_NAME = "practiceName";
private long idPracticeConf;
private String practiceName;
// getters & setters...
}
NewPracticeController.java
public class NewPracticeController extends SimpleFormController{
protected SmartLogger log = SmartLogger.getLogger(this.getClass());
private PracticeSu practiceSu;
private ConfigurationSu configurationSu;
private HibernateEntityDataBinder practiceConfTBinder;
private HibernateEntityDataBinder practiceTBinder;
public NewPracticeController() {
setCommandClass(NewPracticeBean.class);
setCommandName("command");
}
#Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
log.trace("NewPracticeController -- initBinder");
super.initBinder(request, binder);
binder.registerCustomEditor(PracticeT.class, "practiceT", practiceTBinder);
binder.registerCustomEditor(PracticeConfT.class, "practiceT.practiceConfT", practiceConfTBinder);
}
#Override
protected Map referenceData(HttpServletRequest request) throws Exception {
log.trace("NewPracticeController -- referenceData");
Map model = new HashMap();
RetrieveAllEntitiesReq req = new RetrieveAllEntitiesReq();
req.setEntity(PracticeConfT.class);
req.setOrderProperty(PracticeConfT.PRACTICE_NAME);
RetrieveAllEntitiesResp resp = configurationSu.retrieveAllEntities(req);
List entitiesList = resp.getEntitiesList();
model.put("practiceTypeList", entitiesList);
return model;
}
#Override
protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {
NewPracticeBean practiceBean = (NewPracticeBean)command;
Map model = errors.getModel();
CreateNewPracticeReq req = new CreateNewPracticeReq();
req.setPracticeT(practiceBean.getPracticeT());
CreateNewPracticeResp resp = practiceSu.createNewPractice(req);
practiceBean.setPracticeT(resp.getPracticeT());
model.putAll(referenceData(null));
model.put(getCommandName(), practiceBean);
return new ModelAndView(getSuccessView(), model);
}
// setters and getters...
}
After spending some time with OptionsTag, OptionWriter and SelectValueComparator, I would say, then output of "selected" is based on Object.equals.
So if for any reason (Lazyloading...) the Object PracticeT.practiceConfT and the according Objects of model.put("practiceTypeList", entitiesList) are not the SAME (==) then forms:options will not select them as long as the equals method is not correct implemented.
So I guess you need to implement a correct equals method, even if this did not fix this problem, it is always better to have a correct equals method than a wrong or none.
Correct implemented means that it must pay attention to the fact that is used with Hibernate. (for example use if (Hibernate.getClass(this) != Hibernate.getClass(other)) instead of `if (this.getClass() != other.getClass() )

Form binding a HashMap using annotation based controller in Spring 2.5

I have been hitting a brick wall with this problem for some time and no amount of searching and reading has turned up an answer. I have posted on the Spring forums, but to no avail. Maybe someone here can help?
I have a bean containing a HashMap which I have bound to form using the Spring:form taglib and Spring:bind. Binding to the view works perfectly, but upon submitting the form and handling with an annotation based controller the binding does not appear to work correctly. I get no exceptions, but the HashMap is not populated. Here is my setup:
The JSP:
<form:form method="post" action="updateUserPermissions" modelAttribute="wsPermissions" >
<table>
<tr class="head">
<td>Workspace</td>
<td>Read?</td>
<td>Write?</td>
<td>Manage?</td>
</tr>
<c:forEach var="ws" varStatus="wsItem" items="${selectedUserWSs}">
<c:set var="wsURI" value="'${ws.uri}'"/>
<tr>
<td>${ws.kbInfo.name} # ${ws.community.name}</td>
<td>
<spring:bind path="wsPermissions.map[${ws.uri}].read">
<input type="checkbox" <c:if test="${status.value}">checked</c:if> disabled="disabled"/>
</spring:bind>
</td>
<td>
<spring:bind path="wsPermissions.map[${ws.uri}].write">
<input type="checkbox" <c:if test="${status.value}">checked</c:if>/>
</spring:bind>
</td>
<td>
<spring:bind path="wsPermissions.map[${ws.uri}].manage">
<input type="checkbox" <c:if test="${status.value}">checked</c:if>/>
</spring:bind>
</td>
<td>[Remove]</td>
</tr>
</c:forEach>
</table>
<input type="hidden" name="userid" value="${selectedUser.email}" />
<input type="submit" value="Update user permissions" />
</form:form>
This displays fine, binding works, the checkboxes show the correct initial values. Form submission is then handled by this controller method:
#RequestMapping
public String updateUserPermissions(#ModelAttribute(value="wsPermissions") WorkspacePermissionMap wsPermissions,
#RequestParam String userid,
HttpServletRequest request, ModelMap modelMap){
// code to update permissions here.....
LOG.debug(wsPermissions.getMap().size());
//the above prints zero
return "redirect:editUser?id="+userid;
}
Debugging the controller method shows that HashMap is empty.
Here is the code for WorkspacePermissionMap:
public class WorkspacePermissionMap {
private Map<String, WorkspacePermission> map = new HashMap<String, WorkspacePermission>();
/**
* #param map the map to set
*/
public void setMap(Map<String, WorkspacePermission> map) {
this.map = map;
}
/**
* #return the map
*/
public Map<String, WorkspacePermission> getMap() {
return map;
}
}
and for WorkspacePermission:
public class WorkspacePermission {
private boolean read = false;
private boolean write = false;
private boolean manage = false;
/**
* #return the write
*/
public boolean isWrite() {
return write;
}
/**
* #param write the write to set
*/
public void setWrite(boolean write) {
this.write = write;
if (write){
setRead(write);
} else {
setManage(write);
}
}
/**
* #return the moderate
*/
public boolean isManage() {
return manage;
}
/**
* #param moderate the moderate to set
*/
public void setManage(boolean moderate) {
this.manage = moderate;
if (moderate){
setWrite(moderate);
setRead(moderate);
}
}
/**
* #param read the read to set
*/
public void setRead(boolean read) {
this.read = read;
if (!read){
setWrite(read);
setManage(read);
}
}
/**
* #return the read
*/
public boolean isRead() {
return read;
}
}
Can anybody please point out where I'm going wrong? Am I barking up completely the wrong tree, or have I made a stupid error?
Thank you for your help,
Chris
There's definitely some weirdness on the jsp path expressions needed for this.
I'm using hard coded values:
applicationDetails['first_name']
or for your example:
wsPermissions.map['hardcodeduri'].read
These work fine for me.
My advice is to try it first hardcoded and then see if you can alter this to use the dynamic variable.
How is that your HTML checkbox element has no name or value attribute on it? Spring isn't supposed to do 'all' the magic for you ;)

Categories