Getting IllegalStateException when creating dynamic Fields using Thymeleaf - java

In my program, I am generating dynamic form names based on the number of feedbacks I get. I am then taking the satisfaction, comment and feedbackId inputs. They are different for each iteration. This is giving me an IllegalStateException error.
My HTML form is:
<form action="#" th:action="#{/heart2heart/token/__${tokenId}__/}" method="post">
<div class="table-responsive">
<table class="table table-striped table-bordered table-hover table-condensed">
<tr>
<th style="display:none;"></th>
<th th:text="#{service.desc}">Service</th>
<th th:text="#{feedback.description}">Feedback</th>
<th th:text="#{visit.date}">Date of Visit</th>
<th th:text="#{repr.name}">FU Repr</th>
<th th:text="#{resolution.response}">Response</th>
<th th:text="#{resolution.satisfactionLevel}">Satisfaction</th>
<th th:text="#{resolution.comment}">Comment</th>
</tr>
<tr th:each="feedback, feedbackStat : *{feedbacks}">
<td style="display:none;"><input type="hidden" th:field="*{feedbacks[__${feedbackStat.index}__].feedbackId}" th:value="${feedback.id}" /></td>
<td th:text="${feedback.service.description}">Steel</td>
<td th:text="${feedback.description}">Problem</td>
<td th:text="${feedback.visits[0].date}">12/08/2015</td>
<td th:text="${feedback.visits[0].repr.fullName}">XYZ</td>
<td th:text="${feedback.receipt.resolutions[0].response}">response</td>
<td>
<div class="radio">
<label><input type="radio" th:field="*{feedbacks[__${feedbackStat.index}__].satisfaction}" th:text="#{global.yes}" value="SATISFIED">Yes</input></label>
</div>
<div class="radio">
<label><input type="radio" th:field="*{feedbacks[__${feedbackStat.index}__].satisfaction}" th:text="#{global.no}" value="NOT SATISFIED">No</input></label>
</div>
</td>
<td><textarea th:field="*{feedbacks[__${feedbackStat.index}__].comment}" class="form-control" rows="2"></textarea></td>
</tr>
</table>
<div class="form-group">
<button type="submit" name="addRow" th:text="#{button.submit}"
class="btn btn-primary btn-md">Submit</button>
</div>
</div>
</form>
My controller is:
#RequestMapping(value = "/{tokenId}/", method = RequestMethod.POST)
public String addSatisfaction(#PathVariable int tokenId, #Valid ReceiptForm receiptForm, BindingResult result, Model model) {
try {
for (SatisfactionForm satisfactionForm : receiptForm.getFeedbacks()) {
Feedback feedback = new Feedback();
feedback.setId(satisfactionForm.getFeedbackId());
Feedback feedback1 = heart2heartService.getFeedbackById(feedback);
Resolution resolution = new Resolution();
resolution.setId(feedback1.getReceipt().getResolutions().get(0).getId());
resolution.setSatisfactionLevel(satisfactionForm.getSatisfaction().name());
resolution.setComment(satisfactionForm.getComment());
heart2heartService.addSatisfaction(resolution);
model.addAttribute("success", "Satisfaction added for tokenId " + tokenId);
}
} catch (Exception e) {
logger.error("Exception :: ", e);
}
return "success2";
}
#RequestMapping(value = "/{tokenId}/", method = RequestMethod.GET)
public String getSatisfaction(#PathVariable int tokenId, Model model) {
Token token = new Token();
token.setId(tokenId);
try {
model.addAttribute("feedbacks", heart2heartService.getFeedbacksByToken(token));
} catch (Exception e) {
logger.error("Exception :: ", e);
}
return "heart2heart/closeFeedback";
}
My forms are:
public class ReceiptForm {
private List<SatisfactionForm> feedbacks = new ArrayList<SatisfactionForm>();
public List<SatisfactionForm> getFeedbacks() {
return feedbacks;
}
public void setFeedbacks(List<SatisfactionForm> feedbacks) {
this.feedbacks = feedbacks;
}
}
and
public class SatisfactionForm {
public static enum Satisfaction {
NOT_SATISFIED, SATISFIED
}
private String comment;
private int feedbackId;
private Satisfaction satisfaction;
public String getComment() {
return comment;
}
public int getFeedbackId() {
return feedbackId;
}
public Satisfaction getSatisfaction() {
return satisfaction;
}
public void setComment(String comment) {
this.comment = comment;
}
public void setFeedbackId(int feedbackId) {
this.feedbackId = feedbackId;
}
public void setSatisfaction(Satisfaction satisfaction) {
this.satisfaction = satisfaction;
}
}
I am getting the following error:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'feedbacks[0]' available as request attribute
How do I fix this?

You did not specify the form-backing bean in your Thymeleaf template.
You are using the *{} operator to access fields of the bean, but Thymeleaf does not know
which bean you want to use. To resolve the error, add a th:object to your form.
Assuming that heart2heartService.getFeedbacksByToken(token) returns a ReceiptForm your form would look like this:
<form action="#" th:action="#{/heart2heart/token/__${tokenId}__/}" method="post" th:object="${feedbacks}">

Related

Spring Web App - Refreshing data routinely

I'm currently developing an online banking application where you can buy stocks. It is being built with spring boot and the front-end is html/css.
I am using the YahooFinance API to get stock quotes but I need to refresh my page to get the live stock quotes, how can I automatically update the page every 30 seconds to get the new prices for each stock?
Also, is there a way I could implement this using Threads?
Banking Controller
#GetMapping("/banking/stocks")
public String stocks(Model model) {
model.addAttribute("stock", new StockDto());
try {
List<Stock> stocks = stockService.getDefaultStocks();
model.addAttribute("stocks", stocks);
} catch (IOException e) {
e.printStackTrace();
}
return "stocks.html";
}
StockServiceImpl:
#Service
public class StockServiceImpl implements StockService {
private String[] startingStocks = { "AAPL", "BABA", "MSFT", "AXP", "BA", "AMD", "TSLA", "MA", "SHOP", "GOOGL",
"KL" };
#Override
public Stock getStock(String stockName) throws IOException {
Stock stock = YahooFinance.get(stockName);
return stock;
}
#Override
public Map<String, Stock> getStock(String[] s) throws IOException {
Map<String, Stock> stocks = YahooFinance.get(s);
return stocks;
}
#Override
public List<Stock> getDefaultStocks() throws IOException {
Map<String, Stock> stocks = YahooFinance.get(startingStocks);
List<Stock> stockList = new ArrayList<Stock>();
for(String s : startingStocks) {
stockList.add(stocks.get(s));
}
return stockList;
}
}
HTML Page For Displaying Stocks:
<main class='main-content bgc-grey-100'>
<div id='mainContent'>
<div class="container-fluid">
<br>
<h4 class="c-grey-900 mT-10 mB-30">Stock Table</h4>
<form action="#" th:object="${stock}" th:action="#{/banking/stock-search}"
method="POST" class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="search"
th:field="*{name}" placeholder="Search Stock"
aria-label="Search">
<button class="btn btn-outline-primary my-2 my-sm-0" type="submit">Search</button>
</form>
<br>
<div class="row">
<div class="col-md-12">
<div class="bgc-white bd bdrs-3 p-20 mB-20">
<table id="dataTable" class="table table-striped table-bordered"
cellspacing="0" width="100%">
<thead>
<tr>
<th>Ticker</th>
<th>Trade</th>
<th>Name</th>
<th>Price</th>
<th>(%) Change</th>
<th>Div Yield (%)</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Ticker</th>
<th>Trade</th>
<th>Name</th>
<th>Price</th>
<th>(%) Change</th>
<th>Div Yield (%)</th>
</tr>
</tfoot>
<tbody>
<tr th:each="stock : ${stocks}">
<td th:text="${stock.getSymbol()}"></td>
<td>
<form action="#" th:action="#{/banking/stocks/} + ${stock.symbol}" method="get">
<button class="btn btn-outline-success my-2 my-sm-0" th:id="'table_entry_childs_button_' + ${stock.symbol}" type="submit">
<i>Trade</i>
</button>
</form>
</td>
<td th:text="${stock.getName()}"></td>
<td th:text="${stock.getQuote().getPrice()}"></td>
<td th:class="${stock.getQuote().getChangeInPercent() > 0 ? 'text-success' : 'text-danger'}" th:text="${stock.getQuote().getChangeInPercent() + '%'} "></td>
<td th:if="${stock.getDividend().getAnnualYield() != null}" th:text="${stock.getDividend().getAnnualYield() + '%'}">0.00%</td>
<td th:if="${stock.getDividend().getAnnualYield() == null}" >0.00%</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</main>
You can exploit STOMP protocol and web sockets using spring boot.
For reference:
https://www.baeldung.com/spring-websockets-send-message-to-user
on back end side you can use
#Autowired
SimpMessagingTemplate messagetemplate;
public void somemethod(String strParam){
while (true){
// build string or json whatever you need to send
messagetemplate.convertAndSend("/blabla/blabla",strParam);
Thread.sleep(30*1000);
}
}
on front end side you have to use stomp.js
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.js">
<script type="text/javascript">
function load(){
var stompClient = Stomp.client("ws://localhost:8080/ws");
stompClient.connect({}, function (frame) {
stompClient.subscribe('/blabla/blabla', function (message) {
// do something here
});
});
}
lastly, part of html where you want to call on load
<html>
<body onload="load()">
</body>
</html>
You can create an #Scheduled method that can call this API request every 30 seconds to get data and update your Front-End.
#Scheduled(fixedRate = 30000)
public void updateStocksElement() {
//Call your /banking/stocks rest endpoint
}
https://spring.io/guides/gs/scheduling-tasks/

getting Ids from selected checkboxes in a table using Spring + Thymeleaf

I'm getting an error NotReadablePropertyException: Invalid property 'userIds' of bean class [...ListOfIds]... And I'm not sure why. If I remove the th:field attribute on the checkbox, the table fills in properly. I've tried with th:field="*{requestIds}" and th:field="*{requestIds.ids}"
What I'm trying to do is collect the list of ids from the selected checkboxes and pass them back to the controller for the post.
Form
public class ListOfIds {
List<Long> ids = new ArrayList<>();
public List<Long> getIds() { return ids; }
// I've tried both set methods by themselves and together.
public void setIds(List<Long> ids) { this.ids = ids; }
public void setIds(Long[] ids) { this.ids = Arrays.asList(ids); }
}
Request bean
public class Request {
long id;
String name;
String phone;
String email;
// Getters/Setters
}
Controller
#GetMapping("/myTable")
public ModelAndView getMyTable(ModelAndView mav) {
mav.setViewName("myTable");
List<Request> requests = service.getRequests();
mav.addObject("requests", requests);
mav.addObject("requestIds", new ListOfIds());
return mav;
}
#PostMapping("/myTable")
public ModelAndView postRequests(ModelAndView mav, #ModelAttribute("requestIds") ListOfIds ids) {
...
}
html page
...
<form method="post" th:action="#{/myTable}" th:object="${requestIds}">
<table class="table ...">
<thead>
<tr>
<th><input type="checkbox" class="selectall" data-target="requests-all"/></th>
<th>Name</th>
<th>Phone</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr role="row" th:each="request : ${requests}">
<td>
<input type="checkbox" name="requestId" data-target="requests-all"
th:value="${request.id}" th:field="*{requestIds}"/>
</td>
<td th:text="${request.name}"></td>
<td th:text="${request.phone}"></td>
<td th:text="${request.email}"></td>
</tr>
</tbody>
</table>
<button class="btn btn-primary show-selected">Process</button>
</form>
...
<script>
$(document).ready(function() {
$('button').click(function(e) {
if !(confirm("Are you sure you wish to process these requests")) {
e.preventDefault();
}
});
});
</script>
...
So the answer is that name and th:field don't play nice together.
I made the following changes and it worked:
Controller
#PostMapping("/myTable")
public ModelAndView postRequests(ModelAndView mav,
#ModelAttribute("requestIds") Long[] ids) {
...
}
html
<form id="postMyTable" method="post" th:action="#{/myTable}">
<table ...
<input type="checkbox" name="requestId" data-target="requests-all"
th:value="${request.id}"/>
...
<script>
$(document).ready(function() {
$('button').click(function(e) {
if !(confirm("Are you sure you wish to process these requests")) {
e.preventDefault();
} else {
$("#postMyTable").submit();
}
});
});
</script>

Bean value not being filled in on JSP page

I am new to Java... I made this application, but the problem is that when I run the project I am getting the text which i have written in h tag's value attribute instead of the value from the bean. I have searched a lot but the problem is still there. The code and the screenshot tells the rest of the story. Here is my login.jsp:
</head>
<body>
<f:view>
<div class="login_container">
<h:messages errorClass="errorMsg"/>
<div class="login_box">
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<div class="login_wrap">
<div class="login_logo">
<img src="images/login_logo.gif" width="116" height="141" />
</div>
<h:form id="login_form">
<div class="login_form">
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<div style="float: left;">
<h2 class="orange">
Please Login
</h2>
</div>
<div class="login_icon">
<img src="images/icn_lock.png" width="16" height="16" />
</div>
</td>
</tr>
<tr>
<td>
<label>
Username
</label>
</td>
</tr>
<tr>
<td><h:inputText id="username" value="#{loginBean.username}" /></td>
</tr>
<tr>
<td>
<label>
Password
</label>
</td>
</tr>
<tr>
<td><h:inputText id="password" value="#{loginBean.password}"/>
</td>
</tr>
<tr>
<td>
</td>
</tr>
<tr>
<td align="left" valign="middle">
<h:commandButton image="images/btn_login.gif" id="loginButton" action="#{loginBean.login}"
style="width:81px; height:29px" />
</td>
</tr>
</table>
</div>
</h:form>
</div>
</td>
</tr>
<tr>
<td>
<div class="login_box_bt">
</div>
</td>
</tr>
</table>
</div>
<div class="login_footer_box">
<div class="login_footer">
<div class="login_footer_text">
<p>
<span class="text_orange">Phone:</span> (+92-51) 5120684
<br />
<span class="text_orange">E-mail:</span> support#noeticworld.com
<br />
<span class="text_orange">Web:</span> http://www.noeticworld.com.pk
</p></div>
<div class="login_footer1_text">
<p>
<span class="text_orange">Leading VAS Solution Provider
</span>
<% /**<span class="text_orange">Fax:</span> (+92-51) 260 9263*/ %>
<br />
</p></div>
</div>
</div>
<div class="login_box_bt">
</div>
</f:view>
</body>
</html>
here is my backingbeans :
public class LoginBackingBean
{
private String username;
private String password;
private Boolean rememberMe;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public Boolean getRememberMe()
{
return rememberMe;
}
public void setRememberMe(Boolean rememberMe)
{
this.rememberMe = rememberMe;
}
public String login()
{
boolean isValidUser = true;
String message = "";
Employee employee = null;
try
{
employee = getCurrentEmployee();
if (employee == null)
{
isValidUser = false;
message = "Sorry, the username or password is incorrect. Please try again";
}
}
catch (SQLException e)
{
isValidUser = false;
message = e.getMessage();
e.printStackTrace();
}
if (!isValidUser)
{
FacesMessage facesMessage = new FacesMessage();
facesMessage.setSeverity(FacesMessage.SEVERITY_ERROR);
facesMessage.setSummary(message);
FacesContext.getCurrentInstance().addMessage("login_form", facesMessage);
return "failure";
}
EmployeeBackingBean employeeBackingBean = EmployeeBackingBean.getEmployeeBackingBean(employee);
List<Integer> recursiveSubordinatesIds;
try
{
recursiveSubordinatesIds = new EmployeeDAOImpl(DigiDeskDAO.getSqlMapper()).selectIdsOfRecursiveSubordinates(employeeBackingBean.getEmployeeId());
employeeBackingBean.setRecursiveSubordinatesIds(recursiveSubordinatesIds);
}
catch (SQLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
SessionManager.setEmployeeInSession(employeeBackingBean);
return "success";
}
/**
* This function finds the employee with the provided username and password
*
* #return - Employee object if validation succeeds, null if no matching user is found
* #throws SQLException
*/
private Employee getCurrentEmployee() throws SQLException
{
EmployeeDAOImpl employeeDAOImpl = new EmployeeDAOImpl(DigiDeskDAO.getSqlMapper());
EmployeeExample employeeExample = new EmployeeExample();
EmployeeExample.Criteria criteria = employeeExample.createCriteria();
criteria.andUsernameEqualTo(username);
criteria.andPasswordEqualTo(password);
List<Employee> employeesList = employeeDAOImpl.selectByExampleWithBLOBs(employeeExample);
if (employeesList.isEmpty())
{
return null;
}
Employee employee = employeesList.get(0);
return employee;
}
}
This is the problem, username and password shows the text:
Try to replace #{~~} with ${~~}

How to pass nested list element to the controller in spring mvc

In my jsp page there have a table with nested list value, i want to send that table value to the container, The outer table value were sent but the inner table value not sent to the container, I am new here please let me know how to over come this situation,
My jsp
<script>
function rowAdded(rowElement) {
//clear the imput fields for the row
$(rowElement).find("input").val('');
//may want to reset <select> options etc
//in fact you may want to submit the form
saveNeeded();
}
function rowRemoved(rowElement) {
saveNeeded();
}
function saveNeeded() {
$('#submit').css('color','red');
$('#submit').css('font-weight','bold');
if( $('#submit').val().indexOf('!') != 0 ) {
$('#submit').val( '!' + $('#submit').val() );
}
}
function beforeSubmit() {
alert('script Working');
return true;
}
$(document).ready( function() {
var config = {
rowClass : 'rule',
addRowId : 'addRule',
removeRowClass : 'removeRule',
formId : 'ruleListForm',
rowContainerId : 'ruleListContainer',
indexedPropertyName : 'ruleList',
indexedPropertyMemberNames : 'id,ruleName,parameterName,overwriteValue',
rowAddedListener : rowAdded,
rowRemovedListener : rowRemoved,
beforeSubmit : beforeSubmit
};
new DynamicListHelper(config);
});
</script>
<html>
<form:form action="/update" method="post" id="ruleListForm" modelAttribute="ruleListContainer">
<table border="1">
<thead>
<h3 align="center">Selected Rule</h3>
<tr>
<th data-field="id" width="25">ID </th>
<th data-field="details" width="20">RuleName </th>
<th data-field="parameter" width="240">Parameter </th>
</tr>
</thead>
<tbody id="ruleListContainer">
<c:forEach items="${List2}" var="as">
<tr class="rule">
<td><input type="hidden" name="ruleList[].id" value="${as.rule.id}" /> ${as.rule.id}</td>
<td><input type="hidden" name="ruleList[].ruleName" value="${as.rule.ruleName}" /> ${as.rule.ruleName}</td>
<td> <input id="one" class="datepicker" type="text" name="ruleList[].startDate" size="11" height="0.10"></td>
<td> <input id="two" class="datepicker" type="text" name="ruleList[].endDate" size="11" height="0.10"></td>
<td>
<table border="1">
<c:forEach items="${as.ruleAssignmentParameter}" var="asss">
<tr>
<td><input type="hidden" name="ruleList[].parameterName"value="${asss.parameterName}" > ${asss.parameterName}</td>
<td><input type="hidden" name="ruleList[].overwriteValue" value="${asss.overwriteValue}" /> ${asss.overwriteValue}</td>
</tr>
</c:forEach>
</table>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<br>
<input type="submit" value="Update">
</form:form>
</html>
Here is my model class
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import com.demo.app.model.RuleAssignmentParameter;
public class RuleAssUI {
private int id;
private String ruleName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRuleName() {
return ruleName;
}
public void setRuleName(String ruleName) {
this.ruleName = ruleName;
}
private List<RuleAssignmentParameter> ruleAssignmentParameter = new LinkedList<RuleAssignmentParameter>();
public List<RuleAssignmentParameter> getRuleAssignmentParameter() {
return ruleAssignmentParameter;
}
public void setRuleAssignmentParameter(List<RuleAssignmentParameter> ruleAssignmentParameter) {
this.ruleAssignmentParameter = ruleAssignmentParameter;
}
public RuleAssUI(){
}
public RuleAssUI(int id,String ruleName){
this.id=id;
this.ruleName=ruleName;
}
}
My container where i store the list value
import java.util.LinkedList;
import java.util.List;
public class RuleListContainer {
private List<RuleAssUI> ruleList = new LinkedList<RuleAssUI>();
public RuleListContainer() {
}
public RuleListContainer(List<RuleAssUI> ruleList) {
this.ruleList = ruleList;
}
public List<RuleAssUI> getRuleList() {
return ruleList;
}
public void setRuleList(List<RuleAssUI> ruleList) {
this.ruleList = ruleList;
}
Controller
#RequestMapping(value = "/update", method = RequestMethod.POST)
public String update(#ModelAttribute("SpringWeb") RuleListContainer ruleListContainer, HttpSession session, ModelMap model) {
ruleListContainer.getRuleList().size();
for (RuleAssUI rul1 : ruleListContainer.getRuleList()) {
System.out.println("Id: " + rul1.getId());
System.out.println("RuleName: " + rul1.getRuleName());
for (RuleAssignmentParameter rul2 : rul1.getRuleAssignmentParameter()) {
System.out.println("ParameterName: " + rul2.getParameterName());
System.out.println("ParameterValue: " + rul2.getOverwriteValue());
}
}
session.setAttribute("ruleListContainer", ruleListContainer);
return "hello";
}
I am trying so many time but unable to fixed the issue, And browse also but did't get any proper help, so please help to do items
I NEED HELP PLEASE SOME BODY HELP ME...!
Thank you in advance
I think the problem is in your jsp file.
You need to set the index of each list element.
<c:forEach items="${List2}" var="as" varStatus="vs">
<tr class="rule">
<td><input type="hidden" name="ruleList[${vs.index}].id" value="${as.rule.id}" /> ${as.rule.id}</td>
<td><input type="hidden" name="ruleList[${vs.index}].ruleName" value="${as.rule.ruleName}" /> ${as.rule.ruleName}</td>
<td> <input id="one" class="datepicker" type="text" name="ruleList[${vs.index}].startDate" size="11" height="0.10"></td>
<td> <input id="two" class="datepicker" type="text" name="ruleList[${vs.index}].endDate" size="11" height="0.10"></td>
<td>
<table border="1">
<c:forEach items="${as.ruleAssignmentParameter}" var="asss" varStatus="assignments">
<tr>
<td><input type="hidden" name="ruleList[${vs.index}].ruleAssignmentParameter[${assignments.index}].parameterName" value="${asss.parameterName}" > ${asss.parameterName}</td>
<td><input type="hidden" name="ruleList[${vs.index}].ruleAssignmentParameter[${assignments.index}].overwriteValue" value="${asss.overwriteValue}" /> ${asss.overwriteValue}</td>
</tr>
</c:forEach>
</table>
</td>
</tr>
</c:forEach>
Also in your controller (POST method) you are trying to get the object identified by "SpringWeb" but should be "ruleListContainer", same name you have in your form tag
The problem was you had a list into RuleAssUI and you was not accesing correctly, you need 2 loops and indexes, one for each list.
Here is the key:
ruleList[${vs.index}].ruleAssignmentParameter[${assignments.index}].parameterName

JSP or Spring MVC controller display same info several times

I have controller which adds Computer assigned to User by admin. User can have several assigned Computers and it is implemented through Spring MVC Multiple Selection. But I’ve little issue with displaying of info after updating. It shows as many users in List of users as many computers were assigned. I think problem not in JSP and debuggers shows nothing so I’ll very appreciate your help.
Here is my AdminUserUpdateController.java
#Controller
public class AdminUserUpdateController {
#InitBinder("userForm")
private void initBinder(WebDataBinder binder) {
binder.setValidator(updateValidator);
binder.registerCustomEditor(Set.class, "computers", new CustomCollectionEditor(Set.class) {
#Override
protected Object convertElement(Object element) {
String pcName = null;
if (element instanceof String && !((String) element).equals("")) {
try {
pcName = (String) element;
Set<Computer> computerSet = new LinkedHashSet<>();
computerSet.add(computerService.getComputerByName(pcName));
new UserForm().setComputers(computerSet);
} catch (NumberFormatException e) {
logger.info("Error in element");
logger.info("Element was " + ((String) element));
}
}
return pcName != null ? computerService.getComputerByName(pcName) : null;
}
});
}
...............
#RequestMapping(value = "/adminEdit/{userId}", method = RequestMethod.GET)
public String updateView(#PathVariable("userId") Integer userId,
UserForm userForm,
ModelMap model) {
userForm.setUser(userService.getUserById(userId));
model.addAttribute("userForm", userForm);
model.addAttribute("computers", computerService.getAllComputers());
return "adminUserUpdate";
}
#RequestMapping(value = "adminEdit.do/{userId}", method = RequestMethod.POST)
public ModelAndView updateUserProcess(#ModelAttribute(value = "userForm")
UserForm userForm,
#PathVariable("userId") Integer userId,
BindingResult result, Model model) {
User user = userService.getUserById(userId);
model.addAttribute("computers", computerService.getAllComputers());
model.addAttribute("userForm", userForm);
updateValidator.validate(userForm, result);
return updatingUser(user, model, userForm);
}
private ModelAndView updatingUser(User user, Model model,
UserForm userForm) {
if (isEmailExists(userForm, user)) {
model.addAttribute("errorMsg", "Email is already in use!");
return new ModelAndView("adminUserUpdate");
}
fillForm(userForm, user);
user = userForm.getUser();
userService.updateUser(user);
return new ModelAndView("redirect:/adminPage", "user", user);
}
private void fillForm(UserForm userForm, User user) {
userForm.setUserId(user.getUserId());
userForm.setLogin(user.getLogin());
userForm.setRegDate(user.getRegDate());
// userForm.setComputers(computer);
userForm.setRole(roleService.findByName(user.getRole().getRoleName()));
}
}
And here it is my JSP
<!--BEGIN OF USERS TABLE-->
<div align="center">
<table border=1>
<thead align="center">
<tr>
<th>User Id</th>
<th>Login</th>
<th>Name</th>
<th>Password</th>
<th>Email</th>
<th>Regsiter Date</th>
<th>PC Assigned</th>
<th colspan=2>Action</th>
</tr>
</thead>
<tbody align="center">
<tr>
<c:forEach items="${members}" var="user">
<td><c:out value="${user.userId}"/></td>
<td><c:out value="${user.login}"/></td>
<td><c:out value="${user.name}"/></td>
<td><c:out value="${user.password}"/></td>
<td><c:out value="${user.email}"/></td>
<td><fmt:formatDate pattern="yyyy-MM-dd" value="${user.regDate}"/></td>
<td>
<c:choose>
<c:when test="${user.computers!= null && !user.computers['empty']}">
<c:forEach items="${user.computers}" var="comp">
<c:out value="${comp.pcName}"/>
</c:forEach>
</c:when>
<c:otherwise>
<p class="h3_error">No PC Assigned</p>
</c:otherwise>
</c:choose>
</td>
<td>Update</td>
<td>Delete</td>
</tr>
</c:forEach>
</tbody>
</table>
<br>
</div>
<!--END OF USERS TABLE-->

Categories