I am new in Spring MVC. I'm stuck for more than 24hrs trying to add a dynamic row using thymeleaf. I followed this link and also the thymeleaf documentation In this tutorial but i have not been able to make it work. Clicking addRow and removeRow doesn't work. Someone should please help me. Thanks
Here is my Controller code:
#Controller
#SessionAttributes("qualification")
public class QualificationController {
private final QualificationService qualificationService;
private final StaffService staffService;
private final CourseService courseService;
#Autowired
public QualificationController(QualificationService qualificationService,
StaffQualificationService service,
StaffService staffService, CourseService courseService) {
this.qualificationService = qualificationService;
this.staffService = staffService;
this.courseService = courseService;
}
#InitBinder
public void setAllowedFields(WebDataBinder dataBinder) {
dataBinder.setDisallowedFields("id");
}
#GetMapping("/staff/{id}/qualification")
public String initForm(#PathVariable("id") Integer id, Model model) {
Staff staff = staffService.findById(id);
staff.addQualification(new StaffQualification());
model.addAttribute("qualification", staff);
model.addAttribute("qualifications", qualificationService.findAll());
model.addAttribute("courses", courseService.findAll());
return "registration/qualification";
}
#PostMapping(path = "/staff/{id}/qualification/new", params = {"save"})
public String addQualification(#ModelAttribute("qualification")
#Valid Staff staff,
BindingResult result, RedirectAttributes attributes,
SessionStatus status) {
if (result.hasErrors()) {
return "registration/qualification";
}
staffService.save(staff);
attributes.addFlashAttribute("successMessage", "Qualification successfully saved");
status.setComplete();
return "registration/qualification";
}
#PostMapping(path = "/staff/{id}/qualification/new", params = {"addRow"})
public String addRow(final Staff staff, BindingResult result) {
staff.getQuals().add(new StaffQualification());
return "registration/qualification";
}
#PostMapping(params = "removeRow", path = {"/staff/{id}/qualification/new"})
public String removeRow(final Staff staff, final BindingResult result,
final HttpServletRequest request) {
final int rowId = Integer.parseInt(request.getParameter("removeRow"));
staff.removeQualification(staff.getQuals().remove(rowId));
return "registration/qualification";
}
}
My entities:
public class Staff extends NamedEntity {
#NotBlank(message = "First Name is blank")
private String firstName;
#NotBlank(message = "Last Name is blank")
private String lastName;
private String middleName;
#Digits(fraction = 0, integer = 10)
#NotBlank(message = "Please fill in your phone number")
private String phoneNumber;
private boolean married;
private String gender;
#Transient
private int age;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "staff", orphanRemoval = true)
private List<StaffQualification> quals = new ArrayList<>();
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "staff", orphanRemoval = true)
private List<Document> documents = new ArrayList<>();
}
public class StaffQualification extends BaseEntity {
private String qualification;
private String course;
private String school;
#NotNull(message = "Date obtained qualification must be in the past")
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private LocalDate qualDate;
#ManyToOne
private Staff staff;
}
Thymeleaf code:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Staff form</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css"
th:href="#{https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css}"
integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
</head>
<body>
<div class="justify-content-start">
<div th:include="fragments/bodyHeader.html"></div>
</div>
<div class="main body-content">
<div class="container">
<form th:object="${qualification}" th:action="#{/staff/{id}/qualification/new}" th:method="post">
<div class="alert alert-info" th:if="${successMessage}" th:utext="${successMessage}"></div>
<fieldset>
<legend class="w-auto" th:text="#{qualification.staff}">Staff Qualifications</legend>
<div>
<table id="items" class="table table-bordered">
<thead>
<tr>
<th th:scope="col">#</th>
<th th:scope="col">Title</th>
<th th:scope="col">Course</th>
<th th:scope="col">School</th>
<th th:scope="col" type="date">Date Obtained</th>
<th>
<button type="submit" name="addRow" th:text="#{qualification.row.add}">Add row</button>
</th>
</tr>
</thead>
<tbody id="tbodyContainer">
<tr th:each="row, rowStat : *{quals}">
<td th:text="${rowStat.count}">1</td>
<td>
<label>
<select th:field="*{quals[__${rowStat.index}__].qualification}">
<option th:each="var : ${qualifications}"
th:value="${var.id}"
th:text="${var.name}">
</option>
</select>
</label>
</td>
<td>
<label>
<select th:field="*{quals[__${rowStat.index}__].course}">
<option th:each="let : ${courses}"
th:value="${let.id}"
th:text="${let.name}">
</option>
</select>
</label>
</td>
<td>
<label>
<input type="text" th:field="*{quals[__${rowStat.index}__].school}"
th:errorClass="fieldError"/>
</label>
</td>
<td>
<label>
<input type="date" th:field="*{quals[__${rowStat.index}__].qualDate}"/>
</label>
</td>
<td>
<button type="submit" name="removeRow" th:value="${rowStat.index}"
th:text="#{qualification.row.remove}">Remove row
</button>
</td>
</tr>
</tbody>
</table>
</div>
<div>
<button class="btn btn-primary" name="save" style="margin-right: 50px" type="submit">Save</button>
</div>
</fieldset>
<div class="form-actions row justify-content-center" style="padding-top:10px; padding-right: 200px">
<a th:if="${qualification.id}" href="/staff/{id}/qualification"
th:href="#{/staff/{id}/qualification/(id=${qualification.id})}"
class="btn btn-primary">Next</a>
</div>
</form>
</div>
</div>
</body>
</html>
Account Controller:
#Controller
#SessionAttributes("account")
public class AccountController {
private final PencomService pencomService;
private final StaffService staffService;
private final BankService bankService;
#Autowired
public AccountController(PencomService pencomService, StaffService staffService,
BankService bankService) {
this.pencomService = pencomService;
this.staffService = staffService;
this.bankService = bankService;
}
#InitBinder
public void setAllowedFields(WebDataBinder dataBinder) {
dataBinder.setDisallowedFields("id");
}
#GetMapping("/staff/{id}/account")
public String initCreationForm(#PathVariable("id") Integer staffId, Model model) {
Staff staff = staffService.findById(staffId);
staff.setBankAccount(new BankAccount());
staff.setPencomAccount(new PencomAccount());
model.addAttribute("account", staff);
model.addAttribute("listBanks", bankService.findAll());
model.addAttribute("listPensions", pencomService.findAll());
return "registration/account";
}
#PostMapping("/staff/{id}/account/new")
public String addAccount(#ModelAttribute("account") #Valid Staff staff,
BindingResult result, RedirectAttributes attributes, SessionStatus status) {
if (result.hasErrors()) {
return "registration/account";
} else {
staffService.save(staff);
attributes.addFlashAttribute("successMessage", "Accounts successfully saved");
status.setComplete();
return "/registration/account";
}
}
}
Error Message:
java.lang.NullPointerException: null
at com.chairmo.cadre.controller.AccountController.initCreationForm(AccountController.java:48) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.36.jar:9.0.36]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Related
This is view to receive the above values.
Press the Submit button at the end of the form tag to send the data.
(id, password, name, phone_number, ssn, city_name, town_name, street_name, zip_code, details)
Used : Mysql, Springboot, java, jpa, html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>signuppage</title>
<link rel = "stylesheet" href ="/css/sample.css">
<link href="/css/listpage_copy.css" rel="stylesheet">
<link href="/css/font.css" rel = "stylesheet">
</head>
<body>
<form class="row g-3" id = "row_g-3_cumstom" action="/signup_execute" name = "user_info" method="post">
<div class="col-md-6">
<label for="inputEmail4" class="form-label">이메일</label>
<input type="email" class="form-control" id="inputEmail4" placeholder="최대 20자리 까지 입력가능" name = "id" maxlength="40">
</div>
<div class="col-md-6">
<label for="inputPassword4" class="form-label">비밀번호</label>
<input type="password" class="form-control" id="inputPassword4" placeholder="최대 20자리 까지 입력가능" name = "password" maxlength="20">
</div>
<div class="col-md-6">
<label for="inputPassword4" class="form-label">닉네임</label>
<input type="text" class="form-control" placeholder="최대 25자리까지 입력가능" name = "name" maxlength="25">
</div>
<div class="col-md-6">
<label for="inputPassword4" class="form-label">전화번호</label>
<input type="tel" class="form-control" placeholder="ex) 01012345678" pattern="[0-9]{11}" name = "phone" maxlength="12">
</div>
<div class="col-12">
<label for="inputAddress" class="form-label">주민번호</label>
<input type="password" class="form-control" id="inputAddress" placeholder="13자리를 입려하세요." pattern="[0-9]{13}" name = "ssn" maxlength="13">
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault1">
<label class="form-check-label" for="flexRadioDefault1">
남성
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault2" checked>
<label class="form-check-label" for="flexRadioDefault2">
여성
</label>
</div>
<div class="row g-3">
<div class="col-sm-7">
도시명
<input type="text" class="form-control" placeholder="ex) 서울특별시" aria-label="City" name = "city_name" maxlength="20">
</div>
<div class="col-sm">
동명
<input type="text" class="form-control" placeholder="ex) 논현동" aria-label="State" name = "town_name" maxlength="20">
</div>
<div class="col-sm">
도로명
<input type="text" class="form-control" placeholder="ex) 테헤란로 221길" aria-label="Zip" name = "street_name" maxlength="20">
</div>
<div class="col-sm">
우편번호
<input type="text" class="form-control" placeholder="ex) 06049" aria-label="Zip" name = "zip_code" maxlength="20">
</div>
<div class="col-sm">
상세주소
<input type="text" class="form-control" placeholder="ex) 5층 505호" aria-label="Zip" name = "details" maxlength="20">
</div>
</div>
<div class="col-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="gridCheck">
<label class="form-check-label" for="gridCheck">
확인했음.
</label>
</div>
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary" >가입하기</button>
</div>
</form>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
</body>
</html>
'Users' entity to register with DB.
package My_Project.integration.entity;
import My_Project.integration.entity.Dto.UserInfoDto;
import lombok.*;
import javax.persistence.*;
import java.awt.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
#Entity
#Getter
#NoArgsConstructor
#AllArgsConstructor
#Setter
#Table(uniqueConstraints = {#UniqueConstraint(columnNames = {"ssn","phone_number"})})
public class Users {
#Column(name = "id", length = 40, updatable = false)
#Id
private String id;
#Column(name = "password", length = 20, nullable = false)
private String password;
#Column(name = "name", length = 25, nullable = false)
private String name;
#Column(name = "phone_number", length = 12, nullable = false)
private String phoneNumber;
#Column(name = "ssn", length = 13, nullable = false, updatable = false)
private String ssn;
#Embedded
private Address address;
#Column(name = "point")
private Long point;
#OneToMany(mappedBy = "postedUser")
private List<PostInfo> uploadedPost = new ArrayList<>();
#OneToMany(mappedBy = "userId")
private List<PointHistory> pointHistories = new ArrayList<>();
#Embedded
private Dates dates;
public Users(UserInfoDto userInfoDto){
this.setId(userInfoDto.getId());
this.setPassword(userInfoDto.getPassword());
this.setPhoneNumber(userInfoDto.getPhoneNumber());
this.setSsn(userInfoDto.getSsn());
this.setPoint(0L);
Address address = new Address(
userInfoDto.getCityName(),
userInfoDto.getTownName(),
userInfoDto.getStreetName(),
userInfoDto.getZipCode(),
userInfoDto.getDetailsCode()
);
this.setAddress(address);
List<PostInfo> postInfoList = new ArrayList<>();
List<PointHistory> pointHistoryList = new ArrayList<>();
this.setUploadedPost(postInfoList);
this.setPointHistories(pointHistoryList);
Dates dates = new Dates(LocalDateTime.now(), LocalDateTime.now());
this.setDates(dates);
}
}
This is Embedded type 'Address' inside 'Users'
package My_Project.integration.entity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import javax.persistence.Column;
import javax.persistence.Embeddable;
#Embeddable
#Getter
#AllArgsConstructor
public class Address {
#Column(name = "city_name", length = 20, nullable = false) //도시명
private String cityName;
#Column(name = "town_name", length = 20) //동명
private String townName;
#Column(name = "street_name", length = 20, nullable = false) //도로명
private String streetName;
#Column(name = "zip_code", length = 20) // 우편번호
private String zipCode;
#Column(name = "details",length = 20) //상세주소
private String detailsCode;
protected Address() {
}
}
This is a Dto class that receives a value instead of 'Users'.
package My_Project.integration.entity.Dto;
import My_Project.integration.entity.PointHistory;
import My_Project.integration.entity.PostInfo;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
#Setter
#Getter
public class UserInfoDto {
private String id;
private String password;
private String name;
private String phoneNumber;
private String ssn;
private String cityName;
private String townName;
private String streetName;
private String zipCode;
private String detailsCode;
private Long point;
private List<PointHistory> pointHistories;
private List<PostInfo> postInfos;
public UserInfoDto(String id, String password, String name, String phoneNumber, String ssn, String cityName, String townName, String streetName, String zipCode, String detailsCode, Long point, List<PointHistory> pointHistories, List<PostInfo> postInfos) {
this.id = id;
this.password = password;
this.name = name;
this.phoneNumber = phoneNumber;
this.ssn = ssn;
this.cityName = cityName;
this.townName = townName;
this.streetName = streetName;
this.zipCode = zipCode;
this.detailsCode = detailsCode;
this.point = point;
this.pointHistories = pointHistories;
this.postInfos = postInfos;
}
public UserInfoDto() {
}
}
I want to put the values on 'Users' through 'UserInfoDto'. But It's doesn't work with error code above. What should I fix?
Error code
org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value : My_Project.integration.entity.Users.address.cityName; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value : My_Project.integration.entity.Users.address.cityName
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:294)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:551)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
at jdk.proxy4/jdk.proxy4.$Proxy109.save(Unknown Source)
at My_Project.integration.service.UserService.addUsers(UserService.java:26)
at My_Project.integration.service.UserService$$FastClassBySpringCGLIB$$636d190f.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
at My_Project.integration.service.UserService$$EnhancerBySpringCGLIB$$7615f959.addUsers(<generated>)
at My_Project.integration.controller.SignupPageController.signUp(SignupPageController.java:24)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:696)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:779)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value : My_Project.integration.entity.Users.address.cityName
at org.hibernate.engine.internal.Nullability.checkNullability(Nullability.java:122)
at org.hibernate.engine.internal.Nullability.checkNullability(Nullability.java:55)
at org.hibernate.action.internal.AbstractEntityInsertAction.nullifyTransientReferencesIfNotAlready(AbstractEntityInsertAction.java:116)
at org.hibernate.action.internal.AbstractEntityInsertAction.makeEntityManaged(AbstractEntityInsertAction.java:125)
at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:289)
at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:263)
at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:250)
at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:338)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:287)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:135)
at org.hibernate.event.internal.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventListener.java:271)
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:243)
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:318)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:172)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:70)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:829)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:816)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:362)
at jdk.proxy4/jdk.proxy4.$Proxy105.merge(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:311)
at jdk.proxy4/jdk.proxy4.$Proxy105.merge(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:669)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:289)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:530)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:286)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:640)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:164)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:139)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:81)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
... 71 more
From the exception it seams that the field cityName is null somehow when you do the mapping. As there is a not null constraint on this field this causes the issue
this is my ProdottoController:
package it.catalogo.controller;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import it.catalogo.model.Prodotto;
import it.catalogo.repository.ProdottoRepository;
#Controller
#RequestMapping("/prodotto")
public class ProdottoController {
#Autowired
private ProdottoRepository repo;
#GetMapping("/lista")
public ModelAndView list( #RequestParam(name = "id", required = false) String idProdotto, ModelMap mm) {
if(idProdotto!=null) {
Optional<Prodotto> p = repo.findById(Integer.parseInt(idProdotto));
mm.addAttribute("prodottoDaModificare",p);
}
return new ModelAndView("prodotti", "listaProdotti", repo.findAll());
}
#PostMapping("/add")
public String add(#ModelAttribute("datiProdotto") Prodotto p) {
repo.save(p);
return "redirect:/prodotto/lista";
}
#PostMapping("/update")
public String update(#ModelAttribute("datiProdotto") Prodotto p) {
repo.save(p);
return "redirect:/prodotto/lista";
}
#GetMapping("/delete")
public String delete(#RequestParam("id") String id) {
repo.deleteById(Integer.parseInt(id));
return "redirect:/prodotto/lista";
}
}
Prodotto entity:
package it.catalogo.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Prodotto {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "nome")
private String nome;
#Column(name = "descrizione")
private String descrizione;
#Column(name = "prezzo")
private Integer prezzo;
public Prodotto(String nome, String descrizione, Integer prezzo) {
super();
this.nome = nome;
this.descrizione = descrizione;
this.prezzo = prezzo;
}
public Prodotto() {
super();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getDescrizione() {
return descrizione;
}
public void setDescrizione(String descrizione) {
this.descrizione = descrizione;
}
public Integer getPrezzo() {
return prezzo;
}
public void setPrezzo(Integer prezzo) {
this.prezzo = prezzo;
}
}
This is the view (Freemarker):
<!DOCTYPE html>
<html>
<head>
<title>Catalogo prodotti</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/jquery#3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.6.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>
</head>
<body>
<h1>Catalogo prodotti</h1>
<#if prodottoDaModificare?? >
<h2>Modifica del prodotto - ${prodottoDaModificare.nome}</h2>
<div style="margin: 20px">
<form method="POST" action="update" id="datiProdotto">
<input type="hidden" name="id" value="${prodottoDaModificare.id}"/>
<div>
<label for="nome">Nome</label>
<input type="text" name="nome" value="${prodottoDaModificare.nome}" id="nome">
</div>
<div>
<label for="descrizione">Descrizione</label>
<input type="text" name="descrizione" value="${prodottoDaModificare.descrizione}" id="descrizione">
</div>
<div>
<label for="prezzo">Prezzo</label>
<input type="number" name="prezzo" value="${prodottoDaModificare.prezzo}" id="prezzo">
</div>
<div>
<input type="submit" name="invia" value="Salva modifiche"/S>
</div>
</form>
</div>
<#else>
<h2>Nuovo prodotto</h2>
<div style="margin: 20px">
<form method="POST" action="add" id="datiProdotto">
<div>
<label for="nome">Nome</label>
<input type="text" name="nome" value="" id="nome">
</div>
<div>
<label for="descrizione">Descrizione</label>
<input type="text" name="descrizione" value="" id="descrizione">
</div>
<div>
<label for="prezzo">Prezzo</label>
<input type="number" name="prezzo" value="" id="prezzo">
</div>
<div>
<input type="submit" name="invia" value="Aggiungi"/>
</div>
</form>
</div>
</#if>
<hr>
<h2>Lista prodotti</h2>
<div>
<table class="table">
<thead>
<tr>
<th>Nome</th>
<th>Descrizione</th>
<th>Prezzo</th>
<th>Azioni</th>
</tr>
</thead>
<tbody>
<#list listaProdotti as prodotto>
<tr>
<td>${prodotto.nome}</td>
<td>${prodotto.descrizione}</td>
<td>${prodotto.prezzo}</td>
<td>
Elimina
Modifica
</td>
</tr>
</#list>
</tbody>
</table>
</div>
</body>
</html>
When i try to update a value into the table i've the following error:
FreeMarker template error (DEBUG mode; use RETHROW in production!): The following has evaluated to null or missing: ==> prodottoDaModificare.nome [in template "prodotti.ftl" at line 15, column 47] ---- Tip: It's the step after the last dot that caused this error, not those before it. ---- Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? ---- ---- FTL stack trace ("~" means nesting-related): - Failed at: ${prodottoDaModificare.nome} [in template "prodotti.ftl" at line 15, column 45] ---- Java stack trace (for programmers): ---- freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...] at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134) at freemarker.core.EvalUtil.coerceModelToTextualCommon(EvalUtil.java:481) at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:401) at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:370) at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:100) at freemarker.core.DollarVariable.accept(DollarVariable.java:63) at freemarker.core.Environment.visit(Environment.java:347) at freemarker.core.Environment.visit(Environment.java:353) at freemarker.core.Environment.visit(Environment.java:353) at freemarker.core.Environment.process(Environment.java:326) at freemarker.template.Template.process(Template.java:383) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate(FreeMarkerView.java:391) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:304) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:255) at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:179) at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:316) at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1401) at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1145) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1084) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1787) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.base/java.lang.Thread.run(Thread.java:833)
Your problem is that when you do mm.addAttribute("prodottoDaModificare",p), p is not a Prodotto object, but an Option. And of course, Option has no nome property. Use mm.addAttribute("prodottoDaModificare",p.orElse(null)) (or if the object must be there, then orElseThrow).
I am following this book "Spring In Action 5th Edition" example, but having this error whenever validation on form input found something invalid.
error:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sun Oct 27 17:26:07 SGT 2019
There was an unexpected error (type=Internal Server Error, status=500).
An error happened during template parsing (template: "class path resource [templates/design.html]")
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/design.html]")
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241)
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100)
at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072)
at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:362)
at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:189)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1371)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1117)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1056)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.attoparser.ParseException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "design" - line 59, col 20)
at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393)
at org.attoparser.MarkupParser.parse(MarkupParser.java:257)
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230)
... 52 more
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "design" - line 59, col 20)
at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:117)
at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95)
at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633)
at org.thymeleaf.engine.ProcessorTemplateHandler.handleStandaloneElement(ProcessorTemplateHandler.java:918)
at org.thymeleaf.engine.TemplateHandlerAdapterMarkupHandler.handleStandaloneElementEnd(TemplateHandlerAdapterMarkupHandler.java:260)
at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler$InlineMarkupAdapterPreProcessorHandler.handleStandaloneElementEnd(InlinedOutputExpressionMarkupHandler.java:256)
at org.thymeleaf.standard.inline.OutputExpressionInlinePreProcessorHandler.handleStandaloneElementEnd(OutputExpressionInlinePreProcessorHandler.java:169)
at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler.handleStandaloneElementEnd(InlinedOutputExpressionMarkupHandler.java:104)
at org.attoparser.HtmlElement.handleStandaloneElementEnd(HtmlElement.java:79)
at org.attoparser.HtmlMarkupHandler.handleStandaloneElementEnd(HtmlMarkupHandler.java:241)
at org.attoparser.MarkupEventProcessorHandler.handleStandaloneElementEnd(MarkupEventProcessorHandler.java:327)
at org.attoparser.ParsingElementMarkupUtil.parseStandaloneElement(ParsingElementMarkupUtil.java:96)
at org.attoparser.MarkupParser.parseBuffer(MarkupParser.java:706)
at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:301)
... 54 more
Caused by: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'design' available as request attribute
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:153)
at org.springframework.web.servlet.support.RequestContext.getBindStatus(RequestContext.java:903)
at org.thymeleaf.spring5.context.webmvc.SpringWebMvcThymeleafRequestContext.getBindStatus(SpringWebMvcThymeleafRequestContext.java:227)
at org.thymeleaf.spring5.util.FieldUtils.getBindStatusFromParsedExpression(FieldUtils.java:306)
at org.thymeleaf.spring5.util.FieldUtils.getBindStatus(FieldUtils.java:253)
at org.thymeleaf.spring5.util.FieldUtils.getBindStatus(FieldUtils.java:227)
at org.thymeleaf.spring5.processor.AbstractSpringFieldTagProcessor.doProcess(AbstractSpringFieldTagProcessor.java:174)
at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74)
... 67 more
Object been passed to view template:
package tacos;
import java.util.List;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import lombok.Data;
#Data
public class Taco {
#NotNull
#Size(min=5, message="Name must be at least 5 characters long")
private String name;
#NotNull
#Size(min=2, message="You must choose at least 2 ingredient")
private List<String> ingredients;
}
Thymeleaf view template:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Taco Cloud</title>
<link rel="stylesheet" th:href="#{/styles.css}" />
</head>
<body>
<h1>Design your taco!</h1>
<img th:src="#{/images/TacoCloud.png}"/>
<form method="POST" th:object="${design}">
<div class="grid">
<div class="ingredient-group" id="wraps">
<h3>Designate your wrap:</h3>
<div th:each="ingredient : ${wrap}">
<input name="ingredients" type="checkbox" th:value="${ingredient.id}"
/>
<span th:text="${ingredient.name}">INGREDIENT</span><br/>
</div>
</div>
<div class="ingredient-group" id="proteins">
<h3>Pick your protein:</h3>
<div th:each="ingredient : ${protein}">
<input name="ingredients" type="checkbox" th:value="${ingredient.id}"
/>
<span th:text="${ingredient.name}">INGREDIENT</span><br/>
</div>
</div>
<div class="ingredient-group" id="cheeses">
<h3>Choose your cheese:</h3>
<div th:each="ingredient : ${cheese}">
<input name="ingredients" type="checkbox" th:value="${ingredient.id}"
/>
<span th:text="${ingredient.name}">INGREDIENT</span><br/>
</div>
</div>
<div class="ingredient-group" id="veggies">
<h3>Determine your veggies:</h3>
<div th:each="ingredient : ${veggies}">
<input name="ingredients" type="checkbox" th:value="${ingredient.id}"
/>
<span th:text="${ingredient.name}">INGREDIENT</span><br/>
</div>
</div>
<div class="ingredient-group" id="sauces">
<h3>Select your sauce:</h3>
<div th:each="ingredient : ${sauce}">
<input name="ingredients" type="checkbox" th:value="${ingredient.id}"
/>
<span th:text="${ingredient.name}">INGREDIENT</span><br/>
</div>
</div>
</div>
<div>
<h3>Name your taco creation:</h3>
<input type="text" th:field="*{name}"/>
<span class="validationError"
th:if="${#fields.hasErrors('name')}"
th:errors="*{name}">Name Error</span>
<br/>
<button>Submit your taco</button>
</div>
</form>
</body>
</html>
Controller display form method:
#GetMapping
public String showDesignForm(Model model)
{
List<Ingredient> ingredients = Arrays.asList(
new Ingredient("FLTO", "Flour Tortilla", Type.WRAP),
new Ingredient("COTO", "Corn Tortilla", Type.WRAP),
new Ingredient("GRBF", "Ground Beef", Type.PROTEIN),
new Ingredient("CARN", "Carnitas", Type.PROTEIN),
new Ingredient("TMTO", "Diced Tomatoes", Type.VEGGIES),
new Ingredient("LETC", "Lettuce", Type.VEGGIES),
new Ingredient("CHED", "Cheddar", Type.CHEESE),
new Ingredient("JACK", "Monterrey Jack", Type.CHEESE),
new Ingredient("SLSA", "Salsa", Type.SAUCE),
new Ingredient("SRCR", "Sour Cream", Type.SAUCE)
);
Type[] types = Ingredient.Type.values();
for (Type type : types)
{
model.addAttribute(type.toString().toLowerCase(),
filterByType(ingredients, type));
}
model.addAttribute("design", new Taco());
return "design";
}
Controller process form method:
#PostMapping
public String processDesign(#Valid Taco taco, Errors errors)
{
if (errors.hasErrors())
{
return "design";
}
// Save the taco design...
// We will do this in chapter 3
log.info("Processing design: " + taco);
return "redirect:/orders/current";
}
I have no issue in displaying the form. All input fields are well received and processed. But whenever there is validation errors, and process form method call back to the form page "design", the form failed to parse with above mentioned errors.
I had tried:1. to disable validation on the Taco.name field;2. to remove the <span> which displays the name field errors. But none of them work.
Thanks in advance for your help.
I try change this code
#PostMapping
public String processDesign(#Valid Taco taco, Errors errors)
{
if (errors.hasErrors())
{
return "design";
}
// Save the taco design...
// We will do this in chapter 3
log.info("Processing design: " + taco);
return "redirect:/orders/current";
}
to
#PostMapping
public String processDesign(#Valid Taco taco, Errors errors)
{
if (errors.hasErrors())
{
return "redirect:/design";
}
// Save the taco design...
// We will do this in chapter 3
log.info("Processing design: " + taco);
return "redirect:/orders/current";
}
and it works.
I had a similar problem. This is what I did to fix it.
1st - change the opening header in design.html to the following
<form method="POST" th:object="${design}">
2nd - my processDesign() method looks like this:
public String processDesign(#Valid #ModelAttribute("design") Taco taco, Errors errors) {
if (errors.hasErrors()) {
return "design";
}
// this will save our Taco Design
// log.info("Processing design: " + design);
return "redirect:/orders/current";
}
I hope, that this helps and I'm not too late. In general, there are multiple similar errors in the book, that need to be fixed, but the community around it is great, so no need to worry.
Cheers
The code in book has some error, here is the right code from the github of book:
// tag::head[]
package tacos.web;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import lombok.extern.slf4j.Slf4j;
import tacos.Ingredient;
import tacos.Ingredient.Type;
import tacos.Taco;
#Slf4j
#Controller
#RequestMapping("/design")
public class DesignTacoController {
//end::head[]
#ModelAttribute
public void addIngredientsToModel(Model model) {
List<Ingredient> ingredients = Arrays.asList(
new Ingredient("FLTO", "Flour Tortilla", Type.WRAP),
new Ingredient("COTO", "Corn Tortilla", Type.WRAP),
new Ingredient("GRBF", "Ground Beef", Type.PROTEIN),
new Ingredient("CARN", "Carnitas", Type.PROTEIN),
new Ingredient("TMTO", "Diced Tomatoes", Type.VEGGIES),
new Ingredient("LETC", "Lettuce", Type.VEGGIES),
new Ingredient("CHED", "Cheddar", Type.CHEESE),
new Ingredient("JACK", "Monterrey Jack", Type.CHEESE),
new Ingredient("SLSA", "Salsa", Type.SAUCE),
new Ingredient("SRCR", "Sour Cream", Type.SAUCE)
);
Type[] types = Ingredient.Type.values();
for (Type type : types) {
model.addAttribute(type.toString().toLowerCase(),
filterByType(ingredients, type));
}
}
//tag::showDesignForm[]
#GetMapping
public String showDesignForm(Model model) {
model.addAttribute("design", new Taco());
return "design";
}
//end::showDesignForm[]
/*
//tag::processDesign[]
#PostMapping
public String processDesign(Design design) {
// Save the taco design...
// We'll do this in chapter 3
log.info("Processing design: " + design);
return "redirect:/orders/current";
}
//end::processDesign[]
*/
//tag::processDesignValidated[]
#PostMapping
public String processDesign(#Valid #ModelAttribute("design") Taco design, Errors errors, Model model) {
if (errors.hasErrors()) {
return "design";
}
// Save the taco design...
// We'll do this in chapter 3
log.info("Processing design: " + design);
return "redirect:/orders/current";
}
//end::processDesignValidated[]
//tag::filterByType[]
private List<Ingredient> filterByType(
List<Ingredient> ingredients, Type type) {
return ingredients
.stream()
.filter(x -> x.getType().equals(type))
.collect(Collectors.toList());
}
//end::filterByType[]
// tag::foot[]
}
// end::foot[]
and you can get all the source code from https://github.com/habuma/spring-in-action-5-samples
ps: In my opinion, the possible reason is that #valide Taco will transport a Taco object named taco to the template, while we use the design in the tempalte, so, the template cannot find the design which result in the error. And #ModelAttribute('design') can renamed the Taco object to design. On the other hand, we need the ingredients list to init the template whenever we visit the tacoDesign html, that is the reason that we separate the addIngredientsToModel method and using #ModelAttribute above it.
In my recent spring project, I need to generate a pdf file from html page. I am trying to do this task with WkhtmlToPdf. But i am unable to generate pdf file from html page. I search many project and tutorial about WkhtmlToPdf but I didn't find any answer. I am posting my code here.
This is my Controller class that redirect to html page with student list
#Controller
public class TestController {
#Autowired
StudentService studentService;
#Autowired
PdfDemo pdfDemo;
#GetMapping("/test")
private String testPage(Model model)
{
List<Student> studentList = studentService.findAll();
System.out.println(studentList);
model.addAttribute(studentList);
return "sample";
}
}
This is my html page that show list of student
<body>
<div class="container" id="pdfDiv">
<h2>HTML Table</h2>
<table class="table table-striped">
<tr>
<th>Id</th>
<th>Name</th>
<th>Session</th>
<th>Department</th>
<th>Roll</th>
<th>Mobile</th>
</tr>
<tr th:each="student : ${studentList}">
<td th:text="${student.id}"></td>
<td th:text="${student.name}"></td>
<td th:text="${student.session}"></td>
<td th:text="${student.department}"></td>
<td th:text="${student.roll}"></td>
<td th:text="${student.mobile}"></td>
</tr>
</table>
</div>
Download PDF
</body>
Here you can see, I have a link to generate pdf. The PdfGenerateController class is
#Controller
public class PdfGenerateController {
#GetMapping("/getStudentsListAsPdf")
public ResponseEntity<Resource> generateReportOfStudent() {
String downloadFilePath = generatePdfListForStudents();
System.out.println("DL File Path: "+downloadFilePath);
if (downloadFilePath == null)
throw new NullPointerException("data missing");
if (downloadFilePath == null)
return ResponseEntity.badRequest()
.contentType(MediaType.parseMediaType("application/pdf"))
.body(null);
File file = new File(downloadFilePath);
Path path = Paths.get(file.getAbsolutePath());
ByteArrayResource resource = null;
try {
resource = new ByteArrayResource(Files.readAllBytes(path));
} catch (IOException e) {
e.printStackTrace();
}
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment; filename=\"student_list" + ".pdf\"");
return ResponseEntity.ok()
.headers(headers)
.contentLength(file.length())
.contentType(MediaType.parseMediaType("application/pdf"))
.body(resource);
}
}
And this is the class where code are written to generate pdf
#Service
public class PdfDemo {
#Value("${file.download.base}")
private String DOWNLOAD_FOLDER;
public static final String DOWNLOAD_PATH = "tmp/downloads/";
public static final String ZIP_PATH = "/tmp/zip_files";
public static final String FILE_NAME = "student_list";
public static final String SERVER_REPORT_URL = "/report/html";
public static final String DOWNLOAD_FILE_PATH = DOWNLOAD_PATH + FILE_NAME;
public static final String ZIPFILE = "/tmp/zip_files/cmed_report.zip";
public static final String ZIPFILE_NAME = "cmed_report.zip";
public static final String SRCDIR = "/tmp/downloads";
public static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd-HH";
public static String getBaseURL() throws MalformedURLException {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
String baseUrl = "";
if (request != null) {
// handle proxy forward
String scheme = request.getScheme();
if (request.getHeader("x-forwarded-proto") != null) {
scheme = request.getHeader("x-forwarded-proto");
}
Integer serverPort = request.getServerPort();
if ((serverPort == 80) || (serverPort == 443)) {
// No need to add the server port for standard HTTP and HTTPS ports, the scheme will help determine it.
baseUrl = String.format("%s://%s%s", scheme, request.getServerName(), request.getContextPath());
} else {
baseUrl = String.format("%s://%s:%d%s", scheme, request.getServerName(), serverPort, request.getContextPath());
}
}
return baseUrl;
}
public static String generatePdfListForStudents()
{
WkHtmlToPdf pdf = new WkHtmlToPdf();
try {
pdf.addSources(Source.fromUrl(getServerAbsolutePath(SERVER_REPORT_URL)));
System.out.println("Server absolute path: " + getServerAbsolutePath(SERVER_REPORT_URL));
System.out.println(Source.fromUrl(getServerAbsolutePath(SERVER_REPORT_URL)));
} catch (Exception e) {
e.printStackTrace();
}
String downloadPath = DOWNLOAD_FILE_PATH + ".pdf";
pdf.addArguments(
Argument.from(EnableJavascript));
System.out.println("PDF Location: " + downloadPath);
// Save the PDF
File file = new File(downloadPath);
System.out.println("Directory status: " + file.exists() + " " + file.isDirectory());
try {
System.out.println("Paths.get: " + Paths.get(downloadPath));
pdf.save(Paths.get(downloadPath));
} catch (IOException e) {
e.printStackTrace();
}
return downloadPath;
}
public static String getServerAbsolutePath(String requestPath) throws MalformedURLException {
String URL = getBaseURL() + requestPath;
return URL;
}
}
And this is the Controller class for SERVER_REPORT_URL in PdfDemo class
#Controller
public class HtmlViewReportController {
#Autowired
StudentService studentService;
#GetMapping(value = "/report/html")
public String getPdfReportForStudent(Model model) {
model.addAttribute("studentList", studentService.findAll());
return "sample";
}
}
Now, When I hit on Download PDFin html page I get error. Error stack trace here
java.io.IOException: Cannot run program "wkhtmltopdf": error=2, No such file or directory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
at java.lang.Runtime.exec(Runtime.java:620)
at java.lang.Runtime.exec(Runtime.java:528)
at com.ztomic.wkhtmltopdf.WkHtmlToPdf.convert(WkHtmlToPdf.java:84)
at com.ztomic.wkhtmltopdf.WkHtmlToPdf.getPdfBytes(WkHtmlToPdf.java:77)
at com.ztomic.wkhtmltopdf.WkHtmlToPdf.save(WkHtmlToPdf.java:68)
at com.avijit.test.PdfUtil.PdfDemo.generatePdfListForStudents(PdfDemo.java:109)
at com.avijit.test.Controller.PdfGenerateController.generateReportOfStudent(PdfGenerateController.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:155)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:123)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:108)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: error=2, No such file or directory
at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.<init>(UNIXProcess.java:247)
at java.lang.ProcessImpl.start(ProcessImpl.java:134)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
... 71 more
DL File Path: tmp/downloads/student_list.pdf
java.nio.file.NoSuchFileException: /home/dracula/IdeaProjects/WkhtmlToPdfGeneratorProject/tmp/downloads/student_list.pdf
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:86)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:214)
at java.nio.file.Files.newByteChannel(Files.java:361)
at java.nio.file.Files.newByteChannel(Files.java:407)
at java.nio.file.Files.readAllBytes(Files.java:3152)
at com.avijit.test.Controller.PdfGenerateController.generateReportOfStudent(PdfGenerateController.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:155)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:123)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:108)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Here the github link. It will be very helpful if any one can solve this.
Did you install wkhtmltopdf in your machine ? try it on https://wkhtmltopdf.org/downloads.html
I did it in a simpler way using Pdf Object from
import com.github.jhonnymertz.wkhtmltopdf.wrapper.Pdf;
The generation of pdf looks easier as follows:
#Override
public String save(String url) throws IOException, InterruptedException{
Pdf pdf = new Pdf();
pdf.addPageFromUrl(url);
return mockSaveS3(pdf);
}
private String mockSaveS3(Pdf pdf) throws IOException, InterruptedException{
File fileTemp = File.createTempFile("pdf-", "");
File file = pdf.saveAs("apps/" + fileTemp.getName());
return file.getAbsolutePath();
}
And I returned the Url to the PDF that I stored in apps/ directory.
I solved this problem. It took a long time to solve. I wrote a blog step by step in the medium. Here I am posting that link. You can see all the steps here. I also provided github link of sample project. Look
here
When trying to update an entity from the controller, I keep getting this exception. Rest assured, thorough research regarding this exception has been made, but none of the suggestions have worked in my case.
I am trying to update the doctor entity by calling hibernate session.update(entity);
Doctor model:
#Entity
#Table(name = "tbl_doctor")
public class Doctor {
private Long id;
private PersonInfo personInfo;
private String licenseNumber;
private User user;
private String specialization;
private String employmentStatus;
private String suffix;
private List<Patient> patients;
//
// #OneToMany
// #JoinTable(name = "Doctor_Appointment", joinColumns = { #JoinColumn(name
// = "doctor_id") }, inverseJoinColumns = { #JoinColumn(name = //
// "appointment_id") })
// private List<Appointment> appointments;
public Doctor() {
super();
user = new User();
personInfo = new PersonInfo();
}
#Override
public String toString() {
String patients= "";
for(Patient p: this.patients) {
patients += p.toString();
}
return "Doctor [id=" + id + ", personInfo=" + personInfo
+ ", licenseNumber=" + licenseNumber + ", user=" + user
+ ", specialization=" + specialization + ", employmentStatus="
+ employmentStatus + ", suffix=" + suffix + ", patients="
+ patients + "]";
}
#Column(name = "fld_license_number")
public String getLicenseNumber() {
return licenseNumber;
}
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "key_user")
public User getUser() {
return user;
}
#Column(name = "fld_specialization")
public String getSpecialization() {
return specialization;
}
#Column(name = "fld_employment_status")
public String getEmploymentStatus() {
return employmentStatus;
}
#Column(name = "fld_suffix")
public String getSuffix() {
return suffix;
}
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "key_patient")
#Fetch(value = FetchMode.SUBSELECT)
public List<Patient> getPatients() {
return patients;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "key_doctor")
public Long getId() {
return id;
}
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "key_person_info")
public PersonInfo getPersonInfo() {
return personInfo;
}
//setters
}
Person info just includes the biodata like first name, last name, sex, birthday etc.
Controller
#RequestMapping(value="/update_doctor.it", method=RequestMethod.POST)
public String updateDoctor(HttpSession session, #ModelAttribute("doctor") Doctor doctor, Model model, #RequestParam("id") long adminId) {
System.err.println("update doctor controller");
String username = session.getAttribute("user").toString();
session.setAttribute("user", username);
doctor.getUser().setEnabled(true);
doctor.getPersonInfo().setDateModified(LocalDate.now());
doctorDao.updateDoctor(doctor);
return "redirect:/view_doctor_profile.it?id=" + doctor.getId();
}
DaoImpl
#Override
public void updateDoctor(Doctor doctor) {
Session session = sessionFactory.getCurrentSession();
session.update(doctor);
}
JSP
form:form class="docForm" method="post" commandName="doctor" action="update_doctor.it?id=${adminUser.getId() }" >
<section>
<header>
<h3>Doctor Information</h3>
</header>
<form:hidden path="id" value="${doctor.id}" />
<ul class="fields">
<li><label>First Name</label>:<form:input value="${doctor.getPersonInfo().getFirstName()}" path="personInfo.firstName" type="text" required="true" /></li>
<li><label>Last Name</label>:<form:input value="${doctor.getPersonInfo().getLastName()}" path="personInfo.lastName" type="text" required="true" /></li>
<li><label>Suffix</label>:<form:input value="${doctor.getSuffix() }" path="suffix" /></li>
<li><label>License Number</label>:<form:input value="${ doctor.getLicenseNumber() }" path="licenseNumber" /></li>
<li><label>Occupation</label>:<form:input value="${doctor.getPersonInfo().getOccupation() }" path="personInfo.occupation" /></li>
<li><label>Specialization</label>:<form:input value="${ doctor.getSpecialization() }" path="specialization" required="true"/></li>
<li><label>Date of Birth</label>:<input value="${doctor.getPersonInfo().getDateOfBirth() }" name="personInfo.dateOfBirth" type="text" id="datepicker" readonly/></li>
<li><label>Gender</label>:
<label>Male</label><form:radiobutton path="personInfo.sex" value="male"/>
<label>Female</Label><form:radiobutton path="personInfo.sex" value="female"/>
</li>
<li><label>Phone Number</label>:<form:input value="${ doctor.getPersonInfo().getContacts().get(0).getPhoneNumber() }" path="personInfo.contacts[0].phoneNumber"/></li>
<li><label>Mobile Number</label>:<form:input value="${ doctor.getPersonInfo().getContacts().get(0).getMobileNumber() }" path="personInfo.contacts[0].mobileNumber" type="text" required="true"/></li>
<li><label>E-mail Address</label>:<form:input value="${ doctor.getPersonInfo().getEmail() }" path="personInfo.email" type="text" required="true"/></li>
</ul>
</section>
<section>
<header><h3>Address</h3></header>
<ul class="fields">
<li><label>Address</label>:<form:input value="${ doctor.getPersonInfo().getAddresses().get(0).getAddress() }" path="personInfo.addresses[0].address"/></li>
<li><label>City</label>:<form:input value="${ doctor.getPersonInfo().getAddresses().get(0).getCity() }" path="personInfo.addresses[0].city"/></li>
<li><label>Province</label>:<form:input value="${ doctor.getPersonInfo().getAddresses().get(0).getProvince() }" path="personInfo.addresses[0].province"/></li>
<li><label>Zip Code</label>:<form:input value="${ doctor.getPersonInfo().getAddresses().get(0).getZipCode() }" path="personInfo.addresses[0].zipCode" /></li>
</ul>
</section>
<section>
<header><h3>Account Details</h3></header>
<ul class="fields">
<li><label>Username</label>:<form:input value="${ doctor.getUser().getUsername() }" path="user.username" required="true"/></li>
<li><label>Password</label>:<form:password value="${ doctor.getUser().getPassword() }" path="user.password" required="true"/></li>
</ul>
</section>
<section>
<header>
<h3>Hospital Details</h3>
</header>
<ul class="fields">
<li><label>Name</label>:<form:input value="${doctor.getPersonInfo().getCompanyName() }" path="personInfo.companyName"/></li>
<li><label>Employment Status</label>:
<label>Full-time</label><form:radiobutton path="employmentStatus" value="full-time"/>
<label>Part-time</Label><form:radiobutton path="employmentStatus" value="part-time"/>
</li>
<li><label>Phone Number</label>:<form:input value="${ doctor.getPersonInfo().getContacts().get(1).getPhoneNumber()}" path="personInfo.contacts[1].phoneNumber"/></li>
<li><label>Work Mobile Number</label>:<form:input value="${ doctor.getPersonInfo().getContacts().get(1).getPhoneNumber()}" path="personInfo.contacts[1].mobileNumber" /></li>
<li><label>Address</label>:<form:input value="${ doctor.getPersonInfo().getAddresses().get(1).getAddress() }" path="personInfo.addresses[1].address" /></li>
<li><label>City</label>:<form:input value="${ doctor.getPersonInfo().getAddresses().get(1).getCity() }" path="personInfo.addresses[1].city"/></li>
<li><label>Province</label>:<form:input value="${ doctor.getPersonInfo().getAddresses().get(1).getProvince() }" path="personInfo.addresses[1].province" /></li>
<li><label>Zip Code</label>:<form:input value="${ doctor.getPersonInfo().getAddresses().get(1).getZipCode() }" path="personInfo.addresses[1].zipCode" />
</ul>
</section>
<section>
<ul class="btnForm">
<li><span class="btn"><input type="submit"
value="Save" class="btnS"></span></li>
<li><span class="btn"><input type="button"
value="Cancel" class="btnCancel" onClick="viewPotentialsList()"></span></li>
</ul>
Error
SEVERE: Servlet.service() for servlet [emrMVC] in context with path [/emr] threw exception [Request processing failed; nested exception is org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1] with root cause
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70)
at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:90)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:185)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:657)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:755)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:475)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:270)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at com.sun.proxy.$Proxy27.updateDoctor(Unknown Source)
at com.ust.emr.controller.admin.EditDoctorController.updateDoctor(EditDoctorController.java:56)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
I figured it out. A lot of classes or entities are dependent on the doctor, the entity I'm updating. In order for the batch update to execute successfully, I had to place a on the jsp, fetching all the ids of the dependent classes. Thank you!