I am trying to implement simple fileupload using Spring 4.2.3 and HTML form. I have controller class which handles whole action, simple wrapper class for file, validator and simple view with form in HTML & Thymeleaf. Almost everything is running fine, mapping works properly and view is appearing. But when I select file from disk and press upload button I have NullPointerException. Can anyone have a look and give some tips please? I have to mention that I am novice in Spring.
Controller:
@Controller
public class FileUploadController {
private static String UPLOAD_LOCATION = "C:/Temp/";
@Autowired
FileValidator fileValidator;
@InitBinder("file")
protected void initBinderFileBucket(WebDataBinder binder) {
binder.setValidator(fileValidator);
}
@RequestMapping(value = "/upload", method = RequestMethod.GET)
public String getSingleUploadPage(ModelMap model) {
FileBucket fileModel = new FileBucket();
model.addAttribute("fileBucket", fileModel);
return "views/fileUploader";
}
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public String singleFileUpload(@Valid FileBucket file, BindingResult result, ModelMap model)
throws IOException {
if (result.hasErrors()) {
System.out.println("File Uploader validation error");
return "views/fileUploader";
} else {
System.out.println("Fetching file"); //prints out in console
MultipartFile multipartFile = file.getFile();
System.out.println(multipartFile.getName()); //NullPointer here
return "views/success";
}
}
}
File wrapper:
public class FileBucket {
private MultipartFile file;
//getters & setters + soon other stuff
}
Validator:
@Component
public class FileValidator implements Validator {
public boolean supports(Class<?> clazz) {
return FileBucket.class.isAssignableFrom(clazz);
}
public void validate(Object obj, Errors errors) {
FileBucket file = (FileBucket) obj;
if(file.getFile()!=null){
if (file.getFile().getSize() == 0) {
errors.rejectValue("file", "missingfile");
}
}
}
}
View:
<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:th="http://www.thymeleaf.org"
layout:decorator="templates/baseTemplate">
<head>
<title>Upload Page</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<div layout:fragment="contentPanel" class="form-container">
<h1>Simple upload</h1>
<form method="POST" enctype="multipart/form-data" action="upload" >
<input type="file" name="file" /> <br />
<input type="submit" value="Upload" />
</form>
</div>
<a href="/demo">Demo</a>
</body>
</html>
Stacktrace:
INFO: Starting ProtocolHandler ["http-bio-8080"]
Fetching file
kwi 23, 2016 12:39:36 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [spring] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException
at web.controllers.FileUploadController.singleFileUpload(FileUploadController.java:52)
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:497)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
@InitBinderwon't work because yoursingleFileUploadis missing a@ModelAttributemethod and even then it wouldn't work as your init binder usesfileBuckeras a command object, but your method expects one namedfile. Also in your validator you probably want to validate for anullfile object as well.initBinderand method object name tofileBucket. I have question then - do I need to set any additional attribute in form to match@ModelAttributewhen I add it to a method argument insingleFileUpload? Concerning configuration of multipart support - I have Bean in myContextConfiguration:@Bean public CommonsMultipartResolver commonsMultipartResolver() { return new CommonsMultipartResolver(); }