Struts2 modifying an object with arraylist of objects - java

I have an object in my Action class which contains an arraylist of objects internally, I am trying to create a CRUD screen for this object. My Action Class and bean are given below,
/**
* #author rohit
*
*/
public class IRFeedMgmtAction extends ActionSupport implements ModelDriven<IRFeeds>,SessionAware,ServletRequestAware {
private static org.apache.log4j.Logger log = Logger.getLogger(IRFeedMgmtAction.class);
private HttpServletRequest request;
private Map session;
private IRAccountsDAO acctsDAO;
private IRFeeds feed = new IRFeeds();
/* (non-Javadoc)
* #see com.opensymphony.xwork2.ActionSupport#execute()
*/
public String execute()
{
return "success";
}
/**
* #return
*/
public String add()
{
IRUser user = (IRUser) session.get("user");
List<IRAccountUsers> twtUsers = acctsDAO.getTwitterAcctByOrgId(user.getOrgId());
feed.setTwtAccts(prepareTwitterAccounts(twtUsers));
return "addFeed";
}
/**
* #return
*/
public String save()
{
IRFeeds fd = getFeed();
ArrayList<IRFeedAccts> twtAccts = fd.getTwtAccts();
System.err.println(fd.getFeedUrl());
for (Iterator iterator = twtAccts.iterator(); iterator.hasNext();)
{
IRFeedAccts irFeedAccts = (IRFeedAccts) iterator.next();
System.err.println(irFeedAccts.getNumber());
}
return "saved";
}
/**
* #return
*
*/
private ArrayList<IRFeedAccts> prepareTwitterAccounts(List<IRAccountUsers> twtUsers)
{
ArrayList<IRFeedAccts> twtAccts = new ArrayList<IRFeedAccts>();
IRAccountUsers twtUser = null;
IRFeedAccts feedAccnt = null;
for (Iterator iterator = twtUsers.iterator(); iterator.hasNext();)
{
twtUser = (IRAccountUsers) iterator.next();
feedAccnt = new IRFeedAccts();
feedAccnt.setAccountId(twtUser.getSocialId());
feedAccnt.setPic(twtUser.getPic());
feedAccnt.setName(twtUser.getTwtUsrName());
feedAccnt.setNumber(30);
twtAccts.add(feedAccnt);
}
return twtAccts;
}
MY BEAN
public class IRFeeds implements java.io.Serializable {
private Integer feedId;
private Integer campId;
private String feedUrl;
private boolean active;
private Date createdOn;
private Date updatedOn;
private String createdBy;
private ArrayList<IRFeedAccts> twtAccts;
private ArrayList<IRFeedAccts> fbAccts;
private ArrayList<IRFeedAccts> fbPages;
MY JSP FILE
<s:iterator value="#session.fd.twtAccts" status="twtAcct">
<tr>
<td>
<div style="width: 48px; float: left;"><img src="<s:property value="pic" />" /></div>
<div style="text-align: left;"><s:property value="name" /></div>
</td>
<td>
<s:textfield name="number"/>
</td>
<td>
<input type="text" />
</td>
<td>
<s:textfield name="signature"/>
</td>
</tr>
</s:iterator>
Now my problem is when the value of the beans in the arraylist is modified in the JSP, the same doesn't reach the action class save method. The value remains the same.
Regards,
Rohit

Solve this issue
<s:iterator id="twtFeedAccts" value="twtFeedAccts" status="twtAcct">
<tr>
<td width="250">
<img src="<s:property value="%{twtFeedAccts[#twtAcct.index].pic}" />" width="25px" height="25px" />
<s:property value="%{twtFeedAccts[#twtAcct.index].name}" />
</td>
<td width="200">
<s:textfield id="twtFeedAccts[%{#twtAcct.index}].number" name="twtFeedAccts[%{#twtAcct.index}].number" value="%{twtFeedAccts[#twtAcct.index].number}" />
</td>
<td width="200">
<s:select id="twtFeedAccts[%{#twtAcct.index}].cycle" name="twtFeedAccts[%{#twtAcct.index}].cycle" value="%{twtFeedAccts[#twtAcct.index].cycle}"
label="Select a month" list="#{'2':'2 hrs','4':'4 hrs', '6':'6 hrs', '12':'12 hrs', '24':'24 hrs'}" />
</td>
<td width="250">
<s:textfield id="twtFeedAccts[%{#twtAcct.index}].signature" name="twtFeedAccts[%{#twtAcct.index}].signature" value="%{twtFeedAccts[#twtAcct.index].signature}" size="40"/>
</td>
<td width="50">
<s:checkbox id="twtFeedAccts[%{#twtAcct.index}].selected" name="twtFeedAccts[%{#twtAcct.index}].selected" value="%{twtFeedAccts[#twtAcct.index].selected}" />
</td>
</tr>
</s:iterator>
When you submit the form the beans will go populated.
Regards,
Rohit

Here is a working example(Netbeans 6.9 project) illustrating how to iterate over an array or list of objects.
Also, how to submit the form such that the list of objects gets re-created on submission.
Simply resolve the references and get going.

I have solved the issue:
My JSP:
<s:iterator value="feedbackFor" var="feedbackFor" status="stat">
<tr>
<td><s:label> <s:property value="feedbackFor" /></s:label> </td>
<td><s:label><s:property value="empName"/></s:label></td>
<s:hidden name="feedbackFor[%{#stat.index}].feedbackBy" value="%{feedbackBy}"></s:hidden>
<s:hidden name="feedbackFor[%{#stat.index}].feedbackFor" value="%{feedbackFor}"></s:hidden>
<!--<s:hidden name="feedbackFor.[%{#stat.index}].positiveFeedback" value="%{positiveFeedback}"></s:hidden>-->
<td><s:textfield name="feedbackFor[%{#stat.index}].positiveFeedback" value="%{positiveFeedback}" size="100"/></td>
<td><s:textfield name="feedbackFor[%{#stat.index}].negetiveFeedback" value="%{negetiveFeedback}" size="100"/></td>
</tr>
</s:iterator>
</table>
<s:submit value="Submit Feedback"/>
</s:form>
My Action
public class FeedbackAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private List<FeedbackDTO> feedbackFor;
private String employeeId;
public List<FeedbackDTO> getFeedbackFor() {
return feedbackFor;
}
public void setFeedbackFor(List<FeedbackDTO> feedbackFor) {
this.feedbackFor = feedbackFor;
}
public String getEmployeeId() {
return employeeId;
}
public void setEmployeeId(String employeeId) {
this.employeeId = employeeId;
}
public String getEmployees(){
FeedbackHelper feedbackHelper = new FeedbackHelper();
feedbackFor=feedbackHelper.getEmployeeList(employeeId);
System.out.println("The feed back populated is "+ feedbackFor + "Size is "+ feedbackFor.size());
return SUCCESS;
}
public String submitFeedback(){
System.out.println("The feed back repopulated is "+ feedbackFor + "Size is "+ feedbackFor.size());
return SUCCESS;
}
}

Related

how to populate a response from java spring boot with thymleaf

I am trying to return the data as a response body in java spring boot when a button is click in an html page.I have a list of countries displayed in my page with an edit button assigned to each. I want to find the data that was clicked by id so I have defined the method in my controller class. That's when the edit button is click, it should take the id of the country in the clicked row and display the information based on that id. When I test the api in Postman, it returns the data correctly but when I called the same api in my html page, it's giving me this error.
org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "/findById/{id=${country.id}}" (template: "country" - line 555, col 26)
at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:292) ~[thymeleaf-spring5-3.0.14.RELEASE.jar:3.0.14.RELEASE]
Caused by: org.springframework.expression.spel.SpelParseException: Expression [/findById/{id=${country.id}}] #0: EL1070E: Problem parsing left operand
This is my data class
Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String code;
private String capital;
private String description;
private String nationality;
private String continent;
}
My Controller class
#Controller
public class CountryController {
#Autowired
private CountryService countryService;
#GetMapping("/countries")
public String getCountry(Model model){
List<Country> countryList = countryService.getAllCountry();
model.addAttribute("countries",countryList);
return "country";
}
#PostMapping("/countries/addNew")
public String saveInfo(Country country){
countryService.saveCountryInfo(country);
return "redirect:/countries";
}
#GetMapping("/findById/{id}")
#ResponseBody
public ResponseEntity<Country> getCountryById(#PathVariable("id") Long countryId){ //Bind PathVariable id to id
return ResponseEntity.ok(countryService.getCountryById(countryId)) ;
}
#GetMapping("/country/code/{code}")
public Country getCountryCode(#PathVariable("code") String code){
return countryService.getCountryByCode(code);
}
}
My Service class
#Service
public class CountryService {
#Autowired
private CountryRepository countryRepository;
public List<Country> getAllCountry() {
return countryRepository.findAll();
}
public void saveCountryInfo(Country country){
countryRepository.save(country);
}
public Country getCountryById(Long id){
return countryRepository.findById(id).get();
}
public Country getCountryByCode(String code){
return countryRepository.findByCode(code);
}
}
My Repository class
#Repository
public interface CountryRepository extends JpaRepository<Country,Long> {
public Country findByCode(String code);
}
Here is the html code
<section class="section dashboard">
<div class="row">
<!-- Left side columns -->
<div class="row">
<div class="col-lg-9 col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<!-- Image background -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addModal" data-whatever="#mdo">Add A Country</button>
<h1>List of Country</h1>
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Code</th>
<th>Capital</th>
<th>Description</th>
<th>Nationality</th>
<th>Continent</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr th:each="country:${countries}">
<td th:text="${country.id}"></td>
<td th:text="${country.code}">Code</td>
<td th:text="${country.capital}">Capital</td>
<td th:text="${country.description}">Description</td>
<td th:text="${country.nationality}">Nationality</td>
<td th:text="${country.continent}">Continent</td>
<td>
<div class="btn-group">
<a th:href="${/findById/{id=${country.id}}}" class="btn btn-primary" id="editButton" data-bs-toggle="modal" data-bs-target="#editModal">Edit</a>
</div>
</td>
</tr>
</tbody>
</table>
</div><!-- End of Image background -->
</div><!-- End Left side columns -->
</div>
</div>
</div>
</section>

Bean property 'categoryName' is not readable or has an invalid getter method

Could anyone take a look of this error and help me? I spent 2 hours to find problem but I didn't find solution.
Listing data works, but problem is when adding jsp with action="saveCategory.
org.springframework.beans.NotReadablePropertyException: Invalid property 'categoryName' of bean class [java.util.ArrayList]: Bean property 'categoryName' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
JSP:
<c:forEach var="tempInvoiceCategory" items="${invoiceCategory}">
<tr>
<td>${tempInvoiceCategory.categoryName}</td>
<td>
<button type="button" class="btn btn-info">Edit</button>
<button type="button" class="btn btn-danger">Delete</button>
</td>
</tr>
</c:forEach>
<form:form class="forms-sample" action="saveCategory" modelAttribute="invoiceCategory" method="POST">
<div class="form-group">
<label>Nazwa Kategorii</label>
<form:input path="categoryName" type="text" class="form-control"/>
</div>
<button type="submit" class="btn btn-primary mr-2">Submit</button>
</form:form>
Entity:
#Entity
#Table(name="T_INVOICE_CATEGORY")
public class InvoiceCategory {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="ID_CATEGORY")
private int id;
#Column(name="CATEGORY_NAME")
private String categoryName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
#Override
public String toString() {
return "InvoiceCategory [id=" + id + ", categoryName=" + categoryName + "]";
}
}
Controller:
#Controller
#RequestMapping("/invoice")
public class InvoiceController {
#Autowired
private InvoiceCategoryService invoiceCategoryService;
#GetMapping("/listCategory")
public String listCategory(Model theModel) {
List<InvoiceCategory> invoiceCategory = invoiceCategoryService.getInvoiceCategory();
theModel.addAttribute("invoiceCategory",invoiceCategory);
return "add-invoice-category";
}
#PostMapping("/saveCategory")
public String saveCustomer(#ModelAttribute("invoiceCategory") InvoiceCategory theInvoiceCategory) {
invoiceCategoryService.saveInvoiceCategory(theInvoiceCategory);
return "redirect:/customer/list";
}
}
I think problem is that model attribute invoiceCategory is List<InvoiceCategory> and in same JSP you try build list of items and form which try access to this item, but it is List<InvoiceCategory>:
<form:form class="forms-sample" action="saveCategory" modelAttribute="invoiceCategory" method="POST">
<div class="form-group">
<label>Nazwa Kategorii</label>
<form:input path="categoryName" type="text" class="form-control"/>
</div>
<button type="submit" class="btn btn-primary mr-2">Submit</button>
</form:form>
Try comment this part and run application again.

Spring 3 RadioButtonsTag Attribute 'items' must be an array, a Collection or a Map Exception

I am populate a List of String as radio button in the JSP. I add the List to the ModelMap but still the below Exception occurred. What am i missing please?
Attribute 'items' must be an array, a Collection or a Map:
java.lang.IllegalArgumentException: Attribute 'items' must be an
array, a Collection or a Map
#Controller
public class EmployeeController {
#Autowired
private EmployeeManager employeeManager;
#RequestMapping(value = {"/"}, method = RequestMethod.GET)
public String homePage(ModelMap map) {
map.addAttribute("employee", new Employee());
populateDepartments(map);
return "addEmployee";
}
private void populateDepartments(ModelMap map){
List<String> departments = new ArrayList<String>();
departments.add("Dept 1");
departments.add("Dept 2");
map.addAttribute("departments",departments);
}
}
addEmployee.jsp:
<form:form method="post" action="add" commandName="employee">
<table>
<tr>
<td><form:label path="name">Name</td>
<td><form:input path="name" /></td>
<td>Address</td>
<td><form:input path="address" /></td>
<td>Departments</td>
<td><form:radiobuttons path="empDepartment" items="${departments}"/></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Add"/>
</td>
</tr>
</table>
</form:form>
The entity
#Entity
public class Employee {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String name;
private String address;
#Transient
private String empDepartment;
}

Implementing one to one relation ship spring hibernate

I have a table cards which is related to some other master tables (divisions and units) with one to one relation.
On UI I am showing drop downs to select the division and unit values for card, this is the function to create form in CardController.java
#RequestMapping(value = "/addCardForm", method = RequestMethod.GET)
public String addCardForm(ModelMap map)
{
map.addAttribute("divisions", divisionService.getAllDivisions());
map.addAttribute("units", unitService.getAllUnits());
return "admin/addCard";
}
addCard.jsp :
<form:form method="post" action="addCard">
<table cellspacing="10" id="card-table">
<tr>
<td><label for="division" class="control-label">Division : </label></td>
<td><select name="division" class="selectpicker">
<option>Select</option>
<c:forEach items="${divisions}" var="division">
<option value="${division.id}">${division.name}</option>
</c:forEach>
</select></td>
</tr>
<tr>
<td><label for="unit" class="control-label">Unit : </label></td>
<td><select name="unit" class="selectpicker">
<option>Select</option>
<c:forEach items="${units}" var="unit">
<option value="${unit.id}">${unit.name}</option>
</c:forEach>
</select></td>
</tr>
<tr>
<td><button type="submit" class="btn btn-primary">Submit</button></td>
<td></td>
</tr>
</table>
</form>
Drop downs are populated with the data but on submitting form its not setting division or unit to the cardEntity object they are set to null, this is the addCard function in controller :
#RequestMapping(value = "/addCard", method = RequestMethod.POST)
public String addCard(#ModelAttribute(value="card") CardEntity card, BindingResult result)
{
cardService.addCard(card);
//card.getDivision(); -- this is null
return "redirect:/card";
}
There are other fields which are added in the card except drop downs.
CardEntity.java
#Entity
#Table(name="cards")
#Proxy(lazy=false)
public class CardEntity {
#Id
#Column(name="id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#OneToOne
#JoinColumn(name="division_id", referencedColumnName="id")
private DivisionEntity division;
#OneToOne
#JoinColumn(name="unit_of_qty_id", referencedColumnName="id")
private UnitEntity units;
public DivisionEntity getDivision() {
return division;
}
public void setDivision(DivisionEntity division) {
this.division = division;
}
public UnitEntity getUnits() {
return units;
}
public void setUnits(UnitEntity units) {
this.units = units;
}
}
Edit :
I have to set divisionEntity and unitEntity manually :
#RequestMapping(value = "/addCard", method = RequestMethod.POST)
public String addCard(HttpServletRequest request, #ModelAttribute(value="card") CardEntity card, BindingResult result)
{
card.setDivision(divisionService.findOne(Integer.parseInt(request.getParameter("division"))));
card.setUnit(unitService.findOne(Integer.parseInt(request.getParameter("unit"))));
cardService.addCard(card);
return "redirect:/card";
}
So I guess the problem is divisionEntity and unitEntity objects are not set in card after submitting the form.
You can do this too:
<tr>
<td><label for="division.id" class="control-label">Division : </label></td>
<td><select name="division.id" class="selectpicker">
<option>Select</option>
<c:forEach items="${divisions}" var="division">
<option value="${division.id}">${division.name}</option>
</c:forEach>
</select></td>
</tr>
<tr>
<td><label for="unit.id" class="control-label">Unit : </label></td>
<td><select name="unit.id" class="selectpicker">
<option>Select</option>
<c:forEach items="${units}" var="unit">
<option value="${unit.id}">${unit.name}</option>
</c:forEach>
</select></td>
</tr>
The rest is same as your original. But:
Make sure you have a default constrcutor in Division class;
The CardEntity should have getUnit() and setUnit(), not getUnits() and setUnits().
Hope it help.

Spring MVC - populate enum to dropdownlist

I have a form like this :
<form:form method="POST" action="searchProjects" commandName="projectcriteria">
<table>
<tr>
<td class="label"><spring:message code="number" /></td>
<td><form:input path="number" /></td>
<td class="label"><spring:message code="customer" /></td>
<td><form:input path="customer" /></td>
</tr>
<tr>
<td class="label"><spring:message code="name" /></td>
<td><form:input path="name" /></td>
<td class="label"><spring:message code="status" /></td>
<td>
<form:select path="status">
<option value=""><spring:message code="please_select" /></option>
<c:forEach var="enum" items="${allStatus}">
<option value="${enum}"><spring:message code="${enum.statusEnum}" /></option>
</c:forEach>
</form:select>
</td>
</tr>
<tr>
<td colspan="4" style="text-align: center;">
<input type="submit" value="<spring:message code="search"/>" />
<input type="button" value="<spring:message code="reset_criteria"/>" />
</td>
</tr>
</table>
</form:form>
The Projectcriteria and the StatusEnum are like this:
public enum StatusEnum {
INV("Invalidate"),
TOV("Validate"),
VAL("Validated"),
FIN("Finished");
private String name;
private StatusEnum(String name) {
this.name = name;
}
public String getStatusEnum() {
return this.name;
}
}
public class ProjectCriteria {
private long number;
private String name;
private String customer;
private StatusEnum status;
/**
* #return the number
*/
public long getNumber() {
return number;
}
/**
* #param number the number to set
*/
public void setNumber(long number) {
this.number = number;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* #return the customer
*/
public String getCustomer() {
return customer;
}
/**
* #param customer the customer to set
*/
public void setCustomer(String customer) {
this.customer = customer;
}
/**
* #return the status
*/
public StatusEnum getStatus() {
return status;
}
/**
* #param status the status to set
*/
public void setStatus(StatusEnum status) {
this.status = status;
}
}
How do I populate the StatusEnum attribute in the ProjectCriteria class to the jsp page. What do i have to put into the Controller?
Thanks a lot for any help.
Add your enum values in Controller method which giving request to respective page i.e.
model.addAttribute("enumValues",StatusEnum.value());
Then iterate enumValues in dropdown menu using foreach.
You could try this (sorry code not tested):
<c:forEach var="enum" items="${StatusEnum.values()}">
<option value="${enum}"><spring:message code="${enum.name}" /></option>
</c:forEach>
Note: if your enum class has a package name, you might have to include the fully qualified class name in the items attribute. You might be able to pass the enum as a model attribute from your controller as well (?).

Categories

Resources