Post method and String value in Java Spring - java

I'm trying to post a text from home.html template
<form th:action="#{/process_addText}" th:object="${textzz}" method="post" >
<input type="text" th:field="*{text}" />
<button type="submit" class="btn btn-info">Add</button>
</form>
and here is my controller
#PostMapping("/process_addText")
public String processAddText(Text text1) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String name = auth.getName();
User myUser=userRepo.findByEmail(name);
text1.setUser(myUser);
textRepo.save(text1);
return "redirect:/home";
}
#GetMapping("/home")
public String mySuccess(Model model) {
model.addAttribute("textzz",new Text());
LOGGER.info("verif==="+model.toString());
return "home";
}
And it's my Text class:
#Entity
#Table(name = "texts")
public class Text {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idText;
#OneToOne
#JoinColumn(name = "id", referencedColumnName = "id")
private User user;
private String text;
}
when I'm trying to post the "text" value from home.html,I'm getting this error:
WARN 680 --- [nio-8088-exec-7]
.w.s.m.s.DefaultHandlerExceptionResolver : Resolved
[org.springframework.beans.TypeMismatchException: Failed to convert
value of type 'java.lang.String' to required type
'com.myblog.app.model.Text'; nested exception is
org.springframework.core.convert.ConversionFailedException: Failed to
convert from type [java.lang.String] to type [java.lang.Long] for
value 'qvefd'; nested exception is java.lang.NumberFormatException:
For input string: "qvefd"]
I have no idea why I'm getting this, because the types are correct
Update: When I remove the input and I post(without text) in my DB I get correct rows(for text id and User's foreign key), of course with text value=NULL. So the problem is in type of input, maybe.

Your controller method accepts a Text entity but your frontend form sends with post request only a simple String in the body of the request.
Then Spring can not transform that String into a Text object.
So your controller method should be
#PostMapping("/process_addText")
public String processAddText(String text) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String name = auth.getName();
User myUser=userRepo.findByEmail(name);
Text text1 = textRepo.findByUser(myUser);
if (text1 == null){
text1 = new Text();
text1.setUser(myUser);
}
text1.setText(text);
textRepo.save(text1);
return "redirect:/home";
}

Related

thymeleaf and spring boot form exception

I'm trying to add data to my database and reload the same page using spring boot and thymeleaf but when I save data I face this error
org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'org.closure.gcp.entities.QuestionEntity'; nested exception
is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.lang.Integer] for value 'adsf'; nested exception is java.lang.NumberFormatException: For input string: "adsf"
controller code :
#Controller
#RequestMapping(path = "/Questions")
public class QuestionView {
#Autowired
QuestionRepo questionRepo;
#RequestMapping(path = "/")
public String index(#ModelAttribute("question") QuestionEntity question, Model model)
{
List<QuestionEntity> list = questionRepo.findAll();
model.addAttribute("questions", list);
return "Questions";
}
#RequestMapping(value="/add", method=RequestMethod.POST)
public String addQuestion(Model model,#ModelAttribute("question") QuestionEntity question) {
questionRepo.save((QuestionEntity)model.getAttribute("question"));
List<QuestionEntity> list = questionRepo.findAll();
model.addAttribute("questions", list);
return "Questions";
}
}
thymeleaf page :
<html>
<header>
<title>Questions</title>
</header>
<body>
<h2>hello questions</h2>
<hr>
<tr th:each="q: ${questions}">
<td th:text="${q.question}"></td>
<br>
<td th:text="${q.question_type}"></td>
<hr>
</tr>
<!-- <form th:action="#{/add}" th:object="${question}" method="post"> -->
<form action="./add" th:object="${question}" method="POST">
<input type="text" th:field="*{question}" />
<br >
<input type="text" th:field="*{question_type}" />
<br >
<input type="submit" value="save" >
</form>
</body>
</html>
#Entity
#Table(name="question")
public class QuestionEntity {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private Integer id;
#Column(nullable=false)
private String question;
#Column(nullable=false)
private String question_type;
#ManyToOne(optional = true)
private InterestEntity interest;
#ManyToOne(optional = true)
private LevelEntity level;
#Column(nullable = true)
private String sup_file;
#Column(nullable = false)
private int pionts;
#ManyToMany
private List<ContestEntity> contest;
#OneToMany(mappedBy ="question")
private List<AnswerEntity> answers;
// getters and setters
}
notice when I try to open another page in "/add" it works
I found this to solve
I just made a model class and use it instead of entity
and I used just one method to handle index and add requests
#Controller
#RequestMapping(path = "/Questions")
public class QuestionView {
#Autowired
QuestionRepo questionRepo;
#RequestMapping(path = {"/",""},method = {RequestMethod.POST,RequestMethod.GET})
public String index(#ModelAttribute("question") QuestionModel question, Model model,HttpServletRequest request)
{
if(request.getMethod().equals("POST"))
{
questionRepo.save(new QuestionEntity().question(question.getQuestion()).question_type(question.getQuestion_type()));
}
List<QuestionEntity> list = questionRepo.findAll();
model.addAttribute("questions", list);
return "Questions";
}
}
It is better to have 2 separate methods, one for GET and one for POST and to use redirect after the POST (see https://en.wikipedia.org/wiki/Post/Redirect/Get). This is how I would code this based on your separate QuestionModel class:
#Controller
#RequestMapping(path = "/Questions")
public class QuestionView {
#Autowired
QuestionRepo questionRepo;
#GetMapping
public String index(Model model)
{
List<QuestionEntity> list = questionRepo.findAll();
model.addAttribute("questions", list);
model.addAttribute("question", new QuestionModel());
return "Questions";
}
#PostMapping("/add")
public String addQuestion(#Valid #ModelAttribute("question") QuestionModel question, BindingResult bindingResult, Model model) {
if(bindingResult.hasErrors()) {
return "Questions";
}
questionRepo.save(new QuestionEntity().question(question.getQuestion()).question_type(question.getQuestion_type()));
return "redirect:/Questions";
}
}
Main points:
Use separate methods for GET and POST
Add the #Valid annotation to the #ModelAttribute in the POST method so any validation annotations on QuestionModel are checked (Because you probably want to make sure the question has at least some text in it for example).
Use BindingResult as parameter to check if there are validation errors.
Use "redirect:" to force a new GET after the POST to help avoid double submissions if a user would refresh the browser.

How to post a Form data from Client side to server using RestTemplate?

For client side i used tomcat 8080 port and for server side i used tomcat 8081 port. I just tried to post Form data to server side using RestTemplate. Is there is any specific way to doing this?
And i tried to do this as follows,
{ #RequestMapping(value="/addBook")
public String addBook(Book book){
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
ResponseEntity<Book> response = restTemplate.postForEntity(
"http://localhost:8081/api/addbook", book, Book.class);
System.out.println(response.getBody());
return "Home";}
this is my form,
<h1>Form</h1>
<form action="addBook">
<input type="text" name="name"><br>
<input type="text" name="author"><br>
<input type="text" name="stock"><br>
<input type="submit" ><br>
</form>
And this is my Book class,
package com.example.libraryfrontend.entity;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#JsonIgnoreProperties(ignoreUnknown = true)
public class Book {
private String name;
private String author;
private Integer stock;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Integer getStock() {
return stock;
}
public void setStock(Integer stock) {
this.stock = stock;
}}
and this is error i faced,
> Error while extracting response for type [class com.example.libraryfrontend.entity.Book] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized token 'Book': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Book': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false') at [Source: (PushbackInputStream); line: 1, column: 6]
org.springframework.web.client.RestClientException: Error while extracting response for type [class com.example.libraryfrontend.entity.Book] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized token 'Book': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Book': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')...
Can anyone help me for this or is there any special way to send form data to saver side?

I'm entering String in a form but getting java.lang.NumberFormatException : SpringBoot hibernate Java app

I need help with this. I've spent 2 hrs and can't find anything.
The problem: I'm entering Text in Skill and Proficiency field in an html form. The model takes String. But I get the error saying failed to convert to number.
This is the error I'm getting:
Failed to bind request element:
org.springframework.beans.TypeMismatchException: Failed to convert value of
type 'java.lang.String' to required type 'com.byAJ.persistence.models.Skills';
nested exception is
org.springframework.core.convert.ConversionFailedException: Failed to convert
from type [java.lang.String] to type [java.lang.Long] for value 'Designing
engines'; nested exception is java.lang.NumberFormatException: For input
string: "Designingengines"
2017-07-09 15:48:57.233 WARN 16312 --- [nio-8080-exec-9]
.w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by
Handler execution: org.springframework.beans.TypeMismatchException: Failed to
convert value of type 'java.lang.String' to required type
'com.byAJ.persistence.models.Skills'; nested exception is
org.springframework.core.convert.ConversionFailedException: Failed to convert
from type [java.lang.String] to type [java.lang.Long] for value 'Designing
engines'; nested exception is java.lang.NumberFormatException: For input
string: "Designingengines"
HTML Page:
<form autocomplete="off" action="#" th:action="#{/skill}"
th:object="${skill}" method="post">
<div class="form-group">
<!-- <label for="degree">Degree <mark><strong><span th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}">First Name Error</span></strong></mark></label>-->
<label for="skill">Skill<mark><strong><span th:if="${#fields.hasErrors('skill')}" th:errors="*{skill}">can't be empty</span></strong></mark></label>
<input type="text" class="form-control" id="skill" placeholder="Engineer" th:field="*{skill}" />
</div>
<div class="form-group">
<label for="proficiency">Proficiency( Beginner, Proficient, Expert) <mark><strong><span th:if="${#fields.hasErrors('proficiency')}" th:errors="*{proficiency}"> can't be empty</span></strong></mark></label>
<input type="text" class="form-control" id="proficiency" placeholder="Expert" th:field="*{proficiency}" />
</div>
<div class="form-group">
<p>Enter More Skills?</p>
<input type="radio" name="yesOrNo" value="yes"> Yes
<input type="radio" name="yesOrNo" value="no" checked> No
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
Skill Controllers:
#RequestMapping(value="/skill", method = RequestMethod.GET)
public String getSkill(Model model)
{
model.addAttribute("skill", new Skills());
return "skillForm";
}
#RequestMapping(value="/skill", method = RequestMethod.POST)
public String processSkil(#Valid #ModelAttribute("skill") Skills skill, BindingResult result, Model model, #RequestParam("yesOrNo") String yesNo){
System.out.println("helo");
System.out.println(result.toString());
if (result.hasErrors()) {
return "skillForm";
} else {
skill.setUsername(userService.getUserDetails().getUsername());
userService.saveSkill(skill);
}
if( yesNo.equals("yes")){
return "redirect:/skill";
}
return "myResume";
}
Skill Model:
#Entity
public class Skills {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#NotEmpty
private String skill, proficiency;
private String username;
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
public String getProficiency() {
return proficiency;
}
public void setProficiency(String proficiency) {
this.proficiency = proficiency;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public long getId() {
return id;
}
}
Finally Skill Repository CRUD:
import com.byAJ.persistence.models.Skills;
import org.springframework.data.repository.CrudRepository;
public interface SkillRepository extends CrudRepository<Skills, Long>{
}
Any tip is greatly appreciated. Thanks!
UPDATE: When I try entering a number in the skill field, I don't get any error and the value gerts stored in the databse. This is really confusing, as I don't have field that's expecting integer for those values.
I noticed that I had the same name for Object and field and mapping. So I changed them to different names and Now the program is working.

Hibernate exception when trying to connect users - Field 'username' doesn't have a default value

I am trying to allow a user to follow another user but I am getting an error every time. When I insert it via SQL in my database it works, so it is the Java side that I am getting an error on. Here is my code:
#Id
#GeneratedValue
private int id;
#Column(name = "roomie_username")
private String roomie_username;
#ManyToOne(optional=false)
#JoinColumn(name = "username", referencedColumnName="username", insertable=false, updatable=false)
private User user;
public Roomie() {
this.user = new User();
}
public Roomie(int id, String roomie_username, User user) {
super();
this.id = id;
this.roomie_username = roomie_username;
this.user = user;
}
My controller:
#RequestMapping("/user/{username}")
public String showUser(#PathVariable String username, Model model,
Principal principal) {
User user = usersService.getUser(username);
model.addAttribute("user", user);
Roomie roomie = new Roomie();
roomie.setRoomie_username(username);
model.addAttribute("roomie", roomie);
List<Roomie> roomies = roomieService.getRoomies(username);
model.addAttribute("roomies", roomies);
return "user";
}
#RequestMapping(value = "/addRoomie", method = RequestMethod.POST)
public String addRoomie(Principal principal,
#Validated(value = FormValidationGroup.class) Roomie roomie)
throws IOException {
String currentUsername = principal.getName();
if (currentUsername.equals(roomie.getRoomie_username())) {
return "cannotadd";
}
else {
roomie.getUser().setUsername(currentUsername);
if(roomieService.exists(roomie.getRoomie_username(), currentUsername)) {
return "cannotadd";
} else {
roomieService.saveOrUpdate(roomie);
return "roomieadded";
}
}
In my JSP where I'm actually trying to add the roomie:
<sf:form id="details" method="post"
action="${pageContext.request.contextPath}/addRoomie"
commandName="roomie">
<sf:input type="hidden" name="roomie_username"
path="roomie_username" />
<input class="btn btn-default" class="control"
value="Connect to user" type="submit" />
</sf:form>
My database structure:
DB
This is my error:
org.springframework.orm.hibernate3.HibernateJdbcException: JDBC
exception on Hibernate data access: SQLException for SQL [insert into
roomie (roomie_username) values (?)]; SQL state [HY000]; error code
[1364]; could not insert: [com.spring.web.dao.Roomie]; nested
exception is org.hibernate.exception.GenericJDBCException: could not
insert: [com.spring.web.dao.Roomie]
If anyone could help that would be greatly appreciated as I have been stuck on this for a long time.
We can enable the logging in hibernate layer to see the actual input passed to queries. Please refer the URL https://docs.jboss.org/hibernate/orm/3.5/reference/en/html/session-configuration.html. Either you can configure by log4j properties or hibernate XML. It will help you to debug any issues

Form data not binding with Spring Controller Annotation getting new object after submit

I am not getting form data in spring controller after submitting the form below is my code
#RequestMapping(value = "category/addCategory.htm" , method = RequestMethod.GET)
public String add(Model model) {
if (log.isDebugEnabled()){
log.debug("Invoking listCategory");
}
model.addAttribute("categoryView", new CategoryView());
return "editCategory";
}
#RequestMapping(value = "category/saveCategory.htm", method = RequestMethod.POST)
public String saveCategory(CategoryView categoryView, Model model, BindingResult result) {
Category category = prepareCategoryFromView(categoryView);
categoryService.save(category);
categoryView.setCategoryId(category.getCategoryId());
model.addAttribute("categoryView",categoryView);
return "editCategory";
}
prepareCategoryFromView is a method which is setting the actual values on Category it's hibernate entity, below categoryView
public class CategoryView {
private long categoryId;
private String image = "";
private int parentId;
private boolean top;
private int column = 1;
private int sortOrder = 1;
private boolean status;
private String description;
private String name;
.
.
other variable and setter and getters
}
and the form is
<sf:form method="post" enctype="multipart/form-data" id="form-category" cssClass="form-horizontal" modelAttribute="categoryView">
<sf:label path="name" cssClass="col-sm-2 control-label">Category Name</sf:label>
<sf:input path="name" id="name" name="name" cssClass="form-control" placeholder="Category Name" />
<sf:hidden path="categoryId" id="categoryId" name="categoryId" />
<sf:hidden path="languageId" id="languageId" name="languageId" />
<sf:label path="description" cssClass="col-sm-2 control-label">Category Name</sf:label>
<sf:textarea path="description" cssClass="form-control" placeholder="Description" id="description"/>
.
.
.
</sf:form>
In above form every time I am getting name and description is null (I think it's creating a new view object without given values in form)
Pls let me know, where I am wrong
Remove the enctype="multipart/form-data" from your form tag and try again (with the method arguments in the correct order). #ModelAttribute is not strictly required since your attribute name matches the class name.
I think #ModelAttribute annotation is missing here on CategoryView object.Because as per your form code it is the model attribute which will bind data to the bean in controller.
Attach it with your method argument like below,then you can check the data is binding to it or not.
#RequestMapping(value = "category/saveCategory.htm", method = RequestMethod.POST)
public String saveCategory(#ModelAttribute("categoryView") CategoryView categoryView, Model model, BindingResult result) {
Category category = prepareCategoryFromView(categoryView);
categoryService.save(category);
categoryView.setCategoryId(category.getCategoryId());
model.addAttribute("categoryView",categoryView);
return "editCategory";
}

Categories