Spring How to update database entites from dropdown lists thymeleaf - spring

So I need to update the entities in my table with the selected values from dropdown lists from thymeleaf.
What I want to do is update the movie column based on the selections from dropdown list. But I have more than one dropdown list for each WeekMovie entity.
I cant figure out how to update them all.
My WeekMovies Class
#Entity
public class WeekMovies {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#ManyToOne
#JoinColumn(name="movie_id")
private Movie movie;
#ManyToOne
#JoinColumn(name="saloon_id")
private Saloon saloon;
//getter setters.
My Controller
#RequestMapping(value = "/update",method= RequestMethod.GET)
public String updateweekmovies(Model model){
List<WeekMovies> weekMoviesList = weekMovieService.findAll();
List<Movie> movieList= movieService.findAll();
model.addAttribute("weekMovieList",weekMoviesList);
model.addAttribute("movieList",movieList);
return "updateweekmovies";
}
#RequestMapping(value = "/update",method= RequestMethod.POST)
public String updateweekPost(Model model){
return "updateweekmovies";
}
My Thymeleaf
div class="container">
<div class="row">
<form class="form-horizontal" th:action="#{/week/update}" method="post"
enctype="multipart/form-data">
<fieldset>
<legend class="center-block">
Update Book Information<span style="font-size: small"> * is a
required field</span>
</legend>
<!-- category -->
<div class="form-group">
<label class="col-md-2 control-label" for="weekmovie">*
Category</label>
<div class="col-md-8">
<li th:each="weekmovie:${weekMovieList}">
<select th:value="${weekmovie.movie}" id="weekmovie" name="weekmovie" class="form-control">
<option value="" selected="selected" disabled="disabled">Please
select an option...</option>
<option th:each="movie:${movieList}" th:value="${movie.id}" th:text="${movie.title}"> </option>
</select>
</li>
</div>
</div>
<div class="form-group">
<div class="col-md-2"></div>
<div class="col-md-8">
<button type="submit" class="btn btn-success">Update Movie</button>
</div>
</div>
</fieldset>
</form>
</div>

Related

How to submit form jsp to controller?

In my jsp there are two fields: 1 types of documents and 2 are statuses.
The challenge is that I can send the selection to my controller. I can not figure out jsp how to send by action these values ​​at the click of a button
<div id="page-content-wrapper">
<div class="container-fluid">
<div class="card">
<div id="collapseSearchParams" class="collapse show" aria-labelledby="headingSearchParams" >
<div class="card-body">
<form:form action="${request.contextPath}/search" method="post">
<div class="row">
<div class="col-lg-3 col-md-4 col-sm-6">
<fieldset class="form-group">
<label class="form-label semibold" for="typeCode">${phDocType}</label>
<select class="form-control" id="typeCode">
<c:forEach var="type" items="${documentList}">
<option id = "${type.value}"> ${type.name} </ option>
</c:forEach>
</select>
</fieldset>
</div>
<div class="col-lg-3 col-md-4 col-sm-6">
<fieldset class="form-group">
<label class="form-label semibold" for="statusCode">${phOrderStatus}</label>
<select class="form-control" id="statusCode">
<option> A</ option>
<option> B</option>
<option> C</option>
<option> D</option>
</select>
</fieldset>
</div>
<div class="col-sm-12">
<button id ="btnSearchUsers" class="btn btn-sm btn-secondary" style="float: right; "><span class="fa fa-search"></span> <spring:message code="label.button.search" /></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
How to get this data in the controller to process? What changes should I make in jsp and in the method?
#RequestMapping(value = "/perso")
public class PersoController {
#Autowired
private PersoService persoService;
private List<DocumentType> docTypeList = null;
#RequestMapping(value = "/list")
public String persoList(Principal principal, Model model) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
docTypeList = persoService.persoList(authentication, principal);
model.addAttribute("documentList", docTypeList);
return "admin/perso/list";
}
#RequestMapping(value = "/search", method = RequestMethod.POST)
public void searchOrders( ){
}
}
thanks in advance
It's better to use #RequestParam in your controller.
For Example:
#RequestMapping(value = "/bar")
public String testAction(#RequestParam String fieldName) {
//Do whatever you want to fieldName
return "view";
}
For your case
#RequestMapping(value = "/search", method = RequestMethod.POST)
public void searchOrders(#RequestParam String statusCode ,#RequestParam String typeCode)
{
//Do whatever you want
}

How to assign entity to another entity in a form using ThymeLeaf?

I am working on MVC Java project and am using Spring Boot with ThymeLeaf. The issue I have is, that when creating a Task, I want to select and save a User, that will be assign to the task. I managed to do the selection correctly, but am unable to save the selected user. It always saves without the User assigned.
Here is my Task entity class:
#Entity
public class Task extends BaseEntity {
private String name;
private String description;
private Date dateOfCreation;
#DateTimeFormat(pattern = "yyyy-MM-dd")
private Date dueDate;
#ManyToOne
private User assignee;
public Task() {
this.dateOfCreation = new Date(System.currentTimeMillis());
}
}
My User entity is as follows:
#Entity
public class User extends BaseEntity {
private String username;
private String password;
#OneToMany(mappedBy = "assignee")
private List<Task> assignedTasks;
}
Where BaseEntity contains
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Version
private Integer version;
My controller function, that is responsible for my taskform.html is:
#RequestMapping("/new")
public String newTask(Model model){
model.addAttribute("task", new Task());
model.addAttribute("users", userService.getAllUsers());
return "task/taskform";
}
And my taskform.html looks like this:
<form class="form-horizontal" th:object="${task}" th:action="#{/task}" method="post">
<input type="hidden" th:field="*{id}"/>
<input type="hidden" th:field="*{version}"/>
<div class="form-group">
<label class="col-sm-2 control-label">Name:</label>
<div class="col-sm-10">
<input type="text" class="form-control" th:field="*{name}"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Description:</label>
<div class="col-sm-10">
<input type="text" class="form-control" th:field="*{description}"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Description:</label>
<div class="col-sm-10">
<input type="date" th:value="*{dueDate}" th:field="*{dueDate}" id="dueDate" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Select user:</label>
<div class="col-sm-10">
<select class="form-control">
<option th:field="*{assignee}" th:each="assignee : ${users}" th:value="${assignee}" th:text="${assignee.username}">
</option>
</select>
</div>
</div>
<div class="row">
<button type="submit" class="btn btn-default">Submit</button>
</div>
I am trying to pass the object from users list as the value, but it does not work Any idea, how to do it?
Showing the users works as expected:
Working frontend
Null is being assigned to assignee column, where the user should be assigned.
Null in H2 Database
EDIT
Here is my POST method from Task Controller:
#RequestMapping(method = RequestMethod.POST)
public String saveOrUpdate(Task task){
taskService.persistTask(task);
return "redirect:/task/list";
}

Unable to bind thymeleaf template and spring boot correctly

I am working on registration in spring boot with spring security and thymeleaf but for some reason the userForm.getUsername() gives null value during POST (see code below)
Person.java
#Entity#Table(name = "person")
public class Person {
#Id#Column(name = "username")
private String username;
#Column(name = "mobile")
private String mobile;
#JsonIgnore#Column(name = "password")
private String password;
#Transient#JsonIgnore
private String passwordConfirm;
#ManyToMany(cascade = CascadeType.ALL)#JoinTable(name = "bookandperson", joinColumns = #JoinColumn(name = "username"), inverseJoinColumns = #JoinColumn(name = "bookName"))
private List < Book > listOfBooks = new ArrayList < Book > ();
}
PersonController.java
#Controller
public class PersonController {
#Autowired
private UserService userService;
#Autowired
private SecurityService securityService;
#Autowired
private UserValidator userValidator;
#RequestMapping(value = "/registration", method = RequestMethod.GET)
public String registration(Model model, Principal user) {
if (user != null) {
return "redirect:/";
}
model.addAttribute("userForm", new Person());
return "registration";
}
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public String registration(#ModelAttribute Person userForm, BindingResult bindingResult, Model model) {
System.out.println(userForm.getUsername()); //This is giving null value
userValidator.validate(userForm, bindingResult);
if (bindingResult.hasErrors()) {
System.out.println("binding result has errors");
return "registration";
}
userService.save(userForm);
securityService.autologin(userForm.getUsername(), userForm.getPasswordConfirm());
return "redirect:/";
}
registration.html
<head>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
</head>
<body>
<nav th:replace="common/navbar :: common-navbar"/>
<div class="container mt-4">
<div class="row justify-content-center">
<div class="col-md-6 col-md-offset-6">
<form th:action="#{/registration}" method="post">
<div class="form-group row">
<label for="inputUsername" class="col-sm-2 col-form-label">Username</label>
<div class="col-md-6">
<input type="text" class="form-control" th:field="${userForm.username}" id="inputUsername" value="" placeholder="Username">
</div>
</div>
<div class="form-group row">
<label for="mobile" class="col-sm-2 col-form-label">Mobile</label>
<div class="col-md-6">
<input type="text" class="form-control" th:field="${userForm.mobile}" id="inputMobile" placeholder="Mobile">
</div>
</div>
<div class="form-group row">
<label for="inputPassword" class="col-sm-2 col-form-label">Password</label>
<div class="col-md-6">
<input type="password" class="form-control" th:field="${userForm.password}" id="inputPassword" placeholder="Password">
</div>
</div>
<div class="form-group row">
<label for="inputPasswordConfirm" class="col-sm-2 col-form-label">Confirm Password</label>
<div class="col-md-6">
<input type="password" class="form-control" th:field="${userForm.passwordConfirm}" id="inputPasswordConfirm" placeholder="Password">
</div>
</div>
<div class="form-group row">
<div class="offset-2 col-sm-10">
<button type="submit" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" class="btn btn-primary">Submit</button>
</div>
</div>
<small th:text="${error}"></small>
</form>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</body>
I binded correctly using th:field="${userForm.username}" but unable to find what is the problem here.
you have to take the model object into the form as follows
<form action="#" th:action="#{/registration}" th:object="${userForm}" method="post">
and add the getters and setters to the Person class

Cannot process submitted foreign keys

There are 3 one-to-many relationships into an entity Pta :
#Entity
#Table(name = "pta")
public class Pta {
#Id()
#SequenceGenerator(name="s_pta", sequenceName="pta.s_pta", allocationSize=1)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="s_pta")
#Column(name="pta_code")
private Integer code;
#Column(name="pta_intitule")
private String lib;
#ManyToOne
#JoinColumn(name = "obj_code")
private Objectif objectif;
#ManyToOne
#JoinColumn(name = "struct_code")
private Structure structure;
#ManyToOne
#JoinColumn(name = "exer_code")
private Exer exercice;
public Pta() {
super();
}
public Pta(Integer code) {
super();
this.code = code;
}
// getters and setters
}
#Entity
#Table(name = "objectif")
public class Objectif {
#Id
#SequenceGenerator(name="s_objectif", sequenceName="pta.s_objectif", allocationSize=1)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="s_objectif")
#Column(name = "obj_code")
private int code;
#Column(name="obj_intitule")
private String lib;
#ManyToOne
#JoinColumn(name = "prog_code")
private Programme programme;
#ManyToOne
#JoinColumn(name = "nat_obj_code")
private NatureObjectif nature_objectif;
public Objectif() {
super();
}
public Objectif(int code) {
super();
this.code = code;
}
public Objectif(int code, String lib) {
super();
this.code = code;
this.lib = lib;
}
// getters and setters
}
#Entity
#Table(name = "structure")
public class Structure {
#Id()
#Column(name="struct_code")
private String code;
#Column(name="struct_sigle")
private String sigle;
#Column(name="struct_lib")
private String lib;
public Structure() {
super();
}
public Structure(String code) {
super();
this.code = code;
}
// getters and setters
}
#Entity
#Table(name = "exercice")
public class Exer {
#Id()
#Column(name="exer_code")
private String exerCode;
#Column(name="exer_lib")
private String exerLibelle;
public Exer(){
super();
}
public Exer(String exer_code) {
super();
this.exerCode = exer_code;
}
// getters and setters
}
I want to insert a record into the Pta.
controller for page jsp :
modelView.addObject("exercices",exerDao.list());
modelView.addObject("structures",structureDao.list());
HashMap<String, String> criteres = new HashMap<String, String>();
criteres.put("nat_obj_code", "DdP");
modelView.addObject("docs_perf", objectifDao.lireParCritere(criteres));
criteres.clear();
criteres.put("nat_obj_code", "ODD");
modelView.addObject("odds", objectifDao.lireParCritere(criteres));
criteres.clear();
criteres.put("nat_obj_code", "PRO");
modelView.addObject("produits", objectifDao.lireParCritere(criteres));
modelView.addObject("action", request.getContextPath().concat("/elaboration/savePtaEtDetails"));
modelView.addObject("pta_formulaire", new Pta());
return modelView;
jsp :
<form:form cssClass="form-horizontal" servletRelativeAction="${action}" method="post" commandName="pta_formulaire">
<form:hidden path="code"/>
<div class="row">
<div class="col-sm-8">
<div class="form-group">
<label class="col-sm-4 control-label">Exercice</label>
<div class="col-sm-4">
<form:select path="exercice" cssClass="validate[required]">
<form:option value="" label=" -- Sélectionner -- "/>
<form:options items="${exercices}" itemValue="exerCode" itemLabel="exerLibelle" />
</form:select>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Document de performance</label>
<div class="col-sm-4">
<form:select path="objectif" style="width:500px;" cssClass="validate[required]">
<form:option value="" label=" -- Sélectionner -- "/>
<form:options items="${docs_perf}" itemValue="code" itemLabel="lib" />
</form:select>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">ODD</label>
<div class="col-sm-4">
<select id="odd" name="odd" style="width:500px;">
<option value=""> -- Sélectionner -- </option>
<c:forEach items="${odds}" var="odd">
<option value="${odd.code}">${odd.lib}</option>
</c:forEach>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Axes du PND</label>
<div class="col-sm-4">
<select id="pnd" name="pnd" style="width:500px;" multiple></select>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Programmes</label>
<div class="col-sm-4">
<select id="programme" name="programme" style="width:500px;" multiple></select>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Effets</label>
<div class="col-sm-4">
<select id="effet" name="effet" style="width:500px;" multiple></select>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Produits PMO</label>
<div class="col-sm-4">
<select id="produit" name="produit" style="width:500px;" multiple>
<option value=""> -- Sélectionner -- </option>
<c:forEach items="${produits}" var="produit">
<option value="${produit.code}">${produit.lib}</option>
</c:forEach>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Actions PMO</label>
<div class="col-sm-4">
<select id="action" name="action" style="width:500px;" multiple></select>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Activité</label>
<div class="col-sm-4">
<select id="activite" name="activite" style="width:500px;">
<option value=""> -- Sélectionner -- </option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Résultat attendu</label>
<div class="col-sm-4">
<select id="resultat" name="resultat" style="width:500px;">
<option value=""> -- Sélectionner -- </option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Indicateur</label>
<div class="col-sm-8">
<select id="indicateur" name="indicateur" style="width:500px;">
<option value=""> -- Sélectionner -- </option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<fieldset>
<legend><label class="control-label">Programmation physique</label></legend>
<div class="row">
<div class="col-sm-3">
<div class="form-group">
<label class="col-sm-1 control-label">T1</label>
<div class="col-xs-10">
<input class="form-control" type="text" name="t1">
</div>
</div>
</div>
<div class="col-sm-3">
<div class="form-group">
<label class="col-sm-1 control-label">T2</label>
<div class="col-xs-10">
<input class="form-control" type="text" name="t2">
</div>
</div>
</div>
<div class="col-sm-3">
<div class="form-group">
<label class="col-sm-1 control-label">T3</label>
<div class="col-xs-10">
<input class="form-control" type="text" name="t3">
</div>
</div>
</div>
<div class="col-sm-3">
<div class="form-group">
<label class="col-sm-1 control-label">T4</label>
<div class="col-xs-10">
<input class="form-control" type="text" name="t4">
</div>
</div>
</div>
</div>
</fieldset>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<fieldset>
<legend><label class="control-label">Programmation financière</label></legend>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label class="col-sm-1 control-label">Montant</label>
<div class="col-xs-3">
<input class="form-control" type="text" name="progr_financiere">
</div>
</div>
</div>
</div>
</fieldset>
</div>
</div>
</div>
<div class="col-sm-4">
<div class="form-group">
<label class="col-sm-4 control-label">Structure</label>
<div class="col-sm-4">
<form:select path="structure" style="width:230px;" cssClass="validate[required]">
<form:option value="" label=" -- Sélectionner -- "/>
<form:options items="${structures}" itemValue="code" itemLabel="lib" />
</form:select>
</div>
</div>
</div>
<input class="btn btn-primary btn-sm" type="submit"/>
</form:form>
In the controller target :
#RequestMapping(value = "/savePtaEtDetails", method = RequestMethod.POST)
public ModelAndView savePtaEtDetails(#ModelAttribute("pta_formulaire") Pta pta, #RequestParam String exercice, #RequestParam int objectif,
#RequestParam String structure) {
System.out.println("eeeeeeeeeeeeeeee");
return new ModelAndView("redirect:/accueil");
}
At runtime when submitting the form then I got the error The request sent by the client was syntactically incorrect. So what is wrong ?
I found it :) The solution was to not set the attribute in the constructor of the "master" entities :
public Exer(String exer_code) {
super();
}
public Structure(String code) {
super();
}
public Objectif(String code) {
super();
}

How tell the view an error has occured from controller? (Spring MVC)

How can I say trigger error/validation messages in the view from the controller in a better way? Currently, I do this by sending boolean attributes. For example, in creating a product, I have two possible errors. Invalid format of UPC of a product, or duplicate upc. I also have a validati
#RequestMapping("/createProduct")
public String createProduct(Model model, #RequestParam(value = "name") String name,
#RequestParam(value = "upc") String upc, #RequestParam(value = "category") String categoryName,
#RequestParam(value = "description") String description, #RequestParam(value = "price") BigDecimal price,
#RequestParam(value = "stock") int stock){
model.addAttribute("activeTab", 3);
if(Validator.invalidUpcFormat(upc)){
model.addAttribute("invalidFormat", true); //trigger for invalid format
return "management";
}
Category category = productService.getCategory(categoryName);
Product product = new Product(upc, category, name, description, price);
InventoryProduct inventoryProduct = new InventoryProduct(product, stock);
try {
managerService.add(inventoryProduct);
model.addAttribute("productCreated", true);
} catch (DuplicateProductException e) {
model.addAttribute("upc", upc);
model.addAttribute("duplicateProduct", true); // trigger for duplicate product
}
return "management";
}
And here is my view:
<div id="menu3"
class="tab-pane fade <c:if test="${activeTab == 3}">in active</c:if>">
<div class="container-fluid" style="padding: 2%;">
<div class="row">
<div class="col-md-12"
style="padding-left: 15%; padding-right: 15%;">
<c:if test="${productCreated}">
<div class="alert alert-success fade in">
<a href="#" class="close" data-dismiss="alert"
aria-label="close">×</a> <strong>Success!</strong>
Product has been created!
</div>
</c:if>
<c:if test="${duplicateProduct}">
<div class="alert alert-warning fade in">
<a href="#" class="close" data-dismiss="alert"
aria-label="close">×</a> <strong>Oh no!</strong>
Product with the UPC ${upc} already exists!
</div>
</c:if>
<c:if test="${invalidFormat}">
<div class="alert alert-warning fade in">
<a href="#" class="close" data-dismiss="alert"
aria-label="close">×</a> <strong>Oops!</strong>
Invalid UPC format!
</div>
</c:if>
<form
action="${pageContext.request.contextPath}/manager/createProduct"
method="post">
<div class="form-group">
<label for="Name">Name </label> <input type="text" name="name"
class="form-control" required />
</div>
<div class="form-group">
<label for="UPC">UPC </label> <input type="number" name="upc"
class="form-control" required />
</div>
<div class="form-group">
<div class="form-group">
<label for="category">Category</label> <select
class="form-control" name="category" required>
<option selected disabled value="">SELECT CATEGORY</option>
<c:forEach items="${categories}" var="item">
<option>${item.getName()}</option>
</c:forEach>
</select>
</div>
</div>
<div class="form-group">
<label for="description">Description</label>
<textarea class="form-control" rows="5" name="description"></textarea>
</div>
<div class="form-group">
<label for="price">Price </label> <input type="number"
name="price" class="form-control" required />
</div>
<div class="form-group">
<label for="stock">Stock </label> <input type="number"
name="stock" class="form-control" required />
</div>
<button type="submit" class="btn btn-primary">Add
product</button>
</form>
</div>
</div>
</div>
</div>
Is there a better of doing this other than sending boolean triggers?
You could use Spring BindingResult. This is typical filled with the result of Binding and Validation results. But you can also add errors by hand.
But first you need to refactor your code, so that you use an single command/form-backing object instead of all the #Param values
public class CreateProductCommand {
private String name;
private String upc;
private String categoryName;
.... //other fields
public CreateProductCommand (){} //parameter less conturctor
Getter+Setter
}
Controller
#RequestMapping("/createProduct")
public ModelAndView createProduct(CreateProductCommand createProductCommand, BindingResult bindingResult) //Binding result must be the parameter direct next to the object that should been validated!!!
{
if (someustomValidationForUcpFail()) {
bindingResult.rejectValue("upc", //the field name of the invalid field
"error.Message.Key",
"Default Error Message");
}
if (bindingResult.hasErrors()) {
ModelMap model = new ModelMap();
model.add("createProductCommand", createProductCommand);
return new ModelAndView("createForm", model)
} else {
Product product = ...
return new ModelAndView("showProduct", "product", product)
}
}
jsp:
You need to use springs form and input tag:
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:springForm="http://www.springframework.org/tags/form"
version="2.0">
....
<springForm:form action="<c:url value="/manager/createProduct">" method="POST" modelAttribute="createProductCommand">
<springForm:input path="name"/> <form:errors path="name" />
<springForm:input path="ucp"/> <form:errors path="ucp" />
....
</springForm:form>
....

Resources