How to send a post request using spring boot? - java

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?

Related

SpringBoot: parse button value to controller

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>

binding spring validators with angular 2

I am using spring boot as back-end and angular 2 as front-end.
My problem consist how to bind spring validators with angular 2.
For example, i implemented crud functionality with spring boot.
i set the attribute quantite not empty with annotation #notEmpty(message="the quantite field should not be empty").
In the form, if the quantite field is empty and when i click on submit button, i want that spring validates the inputs.
Produit.class
public class Produit implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long id;
private String designation;
private double prix;
#NotEmpty(message="the quantite field should not be empty")
private int quantite;
...
ProduitRestService.class
#RequestMapping(value="/produits/{id}",method=RequestMethod.PUT)
public Produit update(#RequestBody #valid Produit p,#PathVariable Long id)
{
p.setId(id); // ??????
return produitRepository.saveAndFlush(p);
}
angular 2
add.component.html:
<form #addForm="ngForm" (ngSubmit)="onSubmit(addForm.value)" >
<div class="md-form">
<input type="text" id="form4" class="form-control" name="des" [(ngModel)]="des" >
<label for="form4">designation!!!!!</label>
</div>
<div class="md-form">
<input type="number" id="form4" class="form-control" name="prix" [(ngModel)]="prix" >
<label for="form4">prix</label>
</div>
<div class="md-form">
<input type="number" id="form4" class="form-control" #quantiteref="ngModel" name="quantite" [(ngModel)]="quantite" >
<label for="form4">quantité</label>
<div [hidden]="quantiteref.valid" class="alert alert danger" > this field must not be empty</div> // i know this validation in angular 2, but i need the work to be in spring dev
</div>
<div class="text-center">
<button class="btn btn-deep-purple" (click)="addProduct()" >ADD</button>
</div>
</form>
You can add a BindingResult object as a parameter of your update method.
Thus, you'll be able to check if there is any error like this :
public Produit update(#RequestBody #Valid Produit p, BindingResult result, #PathVariable Long id) {
if (result.hasErrors()) {
// handle error
} else {
// good to go
}
}

The server encountered an internal error that prevented it from fulfilling this request

I'm doing an application using Spring MVC and I have a problem when I try to register an bank account to a specific person in my application. In this case, one Person has many accounts:
There are two classes in this relationship:
Sumarizing:
#Entity
public class Pessoa {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private int idPessoa;
#OneToMany(mappedBy = "pessoa", targetEntity = ContaCorretora.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<ContaCorretora> contaCorretora;
#Entity
public class ContaCorretora {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private int idConta;
private TipoConta tipoConta;
private TipoRisco tipoRisco;
private String login;
private String senha;
private BigDecimal valorAtual;
#ManyToOne
#JoinColumn(name="idPessoa")
private Pessoa pessoa;
Controller Class:
#RequestMapping("/pessoa")
#Controller
public class ContaCorretoraController {
#Autowired
private ContaCorretoraDAO contaCorretoraDao;
#Autowired
private PessoaDAO pessoaDao;
#RequestMapping("/pessoacorretora/{id}")
public ModelAndView pessoaCorretora(#PathVariable("id") int id, ContaCorretora contaCorretora ) {
contaCorretora = new ContaCorretora();
Map<String, Object> model = new HashMap<String, Object>();
Pessoa pessoa = pessoaDao.find(id);
model.put("contaCorretora", contaCorretora);
model.put("pessoa", pessoa);
model.put("tipoConta", TipoConta.values());
model.put("tipoRisco", TipoRisco.values());
return new ModelAndView("pessoa/contacorretora", "model", model);
}
#RequestMapping(value="/pessoacorretora/finalizar", method=RequestMethod.POST)
public ModelAndView gravar(ContaCorretora contaCorretora) {
contaCorretoraDao.gravar(contaCorretora);
return new ModelAndView("redirect:pessoa/contacorretora");
}
I really don't know if the controller class is correct, but probably the problem is there. Nevertheless, I'll paste the JSP code as well:
<form:form action="${s:mvcUrl('CCC#gravar').build() }" method="post" commandName="pessoa" enctype="multipart/form-data" >
<div class="form-group" >
<label>Conta</label>
<select name="tipoConta">
<c:forEach items="${model.tipoConta}" var="tipoConta">
<option value=${tipoConta}>${tipoConta}</option>
</c:forEach>
</select>
</div>
<div class="form-group" >
<label>Risco</label>
<select name="tipoRisco">
<c:forEach items="${model.tipoRisco}" var="tipoRisco">
<option value=${tipoRisco}>${tipoRisco}</option>
</c:forEach>
</select>
</div>
<div class="form-group">
<label>Login</label>
<form:input path="login" cssClass="form-control" />
</div>
<div class="form-group">
<label>Senha</label>
<form:input path="senha" cssClass="form-control" />
</div>
<div class="form-group">
<label>Valor Atual</label>
<form:input path="valorAtual" cssClass="form-control" />
</div>
<button type="submit" class="btn btn-primary">Cadastrar</button>
</form:form>
When I try to open the website (..../pessoa/pessoacorretora/6) - 6 is a valid ID, this is the error:
HTTP Status 500 - java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'pessoa' available as request attribute
type Exception report
message java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'pessoa' available as request attribute
description The server encountered an internal error that prevented it from fulfilling this request.
Actually I really don't know how to handle with a relationship of two classes when I want to do CRUD actions.
The problem is that spring can't bind the commandName="pessoa" in your JSP form.
Are you sure that the value of Pessoa returnd by :
Pessoa pessoa = pessoaDao.find(id); // is not Null ??
try this as a test :
model.put("pessoa", pessoa == null ? new Pessoa() : pessoa );
another way to solve this is to add it through Model Attribute annotation on you controller:
#ModelAttribute("pessoa ")
public Pessoa defaultInstance() {
return new Pessoa();
}

Send object in JSP as foreign key using Spring MVC and Hibernate

I want to create a bank account register related to a specific Person in a OneToMany relationship.
I have the clas Pessoa (Person):
#Entity
public class Pessoa {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private int idPessoa;
private String nome;
#OneToMany(mappedBy = "pessoa", targetEntity = ContaCorretora.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<ContaCorretora> contaCorretora;
...and the class ContaCorretora (Bank account):
#Entity
public class ContaCorretora {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private int idConta;
private TipoConta tipoConta;
private TipoRisco tipoRisco;
private String login;
private String senha;
private BigDecimal valorAtual;
#ManyToOne
#JoinColumn(name="idPessoa")
private Pessoa pessoa;
I'm using this method in Controller for start the process of registration:
#RequestMapping(value = "pessoacorretora/{id}")
public ModelAndView pessoaCorretora(#PathVariable("id") int id, ContaCorretora contaCorretora ) {
Map<String, Object> model = new HashMap<String, Object>();
Pessoa pessoa = pessoaDao.find(id);
model.put("pessoa", pessoa);
model.put("tipoConta", TipoConta.values());
model.put("tipoRisco", TipoRisco.values());
return new ModelAndView("corretora/contacorretora", "model", model);
}
Sumarizining, I have a specific page for recording bank accounts. So, I created this form:
<form:form action="${s:mvcUrl('CC#gravar').build() }" method="post" commandName="contaCorretora" enctype="multipart/form-data" >
<div class="form-group" >
<label>Conta</label>
<select name="tipoConta">
<c:forEach items="${model.tipoConta}" var="tipoConta">
<option value=${tipoConta}>${tipoConta}</option>
</c:forEach>
</select>
</div>
<div class="form-group" >
<label>Risco</label>
<select name="tipoRisco">
<c:forEach items="${model.tipoRisco}" var="tipoRisco">
<option value=${tipoRisco}>${tipoRisco}</option>
</c:forEach>
</select>
</div>
<div class="form-group">
<label>Login</label>
<form:input path="login" cssClass="form-control" />
</div>
<div class="form-group">
<label>Senha</label>
<form:input path="senha" cssClass="form-control" />
</div>
<div class="form-group">
<label>Valor Atual</label>
<form:input path="valorAtual" cssClass="form-control" />
</div>
<form:hidden path="pessoa" cssClass="form-control" value="${pessoa}"/>
<button type="submit" class="btn btn-primary">Cadastrar</button>
</form:form>
When I use the form in this way, I receive the error "description The request sent by the client was syntactically incorrect." I figured out that the problem is in this line, because when I delete, the form post ok:
<form:hidden path="pessoa" cssClass="form-control" value="${pessoa}"/>
Nevertheless, if I delete this line, the program doesn't save the idPessoa as a foreign key, this field is null. I would like to know how to pass an entire object in my JSP form. The post method is:
#RequestMapping(method=RequestMethod.POST)
public ModelAndView gravar(ContaCorretora contaCorretora) {
contaCorretoraDao.gravar(contaCorretora);
return new ModelAndView("pessoa/listageral");
}
all the DAO's methods are okay.
You only need to send the primary key of pessoa to the form.
Change the form attribute
<form:hidden path="pessoa.idPessoa" cssClass="form-control" value="${model.pessoa.idPessoa}"/>
Before persisting the ContaCorretora, make sure you get the Pessoa object from db.
#RequestMapping(method=RequestMethod.POST)
public ModelAndView gravar(ContaCorretora contaCorretora) {
contaCorretora.setPessoa(pessoaDao.find(contaCorretora.getPessoa().getIdPessoa()));
//I escaped null check and not found exceptions, you should apply some logic to take care of that
contaCorretoraDao.gravar(contaCorretora);
return new ModelAndView("pessoa/listageral");
}
Using Entities as form model is not a good approach. Persistance layer should not be on the MVC layer.
In order to pass Java object from your Controller
#RequestMapping(method=RequestMethod.POST)
public ModelAndView gravar(ContaCorretora contaCorretora) {
ModelAndView mav = new ModelAndView("pessoa/listageral");
// retrieve object from DAO
Object myObj = Dao.find(id);
// Put object into model map
mav.addObject("myObj", myObj);
// return model and view
return mav;
}
In JSP you can refer to object using ExpressionLanguage syntax
${myObj}

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}" />

Categories