SpringBoot: parse button value to controller - java

im new in springboot and really need your expertise. Please help me.
i need to pass the data to controller when the button is click. Now im facing with the error below, what actually i do wrong in my code ?
'java.lang.String' to required type 'com.portal.dmtt.model.taskSchJob'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.lang.Long] for value 'TEST'; nested exception is java.lang.NumberFormatException: For input string: "TEST"
Controller
#RequestMapping(value="/runJob", method=RequestMethod.GET)
public String runJob(Model model, taskSchJob schJob) {
System.out.println("Start get request");
model.addAttribute("theTaskSchJobList", new taskSchJob());
schJob.getScript();
System.out.println("End get request");
return "redirect:/cronJob";
}
#RequestMapping(value="/runJob", method=RequestMethod.POST)
public String customerSubmit(#ModelAttribute taskSchJob schJob, Model model,#RequestParam String taskJobScript) {
System.out.println("Start post request");
System.out.println("End post request" + taskJobScript.toString());
return "redirect:/cronJob";
}
HTML
<tbody>
<tr th:each="taskJob : ${theTaskSchJobList}" style="text-align: center">
<form th:action="#{/runJob}" th:object="${theTaskSchJobList}" th:method="POST">
<td th:text="${taskJob.id}">Id</td>
<td th:text="${taskJob.title}">Username</td>
<td th:text="${taskJob.script}">Script</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>
<button type="submit" class="btn btn-success" th:value="${taskJob.script}" th:name="taskSchJob">
<span class="glyphicon glyphicon-play"></span>
</button>
</form>
</td>
</tr>
</tbody>
Model
#Entity
#Table (name = "task_Sch_Job")
public class taskSchJob {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#Column(name = "title")
private String title;
#Column(name = "username")
private String username;
#Column(name = "script")
private String script;
#Column(name = "date_create")
private String date_create;
#Column(name = "cron_job")
private String cron_job;
#Column(name = "status")
private String status;
//------
//setter and getter
//------
the below image is, when the user click the button, it will send the data 'title' to the controller.

Your custom class com.portal.dmtt.model.taskSchJob isn't String. Please consider passing the valid JSON/XML in request body. This is applied to model object as well.

finally, i did it.Please find the below answer:
#RequestMapping(value = "/taskRun/{id}", method = RequestMethod.GET, params = "actionEdit")
public String taskEdit(Model model, #PathVariable(required = true, name = "id") Long id) {
System.out.println("Start GET request: the id is: " + id);
return "redirect:/cronJob";
}
HTML text by using GET Method
<form th:action="#{/taskRun/__${taskJob.id}__}">
<button type="submit" class="btn btn-success" th:name="actionRun" th:value="run">
<span class="glyphicon glyphicon-play"></span>
</button></form>

Related

How to send a post request using spring boot?

I am using POSTMAN to send the post api request and it is working fine. I had to send a JSON RAW
{
"id": "232",
"message": "elele",
"authorName": "JK Rowling"
}
and I am getting a successful response. But I want to send the post request from the User interface and it is not working.
This is the ThymeLeaf processing error:
"Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor'
This is the html part of it:
<form action="#" th:action="#{/api/v1/greetings}" th:object="${greeting}" method="post">
<p>Message: <input type="text" th:field="*{message}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
This is the controller code:
#Controller
#RequestMapping(path = "/api/v1/greetings")
public class GreetingController {
#ApiOperation(value = "Create Greeting", notes = "Create a greeting based on the given input")
#PostMapping
public ResponseEntity<GreetingResponse> create(#Valid #RequestBody GreetingRequest greetingRequest) {
//
}
and this is the class:
public class Greeting {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
#Column(name = "message")
String message;
#Column(name = "author_name")
String authorName;
Where am I going wrong?

Spring mvc handling differences in types between form and model

I have this form
<form:form action="saveCustomer" modelAttribute="customer" enctype="multipart/form-data" method="POST">
<!-- need to associate this data with customer id -->
<form:hidden path="id" />
<table>
<tbody>
<tr>
<td><label>First name:</label></td>
<td><form:input path="firstName" /></td>
</tr>
<tr>
<td><label>Last name:</label></td>
<td><form:input path="lastName" /></td>
</tr>
<tr>
<td><label>Email:</label></td>
<td><form:input path="email" /></td>
</tr>
<tr>
<td><label>Profile Image:</label></td>
<td>
<form:input type="file" path="file" id="file" class="form-control input-sm"/>
</td>
</tr>
<tr>
<td><label></label></td>
<td><input type="submit" value="Save" class="save" /></td>
</tr>
</tbody>
</table>
</form:form>
and this model
#Entity
#Table(name="customer")
public class Customer {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="first_name")
private String firstName;
#Column(name="last_name")
private String lastName;
#Column(name="email")
private String email;
#NotEmpty
#Column(name="file")
private String file;
}
In my model, I have decided not to define the file field as MultipartFile and instead I went with String.
I did that to enable me just grab the uploaded files file name and leave spring mvc to upload the file. That works but when I introduce error checking I get this error:
org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'customer' on field 'file': rejected value
[org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile#2a8400bb];
codes
[typeMismatch.customer.file,typeMismatch.file,typeMismatch.java.lang.String,typeMismatch];
arguments
[org.springframework.context.support.DefaultMessageSourceResolvable:
codes [customer.file,file]; arguments []; default message [file]];
default message [Failed to convert property value of type
[org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile]
to required type [java.lang.String] for property 'file'; nested
exception is java.lang.IllegalStateException: Cannot convert value of
type
[org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile]
to required type [java.lang.String] for property 'file': no matching
editors or conversion strategy found]
My controller:
#RequestMapping(value = "/saveCustomer", method = RequestMethod.POST)
public String saveCustomer(#Valid FileBucket fileBucket,
ModelMap model, #ModelAttribute("customer") Customer theCustomer,BindingResult result) throws IOException {
if (result.hasErrors()) {
System.out.println("validation errors");
return "customer-form";
} else {
System.out.println("Fetching file");
MultipartFile multipartFile = fileBucket.getFile();
// Now do something with file...
FileCopyUtils.copy(fileBucket.getFile().getBytes(), new File( UPLOAD_LOCATION + fileBucket.getFile().getOriginalFilename()));
String fileName = multipartFile.getOriginalFilename();
model.addAttribute("fileName", fileName);
theCustomer.setFile(fileName);
customerService.saveCustomer(theCustomer);
return "redirect:/customer/list";
}
}
How can I handle this error?
In your error part say about this only
typeMismatch.customer.file,typeMismatch.file,typeMismatch.java.lang.String,typeMismatch
but in entity class file is a string
<form:form action="saveCustomer" modelAttribute="customer" enctype="multipart/form-data" method="POST">
In your form
<form:input type="file" path="file" id="file" class="form-control input-sm"/>
but, here your modelAttribute is customer front end its and file input and backend it's a String so that your having problem
private String file is incorrect param because it's a multipart data so you should use MultipartFile in your entity class
#Entity
#Table(name="customer")
public class Customer {
... . . . . ..
private MultipartFile file;
//getters setters
}
I created another field called path and made file transient
#Entity
#Table(name="customer")
public class Customer {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="first_name")
private String firstName;
#Column(name="last_name")
private String lastName;
#Column(name="email")
private String email;
#NotEmpty
#Column(name="path")
private String path;
#Transient
private MultipartFile file;
and that worked.

How to bind an object list to checkbox in thymeleaf?

I am having a lot of difficulty with binding checkbox inputs with a object list.Issue is when I add th:field="*{userRole}" on input field type checkbox then I am getting Bad request as response on web browser.
Here is my code:
User Model class:
public class User implements Serializable {
private Integer id;
private String username;
private String password;
private boolean enabled;
private List<UserRole> userRole = new ArrayList<UserRole>(0);
}
UserRole Model class:
public class UserRole implements Serializable {
#Id
#GeneratedValue
private Integer userRoleId;
#ManyToMany(mappedBy = "userRole")
private List<User> users;
#Column(name = "role", nullable = false, length = 45)
private String role;
}
Model Attribute:
#ModelAttribute(value = "user")
public User userModel() {
return new User();
}
GET Method:
#RequestMapping(value = "/", method = RequestMethod.GET)
public String index(Map<String, Object> model) {
List<UserRole> roles = roleService.getAllRoles();
model.put("roles", roles);
return "index";
}
My POST method:
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String addUser(#ModelAttribute("user") User userModel) {
}
Index page Form :
<form role="form" action="#" th:action="#{/add}" th:object="${user}" method="post">
<div class="form-group">
<label for="email">User Name:</label>
<input type="text" class="form-control" id="username" th:field="*{username}" required autofocus>
</div>
<ul>
<li th:each="item : ${roles}">
<input type="checkbox" th:field="*{userRole}" th:value="${item}" />
<label th:text="${item.role}">Test</label>
</li>
</ul>
<input type="submit" value="Submit" />
</form>
when I click submit, browser shows as a Bad request, But without th:field="*{userRole}" I can submit the form. Any idea to resolve this issue?
---Update---
issue was Thymeleaf unable to bind object directly. So added new List of String for binding.
private List<String> userRoles = new ArrayList<>(0);
and then changed the form as #Roel mentioned.
<li th:each="item, stat : ${roles}">
<label th:text="${stat.index}">Test</label>
<input type="checkbox" th:field="*{userRoles[__${stat.index}__]}" th:value="${item.userRoleId}" />
<label th:text="${item.role}">Test</label>
</li>
Thanks.
You are trying to add item as the value to a List. It's like trying to say ArrayList<Integer> list = 5;
What you need is to add the item to the list:
li th:each="item, stat : ${roles}">
<input type="checkbox" th:field="*{userRole[__${stat.index}__]}" th:value="${item}" />
<label th:text="${item.role}">Test</label>
</li>
I'm unsure if this will directly solve your problem as thymeleaf has issues with simply "adding" an object to a list. Thymeleaf generally works with basic types like strings and integers. But at least I pointed out where your problem lies. Try fiffling around with this a little bit. Try using this line instead, at least this will definitely work:
<input type="checkbox" th:field="*{userRole[__${stat.index}__].role}" th:value="${item.role}" />

Java Spring: how to validate only specific fields from my entity

I'm new in Spring and I have a problem with form validation. In my user edit form I want to validate only specific fields, not all fields annotated in my entity.
For example, if I have my UserEntity with fields:
#Entity
#Table(name = "users")
public class UserEntity {
#Id
#Column(name = "user_id")
#GeneratedValue
public int user_id;
#NotEmpty
#Column(name = "userlogin")
public String userlogin;
#NotEmpty
#Column(name = "userpass")
public String userpass;
#NotEmpty
#Column(name = "name")
public String name;
#Email
#NotEmpty
#Column(name = "email")
public String email;
#NumberFormat(style = Style.NUMBER)
#NotEmpty
#Column(name = "phone")
public String phone;
and when I have register form, I need to validate all fields, and that's working fine.
But when I have edit user form, I want to edit and validate only 'name', 'email' and 'phone', I don't want to change 'userlogin' and 'userpass'.
But edit form won't pass successfully, because BindingResult validating all fields.
Here's my edit form:
<springForm:form action="/mywebapp/user/edit" commandName="user" method="POST">
<table>
<tr>
<td>Name:</td>
<td><springForm:input path="name" value="${user.name}" /></td>
<td><springForm:errors path="name" cssClass="error" /></td>
</tr>
<tr>
<td>E-mail:</td>
<td><springForm:input path="email" value="${user.email }" /></td>
<td><springForm:errors path="email" cssClass="error" /></td>
</tr>
<tr>
<td>Phone:</td>
<td><springForm:input path="phone" value="${user.phone}" /></td>
<td><springForm:errors path="phone" cssClass="error" /></td>
</tr>
<tr>
<td><input type="submit" value="Edit" /></td>
</tr>
</table>
</springForm:form>
Here is my controller method:
#RequestMapping(value="user/edit", method=RequestMethod.POST)
public String doUserEdit(#Valid #ModelAttribute("user") UserEntity user, BindingResult result, Principal principal) {
if(result.hasErrors()) {
return "user/edit";
}
UserEntity u = this.userService.getUser(principal.getName());
this.userService.editUser(u.getUser_id(), user);
return "redirect:/user";
}
result.hasError() always return true, because it validating also 'userlogin' and 'userpass'.
How to ignore other fields in edit form and validate only that fields that I want to?
I usually create a separate form class which is only suited for form submission processing and put all the necessary validation there:
public class UserUpdateForm {
#NotEmpty
private String name;
#Email
private String email;
#NotEmpty
#NumberFormat(style = Style.NUMBER)
private String phone;
//Getters and setters here
}
The idea is that you untie your model class from representations (form) classes. The only downside to that is that you'll have to handle transformations between the form objects and model objects somehow. Something like dozer might help though.

Spring web mvc Collection in entity class

Lets say i have 2 entities, Dish and Ingrediƫnt.
As we all know a Dish consists out of multiple Ingredients, so let's say:
Dish.java:
#Entity
public class Dish {
#Id
#GeneratedValue
protected long id;
private String name;
#OneToMany(mappedBy = "dish", cascade = CascadeType.PERSIST)
private Collection<Ingredient> ingredients;
//getters & setters
}
Ingrediƫnt.java :
#Entity
public class Ingredient {
#Id
#GeneratedValue
protected long id;
private String name;
//getters &setters
}
If we then have a DishController.java :
#Controller
public class DishController {
Service service;
public DishController() throws ServiceException {
service = new ShoppingFacade("JPA");
}
#RequestMapping("/showDishOverview")
protected ModelAndView getDishes() throws ServiceException {
Collection<Dish> dishes = service.getAllDishes();
return new ModelAndView("dish/dishOverview", "dishes", dishes);
}
#RequestMapping(value = "/showDishForm", method = RequestMethod.GET)
protected ModelAndView showDishForm(#RequestParam(value = "id") long dishId)throws ServiceException{
Dish dish = shoppingFacade.getDishById(dishId);
return new ModelAndView("dish/dishForm", "dish", dish);
}
#RequestMapping(value = "/editDish", method = RequestMethod.POST)
protected String updateDish(#ModelAttribute("dish") Dish newDish) throws ServiceException{
service.updateDish(newDish);
return "forward:/showDishOverview.htm";
}
}
Now lets say that we select one dish by its id:
${dish.getName()}
Now the showDishForm method in our controller will be called.
which will send us to dishForm.jsp:
<form method="post" action="editDish.htm">
<table>
<tr>
<td><label>Name </label></td>
<td><input type="text" name="name" placeholder="${dish.getName()}" value="${dish.getName()}"/></td>
</tr>
<tr>
<td><label>People</label></td>
<td><input type="text" name="people" placeholder="${dish.getPeople()}" value="${dish.getPeople()}"/></td>
</tr>
<tr>
<td colspan="2">
<input type="hidden" name="ingredients" value="${dish.getIngredient()}" />
<button type="submit" name="id" value="${dish.getId()}">Save</button>
</td>
</tr>
</table>
</form>
How will Spring MVC pass the info from my view to the controller?
Cause I get it working as long as I don't pass any Collections.(comment out <input type="hidden" name="ingredients" value="${dish.getIngredient()}" />
)
If i try to pass a Collection i get the message :
HTTP STATUS 400 - The request sent by the client was syntactically
incorrect
Spring uses Converters, for all standard classes these are already implemented.
For custon classes like this List, you have to write your own converter.

Categories