NullPointer on Multipartfile with Spring MVC - spring

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]'

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

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());
}
....
}

Submit a List from a form generated with JavaScript with a Spring controller [duplicate]

This question already has answers here:
Passing a list generated with Javascript to a Spring controller
(3 answers)
Closed 5 years ago.
I'm building an app with Spring Boot, the MVC pattern, and Thymeleaf as template engine. I have a form that generates a list with JavaScript, and a controller with a #ModelAttribute expecting a list, to be saved into the database.
At the JavaScript side I collect the items with this array:
groupList = [];
groupList.push(inputValue);
function getGroupList(){
return groupList;
}
In the html I'm trying to assign the array value to a hidden input field:
<input type="hidden" class="invisible" id="groupList" th:field="*{groupList}"/>
With this inline function:
<script th:inline="javascript" type="text/javascript">
$(function() {
var groupListCollected = getGroupList();
$("#groupList").val(groupListCollected);
});
</script>
My problem at this point, is that I don't find the way to collect the array, and pass it to the Controller as a list.
This is the value that the console shows, for the input field:
<input type="hidden" class="invisible" id="groupList" name="groupList"
value="[object HTMLInputElement]">
Any advice to face this issue, would be much appreciated. Thanks in advance.
You can proceed like this :
Create a Model, for exemple:
public class User {
private String username;
public User() {
}
public User(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
Create a FormModel:
public class FormUsers {
private List<User> listUsers;
public FormUsers(List<User> listUsers) {
this.listUsers = listUsers;
}
public FormUsers() {
}
public List<User> getListUsers() {
return listUsers;
}
public void setListUsers(List<User> listUsers) {
this.listUsers = listUsers;
}
#Override
public String toString() {
return "FormUsers{" + "listUsers=" + listUsers + '}';
}
}
in your controller (Get and Post) :
#RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello(ModelMap model) {
FormUsers formUsers = new FormUsers();
List<User> list = new ArrayList<>();
list.add(new User("Wassim"));
formUsers.setListUsers(list);
logger.debug("--> " + formUsers.toString());
model.addAttribute("formUsers", formUsers);
return "hello";
}
#RequestMapping(value = "/hello", method = RequestMethod.POST)
public String helloPost(#ModelAttribute FormUsers formUsers, ModelMap model) {
logger.debug("Get List of new users --> " + formUsers.toString());
return "hello";
}
In my view (hello.html) : for listing all users :
<button id="addAction">ADD</button>
<form action="#" th:action="#{/hello}" th:object="${formUsers}" method="post">
<ul id="myUl">
<input type="text" th:field="*{listUsers[0].username}" />
</ul>
<input type="submit" value="Submit" />
</form>
Now if I want to add another user with javascript when I clic in the button 'ADD, I will append() a new 'li' element containing the new user :
<script type="text/javascript">
$(document).ready(function () {
console.log("ready!");
$("#addAction").click(function () {
console.log("FUNCTION");
$("#myUl").append('<li><input id="listUsers1.username" name="listUsers[1].username" value="Rafik" type="text"/></li>');
});
});
</script>
When I Submit, I will get a list with 2 User : 'Wassim' & 'Rafik'.
You can manage this exemple (also the index of the list must managed properly) to append your list with the needed DATA.

Spring + Thymeleaf type Converter in a form

I'm trying to use a type converter in a Spring boot app and using Thymeleaf but I can't get it working. I've put some code on Github so you can see exactly what I'm trying to do. This is Spring 1.5.1 and Thymeleaf 3.0.3. https://github.com/matthewsommer/spring-thymeleaf-simple-converter
Basically this code is just trying to add a person to a comment object. The person object is null when it gets posted and I don't understand why.
Something that's odd is that the ID of the person isn't being added to the value attribute but it is if th:field="*{body}" is removed. I think it has to do with this: https://github.com/thymeleaf/thymeleaf/issues/495 but I'm currently trying to add BindingResult and it's not working...
My HTML is:
<body>
<div th:if="${personObject != null}" th:text="${personObject.name}"></div>
<form th:action="#{/}" th:object="${comment}" method="post">
<input type="hidden" th:if="${personObject != null}" th:value="${personObject.id}" th:field="*{person}" />
<textarea id="comment" placeholder="Comment..." th:field="*{body}"></textarea>
<button id="comment_submit" type="submit">Comment</button>
</form>
<div th:text="${comment.body}"></div>
</body>
My controller:
#Controller
public class HomeWebController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String getHome(final HttpServletRequest request, final Map<String, Object> model, #ModelAttribute(value = "comment") Comment comment) {
model.put("personObject", new Person(1, "John Smith"));
return "Home";
}
#RequestMapping(value = "/", method = RequestMethod.POST)
public String postHome(final HttpServletRequest request, final Map<String, Object> model, #ModelAttribute(value = "comment") Comment comment) {
model.put("commentBody", comment.getBody());
model.put("person", comment.getPerson());
return "Home";
}
}
And the converter:
#Component
public class StringToPersonConverter implements Converter<String, Person> {
#Autowired
public StringToPersonConverter() { }
#Override
public Person convert(String id) {
if(id == "1") {
Person person = new Person(1, "John Smith");
return person;
}
return null;
}
}
Hi finally I had to do some changes to make it work, but this is the result class by class.
ConvertorApplication:
#SpringBootApplication
#Configuration
#EnableWebMvc
public class ConvertorApplication extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(ConvertorApplication.class, args);
}
//Add converter and configuration annotation
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StringToPersonConverter());
}
}
StringToPersonConverter:
#Override
public Person convert(String id) {
//Never compare String with == use equals, the "==" compares memory space not the values
if(id.equals("1")) {
Person person = new Person(1, "John Smith");
return person;
}
return null;
}
HomeWebController
#Controller
public class HomeWebController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String getHome(final Map<String, Object> model, #ModelAttribute(value = "comment") Comment comment) {
//Initialize the comment with the person inside, no need of personObject object
model.put("comment", new Comment(new Person(1, "John Smith")));
return "Home";
}
#RequestMapping(value = "/", method = RequestMethod.POST)
public String postHome(final Map<String, Object> model,
#ModelAttribute(value = "comment") Comment comment,
#RequestParam(value = "person.id") Person person) {
//from the view retrieve the value person.id which will be used by the converter to build the Person entity
comment.setPerson(person);
model.put("comment", comment);
return "Home";
}
}
Comment (Add empty constructor)
public Comment(){}
Person (Add empty constructor)
public Person(){}
Home.jsp (Basically remove personObject, not need)
<!DOCTYPE html>
<html xmlns:th="//www.thymeleaf.org">
<body>
<div th:text="${comment.person.name}"></div>
<form th:action="#{/}" th:object="${comment}" method="post">
<input type="hidden" th:field="*{person.id}" />
<textarea id="comment" placeholder="Comment..." th:field="*{body}"></textarea>
<button id="comment_submit" type="submit">Comment</button>
</form>
<div th:text="${comment.body}"></div>
</body>
</html>
That's would be everything to make it work.

Neither BindingResult nor plain target object for bean name 'loginuser' available as request attribute

#Controller
#RequestMapping("Page/Login.do")
public class HomeController
{
#RequestMapping(method = RequestMethod.GET)
protected String showLoginPage(HttpServletRequest req,BindingResult result) throws Exception
{
loginuser lu=new loginuser();
lu.setLoginn("Amit");
System.out.println(lu.getLoginn());
return "Login";
}
}
Above code is ##HomeController.java##
loginuser.java
package Com.Site.Name.Order;
public class loginuser
{
private String Loginn;
public String getLoginn()
{
System.out.println("hi i m in login get");
return Loginn;
}
public void setLoginn(String loginn)
{
System.out.println("I m in Loin set");
Loginn = loginn;
}
}
My JSP PAGE IS
Login.jsp
<form:form action="Login.do" method="post" commandName="loginuser">
<div id="Getin">
<img alt="" src="Image/loginttt.png">
</div>
<div id="login">
</div>
<form:input path="Loginn"/>
<input type="submit" value="LOGIN"/>
</form:form>
You are trying to use a Model attribute (commandName) but there is no such attribute added to the model or request attributes. You need to add it. Also, the BindingResult in your handler makes no sense. Remove it.
#RequestMapping(method = RequestMethod.GET)
protected String showLoginPage(HttpServletRequest req, Model model) throws Exception
{
loginuser lu=new loginuser();
lu.setLoginn("Amit");
System.out.println(lu.getLoginn());
model.addAttribute("loginuser", lu);
return "Login";
}
The Model attributes are added to the request attributes and are therefore available in the jsp.

Resources