I have one JSP in spring project. I used to get the All the employee details using data table by Ajax. But i got exception while loading the page. Here is my JSP, model and controller method. Correct my mistake.
<%# page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%# page isELIgnored="false" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>User and Employee Management</title>
// Required script and Css link
</head>
<body>
<div class="generic-container" style="width:97%; height:95%;">
<%#include file="authheader.jsp" %>
<div class="panel panel-default">
<!-- Default panel contents -->
<div class="panel-heading"><span class="lead">All Employees</span>
</div>
</div>
<div class="panel-heading"><span class="lead">Employee Details </span>
</div>
<div style="height:70%;overflow:auto;">
<table class="table table-hover" style="overflow-x:auto" id="example">
<thead>
<tr>
<th>Employee Reference Id</th>
<th>Employee Name</th>
<th>Employee Designation</th>
<th>Employee Salary</th>
<th>Address</th>
</tr>
</thead>
<tbody>
</div>
</body>
<script type="text/javascript">
$(document).ready(
function() {
$("#example").DataTable({
scrollY: 280,
scrollCollapse: true,
paging: true,
"sAjaxSource" : "getEmployees",
"aoColumns" : [
{
"mData" : "employeeReferenceId"
},
{
"mData" : "employeeName"
},
{
"mData" : "employeeDesg"
},
{
"mData" : "salary"
},{
"mData" : "address.address"
}
]
});
});
</script>
Model: Employee
#Entity
#Table(name = "Employee")
public class Employee implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name = "EMPLOYEE_ID")
private int id;
#NotEmpty
#Column(name = "EMPLOYEE_NAME")
private String employeeName;
#NotEmpty
#Column(name = "EMPLOYEE_DESG")
private String employeeDesg;
#NotEmpty
#Column(name = "SALARY")
private String salary;
#NotEmpty
#Column(name = "EMPLOYEE_REFERENCE_ID")
private String employeeReferenceId;
#OneToOne(mappedBy="employee", cascade = CascadeType.ALL)
private Address address;
//Getters and Setters
}
Model: Address
#Entity
#Table(name = "ADDRESS")
public class Address {
#Id
#Column(name="ADDRESS_ID")
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="emp_id",insertable = false, updatable = false)
private int employeeId;
#NotNull
#Column(name = "ADDRESS")
private String address;
#OneToOne(fetch=FetchType.EAGER , cascade=CascadeType.ALL, orphanRemoval=true)
#JoinColumn(name="emp_id",referencedColumnName="employee_id")
private Employee employee;
//Getters and Setters
}
And controller method is
#RequestMapping(value = { "/getEmployees" })
public #ResponseBody Map<String, Object> getEmployees(ModelMap model) {
Map<String, Object> data = new HashMap<String, Object>();
List<Employee> employees=employeeService.findAllEmployees();
data.put("data", employees);
return data;
}
And the Error is
Apr 13, 2017 5:58:25 PM
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
handleHttpMessageNotWritable
WARNING: Failed to write HTTP message:
org.springframework.http.converter.HttpMessageNotWritableException: Could
not write content: failed to lazily initialize a collection of role
Reason why getting this exception is entity configuration. Because the JSON is mapping the parent entity with child entity. Since you have configured the child entity with the relation parent entity. Hence, you are getting nested exception.
Employee --> Address (Again Employee configured in Child entity). Can ignore this issue with the following annotation in Address object.
#JSONIgnore
#JoinColumn(name="emp_id",referencedColumnName="employee_id")
private Employee employee;
#JSONIgnore annotation will prevent the nested exception when returning JSON Object.
Related
I need to complete the registration form on SpringBoot. To achieve this I created 2 classes : User and Credentials, the 2nd handles unique username and password.
#Getter
#Setter
#Entity
#Table(name = "users")
public class User {
public User() {}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String username;
}
public class Credentials {
public static final String DEFAULT_ROLE = "DEFAULT";
public static final String ADMIN_ROLE = "ADMIN";
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Getter
#Column(nullable = false, unique = true)
private String username;
#Getter
#Column(nullable = false)
private String password;
#Getter
#Setter
#Column(nullable = false)
private String role;
#OneToOne(cascade = CascadeType.ALL)
private User user;
}
This is registrationController (handles "/registration" requests) :
#Controller
public class RegController {
#GetMapping("/register")
public String register(Model model){
model.addAttribute("user", new User());
model.addAttribute("credentials", new Credentials());
return "register";
}
}
Now it should be all set, ready to read data from html form and register new users using thymeleaf.
This is registration form inside registration.html, my goal is to read username and password then create a new user and save him on Postgres :
<body>
<div class="login">
<form id="login" method="POST" th:action="#{/register}">
<label><b>User Name
</b>
</label>
<input type="text" name="Uname" id="Uname" placeholder="Username" required th:field="${credentials.username}">
<br><br>
<label><b>Password
</b>
</label>
<input type="Password" name="Pass" id="Pass" placeholder="Password" required th:field="${credentials.password}">
<br><br>
<label><b>Repeat Password
</b>
</label>
<input type="Password" name="RPass" id="RPass" placeholder="Password">
<br><br>
<button type="submit" class="btn btn-primary" id="log">Registrati</button>
<div style = "background-color:green">
<a id= "link" th:href="#{/login}" >or login</a>
</div>
</form>
</div>
</body>
But when I navigate to registration.html this is the error from TomCat :
Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException:
An error happened during template parsing (template: "class path resource [templates/register.html]")
What I noticed is that if I remove all the th:field (used to get user input) the page is shown without error.
I noticed that your Credentials class has only getters for username and password. If Thymeleaf has to fill them with the user input, shouldn't you provide setters too?
#Getter
#Setter
#Column(nullable = false, unique = true)
private String username;
#Getter
#Setter
#Column(nullable = false)
private String password;
public class Customer {
#Id
#GeneratedValue
private Integer id;
private String email;
private Long Apprvamount;
#JsonIgnore
#OneToMany(mappedBy="customer", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<MyTransaction> transactions;
#Transient
private Long rewardPoints;
public Long getRewardPoints() {
function to calculate rewardPoints;
}
Contoller adding model attribute
#GetMapping("/customers/{id}")
public String getCustomer(#PathVariable Integer id,Model model) throws RecordNotFoundException {
Customer customer = rewardsService.getCustomerById(id);
model.addAttribute("customer", customer);
return "profile";
}
Thymeleaf
<body>
<div class="card-body">
<h2 th:text="${customer.getEmail()}"></h2>
<p th:text="${customer.getApprvamount()}"></p>
<p th:text="${customer.getRewardPoints()}"></p>
<p class="my-5">
<a href="/{id}(id=${customer.getId()})/emi" class="btn btn-primary">
<i> All</i></a>
</p>
Its sometime throwing null error for getRewardPoints its working for email and approvamount.And url is not getting calculated.Getters and setters are present.What is wrong with the approach?
You may have misspelt customer:
model.addAttribute("costumer", customer);
I have a Spring Boot application that needs adds a post to a feed list. A post is written by a user and consists of a content and several attachments. The database has 3 tables: post, attachment and user.
The main class of the application is:
#SpringBootApplication
public class SocialMediaApplication {
public static void main(String[] args) {
SpringApplication.run(SocialMediaApplication.class, args);
}
}
The entities are the following:
Post.java
#Entity
public class Post implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable = false)
private String content;
#ManyToOne
#JoinColumn(name = "user_id")
private User user;
#Column(nullable = false)
private Timestamp createdAt;
#Column
private String location;
#OneToMany(mappedBy = "post", cascade = CascadeType.ALL)
private List<Attachment> attachmentList;
#OneToMany(mappedBy = "post", cascade = CascadeType.ALL)
private List<Rating> ratingList;
public Post() {
}
public Post(String content, User user, Timestamp createdAt, String location, List<Attachment> attachmentList, List<Rating> ratingList) {
super();
this.content = content;
this.user = user;
this.createdAt = createdAt;
this.location = location;
this.attachmentList = attachmentList;
this.ratingList = ratingList;
}
// ...
}
Attachment.java
#Entity
public class Attachment implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Lob
#Column(length = 100_000, nullable = false)
private byte[] content;
#ManyToOne
#JoinColumn(name = "post_id")
private Post post;
public Attachment() {
}
public Attachment(byte[] content, Post post) {
super();
this.content = content;
this.post = post;
}
// ...
}
User.java
#Entity
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long id;
#Column(nullable = false)
private String firstName;
#Column(nullable = false)
private String lastName;
#Column(nullable = false)
private Date dateOfBirth;
#Column(nullable = false)
private String credential;
#Column(nullable = false)
private String password;
#Column
private String location;
#Lob
#Column(length = 100_000)
private byte[] photo;
#Column
private String motto;
public User() {
}
public User(String firstName, String lastName, Date dateOfBirth, String credential, String password,
String location, byte[] photo, String motto) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.dateOfBirth = dateOfBirth;
this.credential = credential;
this.password = password;
this.location = location;
this.photo = photo;
this.motto = motto;
}
// ...
}
All repositories extend CrudRepository and are annotated with #Transactional:
PostRepository.java
#Transactional
public interface PostRepository extends CrudRepository<Post, Long> {
}
AttachmentRepository.java
#Transactional
public interface AttachmentRepository extends CrudRepository<Attachment, Long> {
}
UserRepository.java
#Transactional
public interface UserRepository extends CrudRepository<User, Long> {
}
The controller that should add a post to the feed is the following:
#Controller
#RequestMapping("/post")
public class PostController {
#Autowired
PostRepository postRepository;
#GetMapping("/add")
public String greetingForm(Model model) {
model.addAttribute("post", new Post());
return "addPost";
}
#PostMapping("/add")
public String addPost(#ModelAttribute Post post, #RequestParam("attachment") MultipartFile uploadingFile) throws IOException {
User user = new User();
user.setId(1L);
post.setUser(user);
post.setCreatedAt(Timestamp.valueOf(LocalDateTime.now()));
List<Attachment> attachmentList = new ArrayList<>();
Attachment attachment = new Attachment();
attachment.setContent(uploadingFile.getBytes());
attachment.setPost(post);
attachmentList.add(attachment);
post.setAttachmentList(attachmentList);
List<Rating> ratingList = new ArrayList<>();
post.setRatingList(ratingList);
postRepository.save(post);
return "allPosts";
}
}
The addPost.html page has the following content:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Add Post</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>Add Post</h1>
<form action="#" th:action="#{/post/add}" th:object="${post}" method="post" enctype="multipart/form-data">
<table border="0">
<tr>
<td>Content</td>
<td><textarea id="content" th:field="*{content}" rows="5" cols="50"></textarea></td>
</tr>
<tr>
<td>Location</td>
<td><input type="text" id="location" th:field="*{location}"/></td>
</tr>
<tr>
<td>Attachment</td>
<td><input type="file" id="attachment" name="attachment"/></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Submit" />
<input type="reset" value="Reset" />
</td>
</tr>
</table>
</form>
</body>
</html>
The application.properties file has the following content:
spring.datasource.url=jdbc:mysql://localhost:3306/****?useSSL=false
spring.datasource.username=root
spring.datasource.password=****
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.id.new_generator_mappings=false
spring.jpa.show-sql=true
spring.thymeleaf.cache=false
spring.thymeleaf.enabled=true
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
However, when I press the submit button, nothing is persisted into the database, although the queries are being displayed in the console:
Hibernate: insert into post (content, created_at, location, user_id) values (?, ?, ?, ?)
Hibernate: insert into attachment (content, post_id) values (?, ?)
What could be the cause?
I have a question to ask:
I have to tables user and user_login joined OneToOne by user.id -> user_login.user_id.
The issue is when I do .updateObject(user) I get 2 queries executed:
Hibernate: insert into User (created, modified, email, first_name,
last_name) values (?, ?, ?, ?, ?) Hibernate: insert into user_login
(created, modified, password, user_id) values (?, ?, ?, ?) [2012-08-15
12:15:04,192] [ERROR] [http-bio-8080-exec-1] SqlExceptionHelper [144]:
Column 'user_id' cannot be null
and looks like there is no reference between 2 objects. If into the Entity User, method setUserLogin I add line
userLogin.setUser(this); its working but I dont find this way elegant honestly. Is there anything I missed in entity configuration
maybe that does not do that automatically ?
Thank you
Here are my Entities
#Entity
#NamedQueries({ #NamedQuery(name = "user.list", query = "select u from User u") })
public class User implements java.io.Serializable {
#Column(name = "first_name", nullable = true)
private String firstName;
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name="user_id", nullable=false)
private UserLogin userLogin;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public UserLogin getUserLogin() {
return userLogin;
}
public void setUserLogin(UserLogin userLogin) {
this.userLogin = userLogin;
//userLogin.setUser(this); THIS IS THE LINE THAT FIXES IT, BUT I DONT FIND THIS WAY ELEGANT
}
}
#Entity
#Table(name="user_login")
public class UserLogin implements java.io.Serializable {
#Column(name = "password", nullable = false)
private String password;
#OneToOne(optional = false, fetch = FetchType.LAZY)
private User user;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
JSP File:
<%# taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<html>
<head>
<title>Registration Page</title>
</head>
<body>
<form:form action="/test" commandName="user">
<tr>
<td>User Name :</td>
<td><form:input path="firstName" /></td>
</tr>
<tr>
<td>Password :</td>
<td><form:input path="userLogin.password" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Register"></td>
</tr>
</table>
</form:form>
</body>
</html>
Spring Controller:
#Controller(value = "/")
public class Test {
#Autowired
UserServiceImpl userServiceImpl;
#RequestMapping(method = RequestMethod.GET, value = "/test")
public void test(ModelMap model) {
model.addAttribute("user", new User());
}
#RequestMapping(method = RequestMethod.POST, value = "/test")
public void test(User user) {
userServiceImpl.update(user);
}
}
As usual, bidirectional relationships do have owning side. Owning side of relationship is attribute that is referenced by mappedBy. In your case attribute user in UserLogin entity is the owning side.
When relationship is persisted to the database, only owning side is consulted. This means, that you have to set value for user attribute to be able to persist. To keep also entity graph in memory consistent both sides of the relationship should be set.
In JPA 2.0 specification this is told with following words:
Bidirectional relationships between managed entities will be persisted
based on references held by the owning side of the relationship. It is
the developer’s responsibility to keep the in-memory references held
on the owning side and those held on the inverse side consistent with
each other when they change.
I'm trying to save Account object in the hibernate .please find the following code.
#RequestMapping(value = "/saveAccount", method = RequestMethod.POST)
public ModelAndView saveAccount(#ModelAttribute("account") Account account,
BindingResult result) {
Session session = sessionFactory.openSession();
System.out.println(account.getFirstName());
System.out.println(account.getLastName());
System.out.println(account.getSubject());
System.out.println(account.getCity().getCityName());
session.save(account);
return new ModelAndView("redirect:/form.html");
}
My jsp page have a form with First Name,Last Name ,city and subject fields.
I'm getting city dropdown fromatabase.
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib
prefix="c"
uri="http://java.sun.com/jsp/jstl/core"
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h3>Contact Form</h3>
<div class="container">
<form method="post" action="/sdnext/saveAccount.html">
<label for="fname">First Name</label>
<input type="text" id="fname" name="firstName" placeholder="Your name..">
<label for="lname">Last Name</label>
<input type="text" id="lname" name="lastName" placeholder="Your last name..">
<label for="country">City</label>
<select name="city" id="cityName" >
<c:forEach var="cityname" items="${lists}">
<option value="${cityname.cityName}">${cityname.cityName}</option>
</c:forEach>
</select>
<label for="subject">Subject</label>
<textarea id="subject" name="subject" placeholder="Write something.." style="height:200px"></textarea>
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>
DataBase bean classes are here
package test.*;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name= "Account")
public class Account implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String lastName) {
LastName = lastName;
}
public City getCity() {
return city;
}
public void setCity(City city) {
this.city = city;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
private String firstName;
private String LastName;
#OneToOne
private City city;
private String subject;
}
package test.*;
#Entity
#Table(name= "City")
public class City implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
private String cityName;
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
}
I have used one to one mapping to city object.But i'm not able to save city object in database,rest all firstNme,LastName and subjects are getting saved.its showing in network console,but data is not getting saved in database.Please help me fix this.Thanking you..
By creating the dto we can persists the values selected from the dropdown.and its working for me .
<option value="${cityname}">${cityname.cityName}</option>
The problem is you are sending cityname.cityName (String) which cannot be mapped to City object so,
send the complete city object as the value. Hibernate will take care of mapping.