How do I upload a file to a Spring MVC controller - spring

I am trying to pass the resume back to the Spring MVC controller. I have created a user class that saves resume/files
public class User {
private int id;
private String firstName;
private String lastName;
private String city;
private String state;
private String zip;
private String username;
private String password;
private int enabled;
private byte[] resume;
//getters/setters for them all
and the controller to take in the uploaded form from the site
#Controller
#RequestMapping(value = "/user")
public class UserController {
UserDao uDao;
#Inject
public UserController(UserDao uDao) {
this.uDao = uDao;
}
#RequestMapping(value = "/profile", method = RequestMethod.GET)
public String postPage(Principal principal, Map model) {
String name = principal.getName();
User u = uDao.getByUsername(name);
String fName = u.getFirstName();
String lName = u.getLastName();
String city = u.getCity();
String state = u.getState();
String zip = u.getZip();
String bc = u.getBootcampAttended();
model.put("fName", fName);
model.put("lName", lName);
model.put("city", city);
model.put("state", state);
model.put("zip", zip);
model.put("bc", bc);
return "user";
}
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public String Upload(#RequestParam("file") MultipartFile file, Principal principal) throws IOException {
if (!file.isEmpty()) {
byte[] bytes = file.getBytes(); // alternatively, file.getInputStream();
// application logic
String name = principal.getName();
User u = uDao.getByUsername(name);
u.setResume(bytes);
uDao.update(u);
return "user";
}
return "user";
}
}
I am trying to pass the resume to display as a clickable file on the jsp in the postPage method. Here is the jsp
<h1>${fName}</h1>
<h1>${lName}</h1>
<h1>${state}</h1>
<h1>${city}</h1>
<h1>${zip}</h1>
<h1>${bc}</h1>
<form method="POST" action="${pageContext.request.contextPath}/user/upload" enctype="multipart/form-data">
<table border="0">
<tr>
<td>Pick file #1:</td>
<td><input type="file" name="file" size="50" /></td>
<td><input type="submit" value="Upload"/>
</tr>
</table>
</form>
Any tips on how to get the file on the Spring MVC controller. Preferably to be the value of the file input as default, instead of it saying "No File Chosen". Was thinking that maybe I could convert the file back into the MultiPartFile, like how I uploaded it, but im not sure how to pass that back to the Spring MVC controller.
Thanks!

Related

NullPointException while uploading file in spring

I try to upload a .csv file's data into database, but when i upload and submit it, it throws nullpointexception. Means, when I print name in controller, name is printed, but when i try to get the file, it show null.
FileUpload model class
public class FileUpload {
private CommonsMultipartFile[] files;
private String name;
// Getters and setters
}
Controller
#RequestMapping(value = "uploadPage", method = RequestMethod.GET)
public ModelAndView uploadPage() {
ModelAndView model = new ModelAndView("upload_page");
FileUpload formUpload = new FileUpload();
model.addObject("formUpload", formUpload);
return model;
}
#RequestMapping(value = "/doUpload", method = RequestMethod.POST)
public String doUpload(#ModelAttribute("formUpload") FileUpload fileUpload, BindingResult result) throws IOException, JAXBException {
System.out.println("myfirl "+fileUpload.getFiles()); // output is null
System.out.println("name "+fileUpload.getName()); // name is displaying
//other stuffs
}
upload_page
<spring:url value="/doUpload" var="doUploadURL"/>
<form:form method="post" modelAttribute="formUpload" action="${doUploadURL }" enctype="multipart/form-data">
<form:input path="files" type="file" multiple="multiple"/>
<form:input path="name" type="text"/>
<button type="submit">Upload</button>
</form:form>
WebConfig
#Bean(name="multipartResolver")
public CommonsMultipartResolver getResolver(){
CommonsMultipartResolver commonsMultipartResolver=new CommonsMultipartResolver();
commonsMultipartResolver.setMaxUploadSizePerFile(20*1024*1024);
return commonsMultipartResolver;
}
I tried to sort it out in many ways, but failed. Anyone try to sort it out? Thanks in advance
#RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
#ResponseBody
public String uploadFileHandler(#RequestParam("file") MultipartFile file) {
if (!file.isEmpty()) {
System.out.println(file.getName);
}
}
or you can do that
#RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public String uploadFileHandler(MultipartHttpServletRequest request) {
Iterator<String> itr = request.getFileNames();
while (itr.hasNext()){
System.out.println(itr.next().toString());
}
....
}

Springboot and thymealf loop

hope you can help with this simple noob problem. I creating a Multiple choice question using springboot and thymeleaf.I am getting this error and hope you can help me write the controller method.
Error during execution of processor 'org.thymeleaf.spring4.processor.attr.SpringInputGeneralFieldAttrProcessor' (learning:23)
Neither BindingResult nor plain target object for bean name 'options[0]' available as request attribute
<form method="post" th:action="#{/list}" >
<table>
<tr th:each="option, rowStat : *{a}">
<td><input type="radio" th:field="*{options[__${rowStat.index}__].ansA}" th:value="A"/></td>
<td><input type="radio" th:field="*{options[__${rowStat.index}__].ansB}" th:value="B"/></td>
</tr>
</table>
<input type="submit" value="ok"/>
</form>
Model object
#Entity
public class LearningStyle {
private int Qid;
private String question;
private String ansA;
private String ansB;
public LearningStyle(int qid, String question, String ansA, String ansB) {
Qid = qid;
this.question = question;
this.ansA = ansA;
this.ansB = ansB;
}
public LearningStyle(){}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Qid", nullable = false, updatable = false)
public int getQid() {
return Qid;
}
public void setQid(int qid) {
Qid = qid;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public String getAnsA() {
return ansA;
}
public void setAnsA(String ansA) {
this.ansA = ansA;
}
public String getAnsB() {
return ansB;
}
public void setAnsB(String ansB) {
this.ansB = ansB;
}
}
Controller
public class LearningStyleController {
#Autowired
LearningStyleService learningstyleservice;
#RequestMapping("/list")
public String learningstyle(Model model) {
List<LearningStyle> a= learningstyleservice.findAll();
model.addAttribute("a",a);
return "learning";
}
#RequestMapping(value = "/list", method = RequestMethod.POST)
public String learn(#ModelAttribute("a") LearningStyle learningStyle, Model model) {
//code to get list of object
return "home";
}

how do I pass the selected parameters in the checkbox from one jsp page to another jsp page?

I have to make the switch to selected values ​​within some checkboxes in a jsp page but after the selection and after pressing the "Send" button, I generate this error with the following description: HTTP Status 400: The request sent by the client was syntactically incorrect.
Where am I wrong?
TaskController.java
#RequestMapping(value="/newTask", method = RequestMethod.GET)
public String task(#ModelAttribute Task task, Model model) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String s = auth.getName();
Student student = studentFacade.retrieveUser(s);
List<Job> jobs = new ArrayList<>();
if(!(auth instanceof AnonymousAuthenticationToken)) {
jobs = facadeJob.retriveAlljobs();
model.addAttribute("job", getMathRandomList(jobs));
model.addAttribute("image", imageFacade.retriveAllImages());
List<Image> img = imageFacade.retriveAllImages();
task.setImages(img);
task.setStudent(student);
taskFacade.addTask(task);
List<Long> images = new ArrayList<>();
for(Image i : img)
images.add(i.getId());
model.addAttribute("images", images);
}
return "users/newTask";
}
#RequestMapping(value="/taskRecap", method = RequestMethod.POST)
public String taskRecap(#ModelAttribute Task task, Model model,BindingResult result) {
model.addAttribute("task", task);
return "users/taskRecap";
}
newTask.jsp
<form:form method="post" action="taskRecap" modelAttribute="task" name="form">
<form:checkboxes path="images" items="${images}" value="yes" />
<td><input type="submit" value="Send" /></td>
</form:form>
taskRecap.jsp Immages
<c:forEach var="image" items="${task.images}">
<c:out value="${image.id}" />
</c:forEach>
Task.java
#Entity
public class Task {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne
private Student student;
#ManyToMany
List<Image> images;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public Task() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Task(Long id, Student student, List<Image> images) {
super();
this.id = id;
this.student = student;
this.images = images;
}
public List<Image> getImages() {
return images;
}
public void setImages(List<Image> images) {
this.images = images;
}
}
Using Query parameter
<a href="edit.jsp?Name=${user.name}" />
Using Hidden variable .
<form method="post" action="update.jsp">
<input type="hidden" name="Name" value="${user.id}">
if you use either of the first 2 methods you can access your value like this:
String userid = session.getParameter("Name");
you can send Using Session object.
session.setAttribute("Name", UserName);
These values will now be available from any jsp as long as your session is still active.
if you use the third option you can access your value like this:
String userid = session.getAttribute("Name");

Spring MVC form setting fields as null

I´m studying Spring MVC with Tiles 3, JPA and all other cool stuff. I created a form to send data, below is the form:
<form:form method="POST" action="/users/save" enctype="multipart/form-data" modelAttribute="formUsuario">
<form:label path="username" for="username">Username</form:label>
<form:input type="text" id="username" path="username" class="span4" value="${user.username}" />
<form:label path="firstName" for="firstName">First name</form:label>
<form:input type="text" id="firstName" path="firstName" class="span4" value="${user.firstName}" />
</form:form>
The method inside the controller to add a new record:
#Secured("ROLE_USER")
#RequestMapping(value = "/new", method = RequestMethod.GET)
public String getNew(#ModelAttribute("formUsuario") br.com.rodrigoferra.domain.User user) {
logger.info("Add new user");
return "users/edit";
}
The method to save the new record:
#Secured("ROLE_USER")
#RequestMapping(value = "/save", method = RequestMethod.POST)
public #ResponseBody String doSave(#ModelAttribute("formUsuario") br.com.rodrigoferra.domain.User user, BindingResult results, Model model) {
if(results.hasErrors()) {
return "users/edit";
}
user = userRepository.save(user);
logger.info("Username: " + user.getUsername());
return "redirect:/users/";
}
It is saving the record, but it is saving everything as Null! The data from the form is being received by the controller. I searched a lot and found the same examples as this, but I can't get mine to work!
Is there any configuration I've missed?
Thanks and sorry for my bad english.
Edited:
Users bean:
#Entity(name="users")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue( strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
#Column(unique=true)
private String username;
private String password;
#Transient
private String passwordConfirmation;
private Date birthdate;
private String signature;
private String email;
private String sex;
private int active;
Use Firebug or similar tool to see if the form field values are correctly included in the request, and the request is sent to correct URI.
Log (or debug) and check the user object content right after receiving the request, in doSave().
Log (or debug) and check the user object content in userRepository.save() to make sure all values are available, prior to persisting it.
Following could be the actual reason, but first checking above would iron out other possiblities
Remove enctype="multipart/form-data" in form definition as this form does not intend to send binary data.
Check following for more info on that:
What does enctype='multipart/form-data' mean?
Form content types in HTML 4 spec
Multipart form data encoding in HTML 5 spec

Spring MVC Pre Populate Checkboxes

First little background info. Got a fairly standard User Role relationship where the User can have many roles. I have roles defined as a set within the user class. Now I know that html forms have all the values as strings and trying to get values as my custom Role object does not work. I implemented an initbinder to convert the id's back into object so that I can retrieve the selected values off of my checkboxes, that part works.
But I can't seem to go back the other way. I retrieve a User from the database that already has roles and want to pre populate role checkboxes with all the roles that a user has. Based on this example :
Checkboxes example
They say that:
form:checkboxes items="${dynamic-list}" path="property-to-store"
For multiple checkboxes, as long as the “path” or “property” value is
equal to any of the “checkbox values – ${dynamic-list}“, the matched
checkbox will be checked automatically.
My interpretation of that is I should be able to feed it a Set of all the roles and define the path to be the roles from the User object and it should match them thus causing the check box to pre populate.
Every example out there seems to have the value of dynamic-list as a String[]. Well thats great and dandy but how does this work for custom objects that our defined as a Set? Can I still use this one line definition for checkboxes or do I need to do some kind of data binding heading into the view also?
Here is my user dto, user controller, custom form binder, and user edit page.
User DTO
#Entity
#Table
public class User extends BaseDto
{
#Column(updatable = false) #NotBlank
private String username;
#Column(name = "encrypted_password") #Size(min = 6, message = "password must be at least 6 characters") #Pattern(regexp = "^\\S*$", message = "invalid character detected")
private String password;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column #NotNull
private boolean enabled;
#Column #Email #NotBlank
private String email;
#Transient
private String confirmPassword;
#ManyToMany(targetEntity = Role.class, fetch = FetchType.EAGER, cascade = CascadeType.REFRESH) #JoinTable(name = "user_role", joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles;
public User()
{
}
public User(final String usernameIn, final String passwordIn, final String firstNameIn, final String lastNameIn, final String emailIn, final boolean enabledIn)
{
username = usernameIn;
password = passwordIn;
firstName = firstNameIn;
lastName = lastNameIn;
email = emailIn;
enabled = enabledIn;
}
public String getUsername()
{
return username;
}
public void setUsername(final String usernameIn)
{
username = usernameIn;
}
public String getPassword()
{
return password;
}
public void setPassword(final String passwordIn)
{
password = passwordIn;
}
public String getFirstName()
{
return firstName;
}
public void setFirstName(final String firstNameIn)
{
firstName = firstNameIn;
}
public String getLastName()
{
return lastName;
}
public void setLastName(final String lastNameIn)
{
lastName = lastNameIn;
}
public String getEmail()
{
return email;
}
public void setEmail(final String emailIn)
{
email = emailIn;
}
public String getConfirmPassword()
{
return confirmPassword;
}
public void setConfirmPassword(final String confirmPasswordIn)
{
confirmPassword = confirmPasswordIn;
}
public boolean isEnabled()
{
return enabled;
}
public void setEnabled(final boolean enabledIn)
{
enabled = enabledIn;
}
public Set<Role> getRoles()
{
return roles;
}
public void setRoles(final Set<Role> rolesIn)
{
roles = rolesIn;
}
}
User Controller
#Controller #RequestMapping("/user")
public class UserController
{
#Autowired private UserService userService;
#Autowired private UserDao userDao;
#Autowired private RoleDao roleDao;
#InitBinder
public void bindForm(final WebDataBinder binder)
{
binder.registerCustomEditor(Set.class, "roles", new CustomFormBinder<RoleDao>(roleDao, Set.class));
}
#RequestMapping(method = RequestMethod.GET)
public String index(final ModelMap modelMap)
{
return "/user/index";
}
#RequestMapping(value = "/create", method = RequestMethod.GET)
public String create(final ModelMap modelMap)
{
modelMap.addAttribute("userInstance", new User());
modelMap.addAttribute("validRoles", new HashSet<Role>(roleDao.findAll()));
return "/user/create";
}
#RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(final ModelMap modelMap, #Valid #ModelAttribute("userInstance") final User user, final BindingResult bindingResult)
{
// TODO move to service validation
if (user.getPassword() == null || !user.getPassword().equals(user.getConfirmPassword()) )
{
bindingResult.addError(new FieldError("userInstance", "password", "password fields must match"));
bindingResult.addError(new FieldError("userInstance", "confirmPassword", "password fields must match"));
}
if (user.getRoles() == null || user.getRoles().isEmpty())
{
bindingResult.addError(new FieldError("userInstance", "roles", "Must select at least one role for a User"));
}
if (bindingResult.hasErrors())
{
modelMap.addAttribute("validRoles", new HashSet<Role>(roleDao.findAll()));
return "/user/create";
}
userService.save(user);
return "redirect:/user/list";
}
#RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
public String edit(#PathVariable final Integer id, final ModelMap modelMap)
{
final User user = userDao.find(id);
if (user != null)
{
modelMap.addAttribute("userInstance", user);
modelMap.addAttribute("validRoles", new HashSet<Role>(roleDao.findAll()));
return "/user/edit";
}
return "redirect:/user/list";
}
#RequestMapping(value = "/edit", method = RequestMethod.GET)
public String editCurrent(final ModelMap modelMap)
{
return edit(userService.getLoggedInUser().getId(), modelMap);
}
#RequestMapping(value = "/update", method = RequestMethod.POST)
public String update(#Valid #ModelAttribute("userInstance") final User user, final BindingResult bindingResult)
{
if (bindingResult.hasErrors())
{
return "/user/edit";
}
userService.save(user);
return "redirect:/user/list";
}
#ModelAttribute("userInstances")
#RequestMapping(value = "/list", method = RequestMethod.GET)
public List<User> list()
{
return userDao.findAll();
}
}
Custom Form Binder
public class CustomFormBinder<T extends GenericDao> extends CustomCollectionEditor
{
private final T dao;
private static final Logger LOG = LoggerFactory.getLogger(CustomFormBinder.class);
public CustomFormBinder(final T daoIn, final Class collectionType)
{
super(collectionType, true);
dao = daoIn;
}
#Override
protected Object convertElement(final Object element)
{
try
{
// forms should return the id as the itemValue
return dao.find(Integer.valueOf(element.toString()));
}
catch (NumberFormatException e)
{
LOG.warn("Unable to convert " + element + " to an integer");
return null;
}
}
}
User Edit View
<html>
<head>
<title>Create User</title>
</head>
<body>
<c:url value="/user/update" var="actionUrl"/>
<form:form method="post" commandName="userInstance" action="${actionUrl}">
<h1>Edit User ${userInstance.username}</h1>
<div>
<form:label path="username">Username:</form:label>
<form:input path="username" id="username" readonly="true"/>
</div>
<div>
<form:label path="password">Password:</form:label>
<form:input path="password" id="password" type="password" readonly="true"/>
<tag:errorlist path="userInstance.password" cssClass="formError"/>
</div>
<div>
<form:label path="firstName">First Name:</form:label>
<form:input path="firstName" id="firstName"/>
<tag:errorlist path="userInstance.firstName" cssClass="formError"/>
</div>
<div>
<form:label path="lastName">Last Name:</form:label>
<form:input path="lastName" id="lastName"/>
<tag:errorlist path="userInstance.lastName" cssClass="formError"/>
</div>
<div>
<form:label path="email">Email:</form:label>
<form:input path="email" id="email" size="30"/>
<tag:errorlist path="userInstance.email" cssClass="formError"/>
</div>
<div>
**<%--Want to Pre Populate these checkboxed--%>
<form:checkboxes title="Assigned Roles:" path="roles" id="roles" items="${validRoles}" itemLabel="displayName" itemValue="id" element="div"/>**
<tag:errorlist path="userInstance.roles" cssClass="formError"/>
</div>
<form:hidden path="enabled"/>
<form:hidden path="id"/>
<form:hidden path="version"/>
<div class="submit">
<input type="submit" value="Update"/>
Cancel
</div>
</form:form>
</body>
</html>
You need a correct implemented equals method for Role!
If this is not enough have a look at class oorg.springframework.web.servlet.tags.form.AbstractCheckedElementTag. The method void renderFromValue(Object item, Object value, TagWriter tagWriter) is where the the checked flag is set.

Resources