I have a form which looks like this:
<form th:action="#{/viewExpenses}" method="post" class="form-horizontal">
<div class="form-group">
<label for="date" class="control-label col-md-3">Date:-</label>
<div class="col-md-9">
<input type="date" class="form-control" id="date" th:name="date"/>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-3 col-md-4">
<button class="btn btn-primary">View Details</button>
</div>
</div>
</form>
Now when I submit this form I wish to get the date value as LocalDate. So on my controller I did:
#RequestMapping(value = "/viewExpenses", method = RequestMethod.POST)
public String expenseDetails(Model model, #RequestParam("date")
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) {
BigDecimal totalExpense = new BigDecimal(0);
List<Expenditure> e = expenditureService.viewExpenseDetails(date);
for (Expenditure exp : e) {
totalExpense = totalExpense.add(exp.getAmount());
}
model.addAttribute("showExpenditure", true);
model.addAttribute("totalExpense", totalExpense);
model.addAttribute("expenses", e);
return "finance/expensedetails";
}
For now I get date value in my controller as null. I have tried changing pattern of #DateTimeFormat but it is still not working.
what might be the correct way to receive date parameter?
This looks like the binding here is not happening.you can try using spring:form tag and bind the controller object via modelAttribute.
Related
I am creating an Spring Boot App, in which the user can create licences. The user can type the name, purchaseDate, renewalDate and expirationDate.
My problem is, that when I try to save the data, it returns null for the name, the purchaseDate, renewalDate and expirationDate.
I absolutely don't know what to do anymore, please help. The "// Comment" values in the Model:Licence are those who get null when executing the post.
Model: Licence
#Entity
#Table(name = "TBL_LICENCES")
public class Licence {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id;
private String licenceName; // --> null after the post
#DateTimeFormat(pattern = "yyyy-MM-dd")
private String purchaseDate; // --> null after the post
#DateTimeFormat(pattern = "yyyy-MM-dd")
private String renewalDate; // --> null after the post
#DateTimeFormat(pattern = "yyyy-MM-dd")
private String expirationDate; // --> null after the post
public Licence() {}
public Licence(Long id, String licenceName, String purchaseDate, String renewalDate, String expirationDate) {
Id = id;
this.licenceName = licenceName;
this.purchaseDate = purchaseDate;
this.renewalDate = renewalDate;
this.expirationDate = expirationDate;
}
// Getter and Setter
}
Model: LicenceRepository
#Repository
public interface LicenceRepository extends CrudRepository<Licence, Long> { }
Service: LicenceService
#Service
public class LicenceService {
#Autowired
private LicenceRepository licenceRepository;
public List<Licence> getLicences() {
return (List<Licence>) licenceRepository.findAll();
}
public Optional<Licence> getLicenceById(Long id) {
return licenceRepository.findById(id);
}
public void addLicence(Licence licence) {
licenceRepository.save(licence);
}
public void updateLicence(Licence licence) {
licenceRepository.save(licence);
}
public void deleteLicenceById(Long id) {
licenceRepository.deleteById(id);
}
}
Controller: LicenceController
#Controller
public class LicenceController {
#Autowired
private LicenceService licenceService;
#GetMapping("/licences")
public String getLicences(Model model) {
model.addAttribute("licences", licenceService.getLicences());
return "licences";
}
#GetMapping("/onelicence")
#ResponseBody
public Optional<Licence> getLicenceByID(Long id, Model model) {
model.addAttribute("onelicence", licenceService.getLicenceById(id));
return licenceService.getLicenceById(id);
}
#RequestMapping(value="/save", method = {RequestMethod.POST, RequestMethod.PUT, RequestMethod.GET})
public String updateLicence(Licence licence) {
licenceService.updateLicence(licence);
return "redirect:/licences";
}
**// Is performed, when clicking "New Licence > Save"**
#RequestMapping(value="/addNew", method = {RequestMethod.POST, RequestMethod.PUT, RequestMethod.GET})
public String addLicence(Licence licence) {
licenceService.addLicence(licence);
return "redirect:/licences";
}
#RequestMapping(value="/delete", method = {RequestMethod.DELETE, RequestMethod.PUT, RequestMethod.GET})
public String deleteLicence(Long id) {
licenceService.deleteLicenceById(id);
return "redirect:/licences";
}
}
licences.html
<!DOCTYPE html>
<html lang="de" xmlns="http://www.w3.org/1999/html"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<script type ="text/javascript" src="webjars/jquery/3.4.1/jquery.min.js"></script>
<script type ="text/javascript" src="webjars/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<link href="webjars/bootstrap/4.4.1/css/bootstrap.css" rel="stylesheet"/>
<title>Licence</title>
</head>
<body>
<div class = "container">
<h2>Licences</h2>
<table class = "table table-striped">
<thead>
<tr>
<td>ID</td>
<td>Name</td>
<td>Kaufdatum</td>
<td>Erneuerungsdatum:</td>
<td>Auslaufdatum:</td>
</tr>
</thead>
<tbody>
<tr th:each = "licence: ${licences}">
<td th:text="${licence.id}">ID</td>
<td th:text="${licence.licenceName}">Name</td>
<td th:text="${licence.purchaseDate}">Kaufdatum</td>
<td th:text="${licence.renewalDate}">Erneuerungsdatum</td>
<td th:text="${licence.expirationDate}">Auslaufdatum</td>
<td><a class="btn btn-warning">Edit</a></td>
<td><a class="btn btn-danger">Delete</a></td>
</tr>
</tbody>
</table>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addModal" data-whatever="#mdo">New Licence</button>
</div>
// Bootstrap Varying Modal Content
<div class="modal fade" id="addModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<form th:action="#{/addNew}" method ="post">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">New Licence</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="name" class="col-form-label">Lizenz Name</label>
<input type="text" class="form-control" id="licenceName" name="name">
</div>
<div class="form-group">
<label for="purchase" class="col-form-label">purchaseDate</label>
<input type="date" class="form-control" id="purchaseDate" name="purchase">
</div>
<div class="form-group">
<label for="renewalAdd" class="col-form-label">renewalDate</label>
<input type="date" class="form-control" id="renewalAdd" name="renewal">
</div>
<div class="form-group">
<label for="expirationAdd" class="col-form-label">expirationDate</label>
<input type="date" class="form-control" id="expirationAdd" name="expiration">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save</button>
</div>
</div>
</div>
</form>
</div>
</body>
</html>
schema.sql
DROP TABLE IF EXISTS TBL_LICENCES;
CREATE TABLE TBL_LICENCES (
id INT AUTO_INCREMENT PRIMARY KEY,
licence_name VARCHAR(250),
purchase_date VARCHAR(250),
renewal_date VARCHAR(250),
expiration_date VARCHAR(250)
);
data.sql --> This works and the data is shown.
INSERT INTO
TBL_LICENCES (licence_name, purchase_date, renewal_date, expiration_date)
VALUES
('Test1', '2020-01-31', '2020-06-31', '2020-12-31'),
('Test', '2021-01-31', '2021-06-31', '2021-12-31');
Properties: application.properties
spring.h2.console.enabled=true
spring.datasource.platform=h2
spring.datasource.url=jdbc:h2:mem:<dbLicences>
spring.jpa.hibernate.ddl-auto=update
The name attribute of the input control should match the name of the fields in the Licence class. Currently your id attribute is matching the name of the fields, but when a form is submitted it uses the name attribute to build the request parameters.
Update your HTML to match something like:
<input type="text" class="form-control" id="licenceName" name="licenceName" />
Fix the name for other fields and you will have the Licence object populated with data from the form.
Also, I see that
#DateTimeFormat(pattern = "yyyy-MM-dd")
private String licenceName;
licenceName is annotated with #DateTimeFormat. I guess this is a mistake, please correct that as well.
On my view, I generate input "username", select with attribute multiple=multiple, which has name "rolesss".
My issue is, that if I send such form via post, my controller should convert roles to list, but i get only list containing single element.
For example:
I send post, with values:
username:MyUser
_csrf:aef50238-92cf-48df-86a4-cb6e2b8f62c9
rolesss:USER
rolesss:ADMIN
In debug mode in my controller I see values:
roless: "USER"
username: "MyUser"
"ADMIN" did just disappear.
My controller looks like:
#Controller
#RequestMapping("/user-management")
public class UserManagementController {
#RequestMapping("")
public ModelAndView home() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("pages/user-management");
return modelAndView;
}
#RequestMapping(value = "", method = RequestMethod.POST)
public ModelAndView changeRoles(#ModelAttribute("username") String username,#ModelAttribute("rolesss") List<String> rolesss) {
return null;
}
}
My view I merged 2 thymeleaf fragments into 1, in my code #user-roles-form is in separate fragment, but I think that it should not change anything:
<th:block layout:fragment="main-content">
<section>
<h2 class="section-title no-margin-top">Role Management</h2>
<div class="form-group">
<div class="panel panel-primary">
<div class="panel-heading">Změna rolí uživatele</div>
<div class="panel-body">
<form class="form-horizontal" role="form" action="/user-management" method="post">
<div class="form-group">
<label for="user-name" class="col-sm-2 control-label">Uživatel</label>
<div class="col-sm-10">
<input id="user-name" class="autocomplete form-control" type="text"
placeholder="Jméno uživatele" name="username"/>
</div>
<input type="hidden"
th:name="${_csrf.parameterName}"
th:value="${_csrf.token}"/>
</div>
<div id="user-roles-form" th:fragment="roles(roles)" xmlns:th="http://www.thymeleaf.org">
<div class="form-group">
<label for="user-roles" class="col-sm-2 control-label">Uživatelovy role</label>
<div class="col-sm-10">
<select multiple="multiple" class="form-control" id="user-roles" name="rolesss">
<th:block th:each="role : ${roles}">
<option th:value="${role.userRole.role}" th:text="${role.userRole.role}" th:selected="${role.selected}"></option>
</th:block>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-ar btn-primary">Uložit</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
</th:block>
try using like below in your controller
in your HTML or JSP
<form modelAttribute="your_model_name"></form>
if you are using model attribute then use #ModelAttribute
otherwise, use #RequestParam("username")
In your case
#RequestMapping(value = "", method = RequestMethod.POST)
public ModelAndView changeRoles(#RequestParam("username") String username,#RequestParam("rolesss") List<String> rolesss) {
..........
.........
return null;
}
Im working on spring MVC webApp project and I'm sort of stuck at this one step. I have a JSP page that have buttons with value of $1.00 .25 etc. when user click the buttons the value need to be stored for purchase. i have a method in the controller but unsure what to pass in the parameter for the input. Please point me to the right the direction. thanks.
<div class="form-group" >
<input class="form-control" style="text-align: center" id="display-money" placeholder="Enter Money" required/> <!--to diplay total -->
</div>
<div class="col-md-6">
<button method="POST"
action="addOne-btn"
value="addOne"
modelAttribute="add-one"
type="button"
name="one"
id="addOne"
class="btn btn-default ">
Add Dollar
</button>
</div>
<div class="col-md-6">
<div class="form-group">
<button method="POST"
value="addQrtr"
action="addQrtr-btn"
type="button"
name="qrtr"
id="addQRTR"
class="btn btn-default">
Add Quarter
</div>
</div>
</div>
-------------------------------------------------------------------
//controller
#RequestMapping(value = "/money", method = RequestMethod.GET)
public String money(HttpServletRequest request, Model model){
BigDecimal moneyIn = new BigDecimal(0);
String input = request.getParameter();//pass in onlcick from jsp.
if(input.equals("addOne")){
moneyIn.add(new BigDecimal(1.00));
}
if(input.equals("")){
moneyIn.add(new BigDecimal(.25));
}
}
Use #ModelAttribute in your submit controller.
#RequestMapping(value = "/money", method = RequestMethod.GET)
public String money(HttpServletRequest request, #ModelAttribute Bean bean){
BigDecimal moneyIn = new BigDecimal(0);
String input = bean.get***();//pass in onlcick from jsp.
if(input.equals("addOne")){
moneyIn.add(new BigDecimal(1.00));
}
if(input.equals("")){
moneyIn.add(new BigDecimal(.25));
}
}
I have tried to solve the problem since 3 days now, but I can´t.
Actually I want to update a row, but instead of the update the .merge() makes a insert.
The Id is autogenerated from the mySql database.
This is the first button to call the formular, with the id from the prior persisted Report:
<a th:href="#{|/reports/updateForm/${reportId}|}">
<button class="button btn-default btn-xs pull-right" type="button" th:title="#{report.formEdit}">
<i class="fa fa-edit fa-fw"></i></button></a>
This is the aspect which should call the view updateformular:
#RequestMapping(value = "/updateForm/{id}", produces = "text/html", method = RequestMethod.GET)
public String ReportController.updateForm(#PathVariable("id") long id, Model model) {
CRMReport newCRMReport = CRMReport.findCRMReport(id);
model.addAttribute("newCRMReport", newCRMReport);
return "reports/update";
}
Excerpt of view update:
<form action="#" class="form" role="form"
th:object="${newCRMReport}" th:action="#{/reports/update/}"
th:method="put">
<div class="modal-body col-lg-6 form-left">
<div class="panel panel-info">
<div class="panel-heading">
<i th:text="#{report.info}"></i>
</div>
</div>
//Example of the send data fields
<div class="form-group" th:classappend="${#fields.hasErrors('projectState')} ? error">
<label for="projectState" th:text="#{report.projectstatus}"></label>
<select class="form-control" id="projectState" th:field="*{projectState}"
th:size="${pros.length}" multiple="multiple">
<option th:each="pro : ${pros}" th:value="${{pro}}" th:field="*{projectState}" th:text="${pro}"></option>
</select>
</div>
<div class="form-group">
<div>
<input type="hidden" th:field="*{id}" class="form-control" id="id"/>
</div>
</div>
<div class="modal-footer col-lg-12">
<button name="action" value="cancel" type="submit"
class="btn btn-default pull-right">
<i class="fa fa-times fa-fw"></i>
<i th:text="' '+#{report.cancel}"></i>
</button>
<button name="action" value="save" type="submit"
class="btn btn-primary pull-right">
<i class="fa fa-save fa-fw"></i>
<i th:text="' '+#{report.show}"></i>
</button>
</div>
The last thing shoud be an merge(update) of the previus send object newCRMReport:
#RequestMapping(value = "/update", produces = "text/html", method = RequestMethod.PUT, params = "action=save")
public String ReportController.updateReport(#Valid #ModelAttribute("newCRMReport") CRMReport newCRMReport,
BindingResult result, Model model, SessionStatus status) {
// ID will be x, from the prior object
System.out.println("id before: " + newCRMReport.getId());
status.setComplete();
newCRMReport = newCRMReport.merge();
// ID will be x+1, from the new object
System.out.println("id then: " + newCRMReport.getId());
return "redirect:/reports/list/" + newCRMReport.getId();
}
This is the object to update:
#RooJavaBean
#RooToString
#RooJpaActiveRecord(table = "crm_report")
public class CRMReport{
private String projectState;
private String sector;
private String location;
private String client;
private String company;
#JoinColumn
#ManyToOne
private CRMUser responsible;
private String relevance;
private String volumeFrom;
private String volumeTo;
private String chance;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(pattern = "dd.MM.yyyy HH:mm:ss")
private Date dateFrom;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(pattern = "dd.MM.yyyy HH:mm:ss")
private Date dateTo;
private String timeSpanFrom;
private String timeSpanTo;
#JoinColumn
#ManyToOne
private CRMUser createdBy;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(style = "M-")
private Date createdAt;
}
Can you please help me? Do you know why it performs an insert instead of update it?
Greetings
Loopek (:
I think the problem might be related to this block:
<div class="form-group">
<div>
<input type="hidden" th:field="*{id}" class="form-control" id="id" th:value="${{reportId}}"/>
<span class="help-inline" th:errors="*{id}">[error]</span>
</div>
</div>
First of all, for a hidden input field you won't show any validation error messages, so remove everything but the hidden input field itself.
Next, you are making an association between the input field and the id property of the newCRMReport object instance using the th:field="*{id}" attribute. But you are using also the th:value="${{reportId}} attribute, with a value (reportId) which I think is not available in the view model. That will end with a null or empty value in the id field.
Try replacing the previous block with the following one. Then check if the generated HTML is valid and the hidden field contains the id value.
<input type="hidden" th:field="*{id}" />
Thank you all for your comments and answers. With your annotations I found out the answer.
I have now added the version, with the type:"hidden" to the update view.
<div class="form-group">
<div>
<input type="hidden" th:field="*{version}"
class="form-control" id="version"/>
</div>
</div>
The merge then performs an update.
My application is writen in Spring MVC with the frontend with JQuery datetimepicker. Then i try to format the Date in java, here is what i do :
My main.html page
<body>
<script>
$(function () {
$("#Tgl_Trans").datepicker({ dateFormat: 'yy/mm/dd'});
/* $("#tgl_order").datetimepicker(); */
});
</script>
<div class="form-group" th:classappend="${#fields.hasErrors('Tgl_Trans')} ? error">
<label class="col-sm-2 control-label">Tgl Trans</label>
<div class="col-sm-10">
<div class="col-xs-6">
<input type="text" th:field="*{Tgl_Trans}" class="form-control" required="required" />
<span class="help-inline" th:errors="*{Tgl_Trans}">[error]</span>
</div>
</div>
</div>
</body>
that's the JQuery datetimepicker should be
and then here is my object model, which is named orders.java
#Column(name = "Tgl_Trans")
#DateTimeFormat(pattern = "yyyy/MM/dd")
private Date Tgl_Trans;
//the getter setter
public Date getTgl_Trans() {
return Tgl_Trans;
}
public void setTgl_Trans(Date tgl_Trans) {
Tgl_Trans = tgl_Trans;
}
that's where i alreader format the date
and then here is my jdbc class when i trying to insert into my database, which is named JdbcOrdersInsert.java
Date tgl_trans = returorder.getTgl_Trans();
String no_retur = kode_Salesman+ tgl_trans.toString();
what i got is the tgl_trans.toString() become something like this "Sat Feb 28 00:00:00 ICT 2015" that the output
how can i format it to be like "20150128"?
even can't do tgl_trans.getYear() <-- it give me a strikethrough and warning. what am i missing here?