NullPointException while uploading file in spring - 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());
}
....
}

Related

Args with Spring MVC

I need help to pars args in a method inside my controller.
i have a form for sending my parameter to function
<form method="post" action="/">
<input type="text" id="query" placeholder="file to search ...">
<input type="submit" id="submit" value="fetch!">
</form>
and in my controller :
#RestController
public class mainController {
#RequestMapping(value = "/index", method = RequestMethod.POST)
public String index(Model model) throws IOException, GeneralSecurityException {
DriveQuickstart drive = new DriveQuickstart("c:/temp/credentials.json");
model.addAttribute("query");
String res = drive.checkFile("query");
return res;
the query is a string send via the form. and return res in the same view.
Do you have any tips?
thanks you very mutch
In Spring MVC It will be like this:
#Controller
public class mainController {
#PostMapping( "/index")
public String index(#ModelAttribute FormDataObjectClass object) throws IOException, GeneralSecurityException {
DriveQuickstart drive = new DriveQuickstart("c:/temp/credentials.json");
//model.addAttribute("query");
String name = object.getName();
String address = object.getAddress();
String res = drive.checkFile("query");
return res;
}
Here no need of passing Model as argument as we need a custom Object(FormDataObjectClass) to be used.
Create a class FormDataObjectClass as per you data in HTML form/JQuery post method

Spring form binding return null with many-2-one relationship

Here is the problem, when I try to submit form, user entity returns null.
Form is
<form:form class="g-form" modelAttribute="objView" id="userAssignmentForm">
<form:hidden path="id" value="${objView.id}"/>
${objView.user.id}
<div class="g-form-group required">
<label for="user">User</label>
<form:hidden id="user" path="user" value="${objView.user}"/>
<input type="text" value="${objView.user.userName}" readonly="true"/>
<input type="button" class="import-input" onclick="gImport.showImportUserForm()"/>
</div>
Controller is
#RequestMapping(value = "/create", method = RequestMethod.POST)
public #ResponseBody
String create(
#ModelAttribute("objView") UserAssignmentView objView, BindingResult result,
SessionStatus status,
HttpServletRequest request) throws UnsupportedEncodingException {
UserAssignment obj = new UserAssignment();
obj.setUser(objView.getUser());
userAssignmentService.create(obj);
return "ok";
}
Model is below contains a view entity. What am I missing?
public class UserAssignmentView extends UserAssignment {
public UserAssignmentView() {
}
public UserAssignmentView(UserAssignment obj) {
setId(obj.getId());
setStatus(obj.getStatus());
setUser(obj.getUser());
}
}
And this is form view part of controller
#RequestMapping(value = "/form", method = RequestMethod.POST)
public ModelAndView form(HttpServletRequest request) {
UserAssignment obj = new UserAssignment();
Account account = AccountRegistry.getByHttpSession(request.getSession());
ModelAndView modelAndView = new ModelAndView("forms/userAssignmentForm");
modelAndView.addObject("objView", UserAssignmentWrapper.wrap(obj));
return modelAndView;
}
I could not solve since 3 days, how can I set user to userassignment?

Spring - Model attributes after BindingResult with errors

In the following piece of code I just want to create a new user and link it to the selected groups.
Everything works fine when the user and group are valid. The problem comes when the bindingresult has errors. The controller detects such error (all fine so far) and returns the same view (I want to keep the data entered by the user) but the list of groups is empty (I have discovered that, after showing again the view, userform.groups is null).
Has anyone a clue about what the problem could be?
UserForm
#Component
public class UserForm {
#Valid
private User user;
#Valid
private Collection<Group> allGroups;
// Setters and getters
}
UserController
#Controller
public class UserController {
#Autowired
UserGroupService userGroupService;
#Autowired
BCryptPasswordEncoder passwordEncoder;
#InitBinder
public void initBinder (WebDataBinder binder) {
binder.registerCustomEditor(Set.class, "userform.user.groups", new GroupListEditor(userGroupService));
}
#RequestMapping(value = "/admin/users/CreateUser", method = RequestMethod.GET)
public ModelAndView createUsetGet () {
ModelAndView mav = new ModelAndView("/admin/users/CreateUser");
UserForm userForm = new UserForm();
userForm.setUser(new User());
userForm.setGroups(userGroupService.getAllEnabledGroups());
mav.addObject("userform", userForm);
return mav;
}
#RequestMapping(value = "/admin/users/CreateUser", method = RequestMethod.POST)
public String createUserPost (#Valid #ModelAttribute("userform") UserForm userForm, BindingResult result) {
if (result.hasErrors() == true) {
return "/admin/users/CreateUser";
}
userForm.getUser().setPassword(passwordEncoder.encode(userForm.getUser().getPassword()));
userGroupService.saveUser(userForm.getUser());
return "redirect:/admin/users/ViewUsers";
}
}
CreateUser.jsp (Only piece regarding the groups)
<form:form modelAttribute="userform" method="post">
Username:
<form:input path="user.loginName"/>
<!-- More fields -->
<form:select path="user.groups" multiple="true">
<form:options items="${userform.groups}" itemValue="id" itemLabel="name" />
</form:select>
<button type="submit">Create</button>
</form:form>
Any help is appreciated!
The object gets recreated and values are bound to the resulting object. Which means no group objects.
Also those shouldn't be in the object at all. To solve use a #ModelAttribute annotated method, which will be invoked for each request handling method and create an object and fill the list of groups.
#ModelAttribute
public void init(Model model) {
UserForm userForm = new UserForm();
userForm.setUser(new User());
model.addAttribute("userform", userForm);
model.addAtrribute("groups", userGroupService.getAllEnabledGroups());
}
#RequestMapping(value = "/admin/users/CreateUser", method = RequestMethod.GET)
public String createUsetGet () {
return "/admin/users/CreateUser";
}
#RequestMapping(value = "/admin/users/CreateUser", method = RequestMethod.POST)
public String createUserPost (#Valid #ModelAttribute("userform") UserForm userForm, BindingResult result) {
if (result.hasErrors() == true) {
return "/admin/users/CreateUser";
}
userForm.getUser().setPassword(passwordEncoder.encode(userForm.getUser().getPassword()));
userGroupService.saveUser(userForm.getUser());
return "redirect:/admin/users/ViewUsers";
}
Ofcourse your jsp has to change slightly also.
<form:select path="user.groups" multiple="true">
<form:options items="${groups}" itemValue="id" itemLabel="name" />
</form:select>
There is one drawback of using this approach now the userGroupService.getAllEnabledGroups() is called for each incoming request. This might not be needed. You could store those in the session using the #SessionAttributes annotation on the class.
#Controller
#SessionAttributes("groups")
public class UserController {
#Autowired
UserGroupService userGroupService;
#Autowired
BCryptPasswordEncoder passwordEncoder;
#InitBinder
public void initBinder (WebDataBinder binder) {
binder.registerCustomEditor(Set.class, "userform.user.groups", new GroupListEditor(userGroupService));
}
#ModelAttribute("groups")
public List<Group> groups() {
return userGroupService.getAllEnabledGroups();
}
#ModelAttribute("userform")
public UserForm userform() {
UserForm userForm = new UserForm();
userForm.setUser(new User());
return userForm;
}
#RequestMapping(value = "/admin/users/CreateUser", method = RequestMethod.GET)
public String createUsetGet () {
return "/admin/users/CreateUser";
}
#RequestMapping(value = "/admin/users/CreateUser", method = RequestMethod.POST)
public String createUserPost (#Valid #ModelAttribute("userform") UserForm userForm, BindingResult result, SessionStatus status) {
if (result.hasErrors() == true) {
return "/admin/users/CreateUser";
}
userForm.getUser().setPassword(passwordEncoder.encode(userForm.getUser().getPassword()));
userGroupService.saveUser(userForm.getUser());
status.setComplete();
return "redirect:/admin/users/ViewUsers";
}
}
You will then need, on success, to tell the SessionStatus that you are finished. If you don't do this your session might pollute.
It's because the information about the validation errors is lost after redirect.
You can solve this using RedirectAttributes. Check this tutorial.

Getting CommandBean or form bean object with out #ModelAttribute in spring mvc

I have a requirement of getting commandbean or form bean object into the controller without using #ModelAttribute either from ModelMap or HttpServletRequest or anything else.
My code is:
JSP:
<form:form commandName="user" method="POST"
action="${pageContext.request.contextPath}/user/createUser">
Name:<form:input path="name" />
Password:<form:input path="password" />
<input type="submit"/>
</form:form>
Controller:
#Controller
#RequestMapping("/user")
public class UserController {
#RequestMapping(method = RequestMethod.GET)
public String setupForm(ModelMap model) {
modelMap.addAttribute("user", new User());
return "userRegistration";
}
#RequestMapping(value = "/createUser", method = RequestMethod.POST)
public String createUser(ModelMap model,HttpServletRequest request) {
User user=(User)model.get("user");// Retruns null
//Tried using request object but user object is not available in it.
return "message";
}
}
I tried different ways but nothing worked out.
You can implement a HandlerMethodArgumentResolver to create the bean manually, then (for example) use a WebMvcConfigurerAdapter to declare it. The argument resolvers supportsParameter method should check the expected type of the parameter. After that you can add a parameter in your Controller that is of the desired type.
You can do it by hand like you would do if you did not know the magic of Spring : just the the HttpServletRequest and gets its parameters to feed your User. It could look like :
#RequestMapping(value = "/createUser", method = RequestMethod.POST)
public String createUser(ModelMap model,HttpServletRequest request) {
User user= new User();
String name = request.getParameter("name");
String password = request.getParameter("password");
if (name != null) {
user.setName(name);
}
if (password!= null) {
user.setPassword(password);
}
model.addAttribute("user", user);
//Tried using request object but user object is not available in it.
return "message";
}
Or in a more terse way : user.setName(request.getParameter("name");

NullPointer on Multipartfile with Spring MVC

It seems my case is simple, so I'm guessing the problem is stupid. Nonetheless...I don't see it.
I'm trying to accept the upload of a collection of files and have been looking at this article as a guide:
http://viralpatel.net/blogs/spring-mvc-multiple-file-upload-example/
Here's the form upload client side:
<form:form method="post" action="save.html" modelAttribute="uploadArtifact" enctype="multipart/form-data">
<div class="controls" id="artifacts">
<input type="file" id="uploader" class="multi"/>
</div>
<div>
<input type="submit" value="Upload" />
</div>
</form:form>
Here's the Model/Bean code:
public class ArtifactModel {
private List<MultipartFile> artifacts;
public List<MultipartFile> getArtifacts() {
return artifacts;
}
public void setArtifacts(List<MultipartFile> artifacts) {
this.artifacts = artifacts;
}
}
...and the controller code:
#Controller
public class ArtifactController {
private static Log logger = LogFactory.getLog(ArtifactController.class);
// #Autowired
// ArtifactService artifactService;
#RequestMapping(value = "/getUploadDialog", method = RequestMethod.GET)
public String displayForm() {
return "uploadArtifacts";
}
#RequestMapping(value = "/save", method = RequestMethod.POST)
public void save(
#ModelAttribute("uploadArtifact") ArtifactModel uploadArtifact,
Model map) {
logger.info("Received file upload request with "+uploadArtifact.getArtifacts().size()+" files");
List<MultipartFile> files = uploadArtifact.getArtifacts();
List<String> fileNames = new ArrayList<String>();
if (null != files && files.size() > 0) {
for (MultipartFile multipartFile : files) {
String fileName = multipartFile.getOriginalFilename();
fileNames.add(fileName);
// Handle file content - multipartFile.getInputStream()
logger.info("Received file with filename: " + fileName);
}
}
map.addAttribute("files", fileNames);
}
}
I'm getting a NullPointerException when I attempt to call the getter on the ArtifactModel object which should have come from the uploadArtifact #ModelAttribute parameter...
I've looked in the browser debugger and seen that the client is sending the data...
Suggestions?
I think you're missing an attribute from your file input element.
Try adding:
name='artifacts[0]'

Resources