have a very simple question on JSTL tags.
I am using spring to fetch data from back-end and display in the JSP.
Have the following code. I am getting the items of the for each tag printed in the console. But the same items are not getting printed/displayed inside the table rows.
<table id="table_id" class="display">
<thead>
<tr>
<th>Movie Name</th>
<th>Movie Rating</th>
</tr>
</thead>
<tbody>
<c:forEach items="${model.movieslist}" var="movie">
<tr>
<td>${movie.name}</td>
<td>${movie.rating}</td>
</tr>
</c:forEach>
</tbody>
My spring controller class
public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
// TODO Auto-generated method stub
logger.info("returning hello view");
List<Movie> moviesList = DbManager.getInstance().getMovies();
ModelMap modelMap = new ModelMap();
modelMap.addAttribute("movieslist", moviesList);
return new ModelAndView("hello.jsp",modelMap);
}
Movie domain class
package springapp.domain;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document(collection = "movie")
public class Movie {
#Id
public String _id;
public String name;
public String getId() {
return _id;
}
public void setId(String _id) {
this._id = _id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getRating() {
return rating;
}
public void setRating(float rating) {
this.rating = rating;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public float rating;
public String date;
#Override
public String toString() {
// TODO Auto-generated method stub
return name;
}
}
First, your jsp should contain the following taglib
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
Second, you don't need to get it using ${model.moviesList}, modify it as follows:
<c:forEach items="${movieslist}" var="movie">
Related
I am trying to save an uploaded file as Blob in a MySql record. I am new to Spring. When I am about to save the record after uploading a file, then when my POST method updateCandidate() executes, I get this exception:
Field error in object 'candidateForm' on field 'cv': rejected value [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile#59c09df6]; codes [typeMismatch.candidateForm.cv,typeMismatch.cv,typeMismatch.java.sql.Blob,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [candidateForm.cv,cv]; arguments []; default message [cv]]; default message [Failed to convert property value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'java.sql.Blob' for property 'cv'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'java.sql.Blob' for property 'cv': no matching editors or conversion strategy found]
What is going wrong? How to fix?
My entity:
import java.sql.Blob;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
#Entity
public class Candidate {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(unique = true)
private String ssn;
private String name;
private String surname;
private String technology;
private String media;
#Lob
private Blob cv;
private boolean activeCV;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getSsn() {
return ssn;
}
public void setSsn(String ssn) {
this.ssn = ssn;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getTechnology() {
return technology;
}
public void setTechnology(String technology) {
this.technology = technology;
}
public String getMedia() {
return media;
}
public void setMedia(String media) {
this.media = media;
}
public Blob getCv() {
return cv;
}
public void setCv(Blob cv) {
this.cv = cv;
}
public boolean isActiveCV() {
return activeCV;
}
public void setActiveCV(boolean activeCV) {
this.activeCV = activeCV;
}
}
In my service:
#Autowired
private CandidateRepository repository;
...
public Optional<Candidate> getCandidate(Long id){
return repository.findById(id);
}
public void addOrUpdateCandidate(Candidate candidate) {
repository.save(candidate);
}
In my controller:
#Controller
#RequestMapping("/candidates")
public class CandidateController {
#Autowired
private EntityManagerFactory emf;
#Autowired
private CandidateService service;
...
#GetMapping("/updateCandidate/{id}")
public String showUpdateUserForm(#PathVariable("id") Long id, Model model) {
Candidate candidate = service.getCandidate(id).get();
model.addAttribute("candidateForm", candidate);
return "updateCandidateForm";
}
#PostMapping("/updateCandidate/updateCandidateResult")
public String updateCandidate(#ModelAttribute("candidateForm") Candidate candidate, #RequestParam("cv") MultipartFile file) throws IOException {
InputStream iStream = file.getInputStream();
long size = file.getSize();
Session session = emf.unwrap(Session.class);
Blob cv = Hibernate.getLobCreator(session).createBlob(iStream, size);
candidate.setCv(cv);
service.addOrUpdateCandidate(candidate);
return "updateCandidateResult";
}
}
My updateCandidateForm.jsp:
<%# page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<body>
<form:form method="POST" action="updateCandidateResult" modelAttribute="candidateForm" enctype="multipart/form-data">
<form:hidden path="id"/>
<table>
<tr>
<td><form:label path="name">Name</form:label></td>
<td><form:input path="name"/></td>
</tr>
<tr>
<td><form:label path="surname">Surname</form:label></td>
<td><form:input path="surname"/></td>
</tr>
<tr>
<td><form:label path="ssn">SSN</form:label></td>
<td><form:input path="ssn"/></td>
</tr>
<tr>
<td><form:label path="technology">Known Technology</form:label></td>
<td><form:input path="technology"/></td>
</tr>
<tr>
<td><form:label path="media">Found us on</form:label></td>
<td><form:input path="media"/></td>
</tr>
<tr>
<td><form:label path="cv">Select a cv</form:label></td>
<td><input type="file" name="cv" /></td>
</tr>
<tr>
<td><form:label path="activeCV">Active CV</form:label></td>
<td><form:checkbox path="activeCV" /></td>
</tr>
<tr>
<td><input type="submit" value="Submit"/></td>
</tr>
</table>
</form:form>
</body>
In my POM:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
EDIT 1 (question):
Would there be even a way of preventing Spring from trying to convert MultipartFile to Blob at "Submit-time", triggering this operation sooner, having the POST method already manage the Candidate (with Blob field already set) object?
EDIT 2:
as suggested by JB Nizet, I tried to use a support POJO, which has the field CV of the type MultipartFile, to store temporarily what I post via form (text fields + file field), and I don't get that exception anymore, because at "Submit-time" the populated object has the cv field of the type of the uploaded file:
import org.springframework.web.multipart.MultipartFile;
public class CandidatePOJO {
private Long id;
private String ssn;
private String name;
private String surname;
private String technology;
private String media;
private MultipartFile cv;
private boolean activeCV;
#Override
public String toString() {
return "CandidatePOJO [id=" + id + ", ssn=" + ssn + ", name=" + name + ", surname=" + surname + ", technology="
+ technology + ", media=" + media + ", cv=" + cv + ", activeCV=" + activeCV + "]";
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getSsn() {
return ssn;
}
public void setSsn(String ssn) {
this.ssn = ssn;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getTechnology() {
return technology;
}
public void setTechnology(String technology) {
this.technology = technology;
}
public String getMedia() {
return media;
}
public void setMedia(String media) {
this.media = media;
}
public MultipartFile getCv() {
return cv;
}
public void setCv(MultipartFile cv) {
this.cv = cv;
}
public boolean isActiveCV() {
return activeCV;
}
public void setActiveCV(boolean activeCV) {
this.activeCV = activeCV;
}
}
in controller, now my first concern is to see whether the pojo can be correctly instantiated, so my GET-POST pair is:
#GetMapping("/updateCandidate/{id}")
public String showUpdateUserForm(#PathVariable("id") Long id, Model model) {
CandidatePOJO candidatePOJO = new CandidatePOJO();
candidatePOJO.setId(id);
model.addAttribute("candidateForm", candidatePOJO);
return "updateCandidateForm";
}
#PostMapping("/updateCandidate/updateCandidateResult")
public String updateCandidate(#ModelAttribute("candidateForm") CandidatePOJO candidatePOJO) {
System.out.println("CANDIDATE POJO");
System.out.println(candidatePOJO.toString()); // here I notice id = null
/* MultipartFile to Blob conversion */
// MultipartFile file = candidatePOJO.getCv();
// InputStream iStream = file.getInputStream();
// long size = file.getSize();
// Session session = emf.unwrap(Session.class);
// Blob cv = Hibernate.getLobCreator(session).createBlob(iStream, size);
/* instantiating the entity object to be freezed in db */
// Candidate candidate = new Candidate();
// set all data from candidatePOJO..
// candidate.setCv(cv);
// service.addOrUpdateCandidate(candidate);
return "updateCandidateResult";
}
and I get a CandidatePOJO object with no id set. I don't manage to have the id pass from GET to POST. Does anyone know what is gong wrong?
EDIT 3:
after many days I opted for the solution with a support POJO, unbelievably I am noticing that the ID is passed from the GET method to the POST one (I haven't changed anything, I have just performed the classical Maven project cleaning as I did when I posted my issue). Unluckily I am facing now another exception (after restoring the code previously commented in the POST method, of course):
javax.persistence.PersistenceException: Hibernate cannot unwrap EntityManagerFactory as 'org.hibernate.Session'
How to fix that?
EDIT 4:
Exception just above solved replacing:
Session session = emf.unwrap(Session.class);
with:
EntityManager em = emf.createEntityManager();
Session session = (Session) em.getDelegate();
BY USING SUPPORT POJO, I finally solved. Indeed I had already solved earlier, by code. The code in the post is right (EDIT 2). When I often performed Maven project cleaning, this didn't discover the errors. I performed it in the last hours and unbelievably my code worked. I can't guess the magic :D I don't know what really happened. By code, I solved in two different ways. First:
#Autowired
private EntityManagerFactory emf;
// ........
#GetMapping("/updateCandidate/{id}")
public String showUpdateUserForm(#PathVariable("id") Long id, Model model) {
Candidate candidate = service.getCandidate(id).get();
CandidatePOJO candidatePOJO = new CandidatePOJO();
candidatePOJO.setId(id);
candidatePOJO.setName(candidate.getName());
candidatePOJO.setSurname(candidate.getSurname());
candidatePOJO.setSsn(candidate.getSsn());
candidatePOJO.setMedia(candidate.getMedia());
candidatePOJO.setTechnology(candidate.getTechnology());
candidatePOJO.setActiveCV(candidate.isActiveCV());
model.addAttribute("candidateForm", candidatePOJO);
return "updateCandidateForm";
}
#PostMapping("/updateCandidate/updateCandidateResult")
public String updateCandidate(#ModelAttribute("candidateForm") CandidatePOJO candidatePOJO) throws IOException {
MultipartFile file = candidatePOJO.getCv();
InputStream iStream = file.getInputStream();
long size = file.getSize();
EntityManager em = emf.createEntityManager();
Session session = (Session) em.getDelegate();
Blob cv = Hibernate.getLobCreator(session).createBlob(iStream, size);
Candidate candidate = new Candidate();
candidate.setId(candidatePOJO.getId());
candidate.setName(candidatePOJO.getName());
candidate.setSurname(candidatePOJO.getSurname());
candidate.setSsn(candidatePOJO.getSsn());
candidate.setMedia(candidatePOJO.getMedia());
candidate.setTechnology(candidatePOJO.getTechnology());
candidate.setActiveCV(candidatePOJO.isActiveCV());
candidate.setCv(cv);
service.addOrUpdateCandidate(candidate);
return "updateCandidateResult";
}
Second (with the same GET):
#PostMapping("/updateCandidate/updateCandidateResult")
public String updateCandidate(#ModelAttribute("candidateForm") CandidatePOJO candidatePOJO) throws IOException, SerialException, SQLException {
MultipartFile file = candidatePOJO.getCv();
Blob cv = new SerialBlob(file.getBytes());
Candidate candidate = new Candidate();
candidate.setId(candidatePOJO.getId());
candidate.setName(candidatePOJO.getName());
candidate.setSurname(candidatePOJO.getSurname());
candidate.setSsn(candidatePOJO.getSsn());
candidate.setMedia(candidatePOJO.getMedia());
candidate.setTechnology(candidatePOJO.getTechnology());
candidate.setActiveCV(candidatePOJO.isActiveCV());
candidate.setCv(cv);
service.addOrUpdateCandidate(candidate);
return "updateCandidateResult";
}
Being new to Spring, I don't know the differences yet. I would appreciate a lot an explanation. Moreover, I want to modify, sooner or later, this code, in order to get rid of the support POJO and to work with just the entity objects: if anyone can solve my initial issue, I would be forever grateful!
i browse "http://localhost:8080/subject/form" for fill information in Subjectform.jsp, after will direct "http://localhost:8080/subject/add" for insert subject object in table subject. But it not insert subject object and encouter following error:
null<br/>
edu.java.spring.controller.SubjectController.addSubject(SubjectController.java:5
0)<br/>
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)<br/>
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)<br
/>
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.jav
a:43)<br/>
java.lang.reflect.Method.invoke(Method.java:497)<br/>
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHa
ndlerMethod.java:215)<br/>
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(I
nvocableHandlerMethod.java:132)<br/>
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMet
hod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)<br/>
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapt
er.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)<br/>
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapt
er.handleInternal(RequestMappingHandlerAdapter.java:689)<br/>
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(A
bstractHandlerMethodAdapter.java:83)<br/>
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.j
ava:938)<br/>
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.ja
va:870)<br/>
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet
.java:961)<br/>
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:86
3)<br/>
javax.servlet.http.HttpServlet.service(HttpServlet.java:707)<br/>
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:8
37)<br/>
javax.servlet.http.HttpServlet.service(HttpServlet.java:790)<br/>
org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:801)<br/>
org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:587)<br/>
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)<br
/>
org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)<br/>
org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223
)<br/>
org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:112
6)<br/>
org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)<br/>
org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
<br/>
org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1060
)<br/>
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)<br
/>
org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerC
ollection.java:215)<br/>
org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java
:110)<br/>
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:113)<
br/>
org.eclipse.jetty.server.Server.handle(Server.java:509)<br/>
org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:288)<br/>
org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:240)<br/>
org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:539)<br/>
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:620)
<br/>
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:540)<
br/>
java.lang.Thread.run(Thread.java:745)<br/>
Here file SubjectController.class
#Controller
public class SubjectController {
#Autowired
public StudentDAO studentDao;
public SubjectDao subjectDao;
#RequestMapping(value = "subject/form",method = RequestMethod.GET)
public ModelAndView subjectForm (){
ModelAndView model = new ModelAndView("SubjectForm", "subject", new Subject());
List<Student> students = studentDao.listStudents();
Map<Integer,String> map = new HashMap<Integer,String>();
for(int i=0;i<students.size();i++){
map.put(students.get(i).getId(), students.get(i).getName());
}
model.getModelMap().put("studentList",map);
return model;
}
#RequestMapping(value="subject/add",method = RequestMethod.POST)
public void addSubject(#Valid #ModelAttribute("subject")Subject subject){
// ModelAndView model = new ModelAndView("redirect:/subject/list");
subjectDao.insert(subject);
// return model;
}
Here file SubjectHibernateDaoImpl.class
public class SubjectHibernateDaoImpl implements SubjectDao {
#Autowired
public LocalSessionFactoryBean sessionFactory;
#Override
public void insert(Subject subject){
Session session = sessionFactory.getObject().openSession();
try {
session.save(subject);
session.flush();
} finally {
// TODO: handle finally clause
session.close();
}
}
public List<Subject> listSubject() {
// TODO Auto-generated method stub
Session session = sessionFactory.getObject().openSession();
Query query = session.createQuery("from Subject");
try {
return query.list();
} finally {
// TODO: handle finally clause
session.close();
}
}
Here file Subject.class
#Entity
#Table(name = "subject",uniqueConstraints={#UniqueConstraint(columnNames="id")})
public class Subject {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column(name = "title", nullable = false, length = 200)
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Column(name = "student", nullable = false)
public int getStudent() {
return student;
}
public void setStudent(int student) {
this.student = student;
}
#Column(name = "score", nullable = false)
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public int id;
public String title;
public int student;
public int score;
}
Here file Subject.jsp
<html>
<head>
<title>Add New Subject Information</title>
</head>
<body>
<h2>Please Input Subject Information</h2>
<form:form method="POST" modelAttribute="subject" action="add">
<table>
<tr>
<td><form:label path="student">Student</form:label></td>
<td><form:input path="student" type = "number"/></td>
</tr>
<tr>
<td><form:label path="title">Title</form:label></td>
<td><form:input path="title"/></td>
</tr>
<tr>
<td><form:label path="score">Score</form:label></td>
<td><form:input path="score" type = "number"/></td>
</tr>
<tr>
<td colspan="3"><input type="submit" value="Submit"/></td>
</table>
</form:form>
</body>
</html>
Looks like you forgot to add the #Autowired annotation. It's present for the studentDao but not for the subjectDao, resulting in that object not being initialized.
I have written a program to display some details entered in one form in another.Like I have a UserRegisteration.jsp where I am entering few details and UserAccount.jsp which has to display some of the entered details.I have created a model object UserDetails which has all the details of a particular code.
When I am running the project I am getting the propertynotfound exception.I have checked everything and couldn't find the reason behind it.I have the getters and setters methods in my model class.And using auto-binding feature using #modelattribute.Kindly let me know if I missed any code.
UserDetails.java
package com.bindu.myBankcontroller;
import java.util.ArrayList;
public class UserDetails {
private String UserName;
private String FirstName;
private String LastName;
private String EmailId;
private ArrayList<String> AccountType;
private ArrayList<String> gender;
private Long AccountNo;
private int age;
private String password;
Address address;
public String getUserName() {
return UserName;
}
public void setUserName(String userName) {
UserName = userName;
}
public String getFirstName() {
return FirstName;
}
public void setFirstName(String firstName) {
FirstName = firstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String lastName) {
LastName = lastName;
}
public String getEmailId() {
return EmailId;
}
public void setEmailId(String emailId) {
EmailId = emailId;
}
public ArrayList<String> getAccountType() {
return AccountType;
}
public void setAccountType(ArrayList<String> accountType) {
AccountType = accountType;
}
public ArrayList<String> getGender() {
return gender;
}
public void setGender(ArrayList<String> gender) {
this.gender = gender;
}
public Long getAccountNo() {
return AccountNo;
}
public void setAccountNo(Long accountNo) {
AccountNo = accountNo;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
Controller class,UserAccountController.java
package com.bindu.myBankcontroller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.*;
import org.springframework.stereotype.*;
import org.springframework.web.servlet.ModelAndView;
import com.bindu.myBankcontroller.UserDetails;
#Controller
public class UserAccountController {
#ModelAttribute
public void addingCommonObjects(Model model1) {
model1.addAttribute("headerMessage", "MyBank, India");
}
#RequestMapping(value="/LoginForm.html", method = RequestMethod.GET)
public ModelAndView getAdmissionForm() {
ModelAndView model1 = new ModelAndView("LoginForm");
return model1;
}
#RequestMapping(value="/userRegistration.html", method = RequestMethod.GET)
public ModelAndView submitRegistrationForm() {
ModelAndView model1 = new ModelAndView("UserRegistration");
return model1;
}
#RequestMapping(value="/UserAccount.html", method = RequestMethod.POST)
public ModelAndView userAccountForm(#ModelAttribute("user") UserDetails user) {
System.out.println("User name:"+user.getUserName());
ModelAndView model1 = new ModelAndView("UserAccount");
return model1;
}
}
UserAccount.jsp
<html>
<body>
<h1>${headerMessage}</h1>
<h3>Congratulations!! you have successfully registered</h3>
<h2>Details submitted by you:: </h2>
<table>
<tr>
<td>User Name :</td>
<td>${user.UserName}</td>
</tr>
<tr>
<td>First Name :</td>
<td>${user.FirstName}</td>
</tr>
<tr>
<td>Last Name :</td>
<td>${user.LastName}</td>
</tr>
</table>
</body>
</html>
None of the related posts helped me in resolving this issue, so I have posted this one.
The problem is cause by the way you are accessing your property in jsp,
${user.UserName}
should instead be
${user.userName}
Same for the other expressions, you should lower case the first letter.
Behind the scenes the UserDetails is introspected and a map of properties is created, but the keys are based on your getter/setter methods, so lowercased (userName, firstName, lastName). In your JSP EL you're passing the key, and it is not matching any property on account of case difference
Your instance variables do not respect the java naming principles. Java variables should start with lower letter and use camel case capitalization.
Ex: userName, firstName, lastName,
and the corresponding getters would be getUserName(), getFirstName(), getLastName().
If you have the instance variable defined like this the jsp accessors will be obtained by stripping the get (or is, if the method returns a boolean) suffix and lower the first letter of the remaining method name: ${user.userName}, ${user.firstName}, ${user.lastName}.
Since I've decided to use same JSP for adding and editing posts, I just pass an attribute "saveUrl" which defines the action for my form in the JSP. Adding a new post works fine, but when editing a post, the object returned to the controller is missing all attributes except for the description.
What am I missing or doing wrong here?
Thanks for help!
My controller:
#Controller
public class BlogController {
private static final Logger logger = LoggerFactory.getLogger(BlogController.class);
#Autowired
private BlogPostManager bpManager;
#Autowired
private UserManager usrManager;
.....
#RequestMapping(value = "addPost", method = RequestMethod.GET)
public String addPost(Locale locale, Model model, Principal principal) {
model.addAttribute("post", new BlogPostEntity());
/** some more code here **/
return "addEditPost";
}
#RequestMapping(value = "addPostProcess", method = RequestMethod.POST)
public String addPostProcess(Locale locale, Model model, Principal principal, #ModelAttribute("post") BlogPostEntity blogPost) {
blogPost.setDate(new Date());
blogPost.setAuthor(usrManager.getUser(principal.getName()));
bpManager.addBlogPost(blogPost);
return "redirect:/latest";
}
#RequestMapping(value = "editPost/{id}", method = RequestMethod.GET)
public String editPost(Locale locale, Model model, Principal principal, #PathVariable Integer id) {
model.addAttribute("post", bpManager.getBlogPost(id));
model.addAttribute("username", getUsername(principal));
model.addAttribute("saveUrl", "");
return "addEditPost";
}
#RequestMapping(value = "editPost/{id}", method = RequestMethod.POST)
public String editPostProcess(Locale locale, Model model, Principal principal, #ModelAttribute("post") BlogPostEntity blogPost) {
bpManager.updateBlogPost(blogPost);
return "redirect:/latest";
}
/** some private methods **/
}
addEditPost.jsp
NOTE: this jsp is acting as a body of Apache tiles.
<h2>Create new post:</h2>
<form:form modelAttribute="post" action="${saveUrl}" method='POST'>
<table>
<tr>
<td><form:label path="title">Title:</form:label></td>
<td><form:input path="title"></form:input></td>
</tr>
<tr>
<td><form:label path="description">Description:</form:label></td>
<td><form:input path="description"></form:input></td>
</tr>
<tr>
<td><form:label path="text">Text:</form:label></td>
<td><form:input path="text"></form:input></td>
</tr>
<tr>
<td><input value="Save" type="submit"></td>
<td></td>
</tr>
</table>
</form:form>
The mapped BlogPost class:
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "BLOGPOST")
public class BlogPostEntity {
#Id
#GeneratedValue
#Column(name = "ID")
private int id;
#Column(name = "TITLE", nullable = false, length = 100)
private String title;
#Column(name = "DESCRIPTION", length = 500)
private String description;
#Column(name = "TEXT", length = 5000)
private String text;
#Column(name = "DATE")
private Date date;
#ManyToOne(targetEntity = UserEntity.class)
#JoinColumn(name = "authorid", referencedColumnName = "id")
private UserEntity author;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public int getId() {
return id;
}
public void setAuthor(UserEntity author) {
this.author = author;
}
public UserEntity getAuthor() {
return author;
}
}
DAO for blogpost:
import java.util.ArrayList;
import java.util.List;
import org.danizmax.simpleblog.entity.BlogPostEntity;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
#Repository("blogpostdao")
public class BlogPostDaoImpl implements BlogPostDao {
#Autowired
private SessionFactory sessionFactory;
#Override
public void addBlogPost(BlogPostEntity blogPost) {
getSession().persist(blogPost);
}
#Override
public void removeBlogPost(int id) {
BlogPostEntity entity = (BlogPostEntity) sessionFactory.getCurrentSession().load(BlogPostEntity.class, id);
if (entity != null) {
getSession().delete(entity);
}
}
#Override
#SuppressWarnings("unchecked")
public List<BlogPostEntity> latest() {
List<BlogPostEntity> result = new ArrayList<BlogPostEntity>();
try {
result = getSession().createQuery("FROM BlogPostEntity ORDER BY 'id' desc LIMIT 5;").list();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
#Override
#SuppressWarnings("unchecked")
public List<BlogPostEntity> listPosts(int userId) {
List<BlogPostEntity> result = new ArrayList<BlogPostEntity>();
try {
result = getSession().createQuery("FROM UserEntity").list();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
#Override
public void updateBlogPost(BlogPostEntity blogPost) {
blogPost = getBlogPost(blogPost.getId());
getSession().update(blogPost);
}
#Override
public BlogPostEntity getBlogPost(int id) {
return (BlogPostEntity) getSession().get(BlogPostEntity.class, id);
}
private Session getSession() {
return sessionFactory.getCurrentSession();
}
}
UPDATE: I've been experimenting a bit and tried method from HERE, but the object returned to the controler was still empty.
Then I changed the saveURL in JSP to (I read it might be important HERE):
<c:url var="addUrl" value="/secure/postProcess"/>
<form:form modelAttribute="post" action="${addUrl}" method='POST'>
and now the object is filled, only the id is still empty. So there is something probably wrong with the JSP.
This question already has answers here:
c:forEach throws javax.el.PropertyNotFoundException: Property 'foo' not found on type java.lang.String
(3 answers)
Closed 7 years ago.
I'm getting the error above.
What i'm trying to do is write an app that takes in an unknown number of names, then prints them out on a new page. This is supposed to be for a bowling scoring app, but for now I just want to get a list of names. The idea is for each name to go into a player object, then in turn be stored in the players arraylist. If anyone can help, I would appreciate it.
This is my controller code:
package multiplayergame;
import java.util.ArrayList;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
#Controller
#SessionAttributes
public class MultiplayerController {
int score;
int roll;
Game game = new Game();
GameProperties gameProps = new GameProperties();
int playerNo = 0;
ArrayList<PlayerGame> players = new ArrayList<>();
PlayerGame player;
#RequestMapping(value = "/home", method = RequestMethod.GET)
public ModelAndView home() {
return new ModelAndView("home", "command", gameProps);
}
#RequestMapping(value = "/nextName", method = { RequestMethod.POST, RequestMethod.GET})
public ModelAndView homeNext(MContact mcontact, BindingResult result) {
player = new PlayerGame();
player.setName(mcontact.getName());
players.add(player);
gameProps.setPlayers(players);
playerNo++;
return new ModelAndView("home", "command", gameProps);
}
#RequestMapping(value = "/test", method = RequestMethod.POST)
public ModelAndView playNext(GameProperties gameProps2, ModelMap model) {
model.addAttribute("players", gameProps.getPlayers());
model.addAttribute("name", gameProps.getPlayers().get(playerNo).getName());
return new ModelAndView("test", "players", gameProps2);
}
}
This holds details for each player:
package multiplayergame;
public class PlayerGame {
private int score;
private int pins;
private String name;
private int roll;
private int nOfPlayers;
private int playerNo;
Game game = new Game();
public Game getGame() {
return game;
}
public void setGame(Game game) {
this.game = game;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public int getPins() {
return pins;
}
public void setPins(int pins) {
this.pins = pins;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getRoll() {
return roll;
}
public void setRoll(int roll) {
this.roll = roll;
}
public int getnOfPlayers() {
return nOfPlayers;
}
public void setnOfPlayers(int nOfPlayers) {
this.nOfPlayers = nOfPlayers;
}
public int getPlayerNo() {
return playerNo;
}
public void setPlayerNo(int playerNo) {
this.playerNo = playerNo;
}
}
This is the code for all Game properties, such as scoring etc.
package multiplayergame;
import java.util.ArrayList;
public class GameProperties {
private int score;
private int pins;
private String name;
private int roll;
private int nOfPlayers;
PlayerGame player;
private ArrayList<PlayerGame> players;
private int playerNo;
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public int getPins() {
return pins;
}
public void setPins(int pins) {
this.pins = pins;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getRoll() {
return roll;
}
public void setRoll(int roll) {
this.roll = roll;
}
public int getnOfPlayers() {
return nOfPlayers;
}
public void setnOfPlayers(int nOfPlayers) {
this.nOfPlayers = nOfPlayers;
}
public ArrayList<PlayerGame> getPlayers() {
return players;
}
public void setPlayers(ArrayList<PlayerGame> players) {
this.players = players;
}
public int getPlayerNo() {
return playerNo;
}
public void setPlayerNo(int playerNo) {
this.playerNo = playerNo;
}
}
The following are my JSP files, the output first:
<%# taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>Test output</title>
</head>
<body>
<h2>Test Roll</h2>
<c:forEach var="player" items="players">
Name <c:out value="${player.name}"/><p>
</c:forEach>
</body>
</html>
This is the home page:
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<title>Bowling</title>
</head>
<body>
<h2>Welcome players!</h2>
<h2>Please enter your names.</h2>
<form:form method="post" action="/multiplayergame/nextName">
<table>
<tr>
<td><form:label path="name">Name</form:label></td>
<td><form:input path="name" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" name = "button" value="Next Player"/>
</td>
</tr>
</table>
</form:form>
<form:form method="post" action="/multiplayergame/test">
<tr>
<td colspan="2">
<input type="submit" name = "button" value="Play"/>
</td>
</tr>
</form:form>
</body>
</html>
Change this <c:forEach var="player" items="players"> to <c:forEach var="player" items="${players}">
As your referring "players" string. it is trying to find the property name in string.