Simple image upload in spring mvc - spring-mvc

Can anyone give me snippet of image upload in spring mvc ? I use #requestparam to get string and other data. But I want to get image and path of "web" folder..so I can save file there.

If I understand well, you need to upload image file from the client to be sent in your request (Rest Controller) using the Spring MVC, so you can use spring form like this:
<form:form method="POST" action="/spring-mvc-xml/uploadFile" enctype="multipart/form-data">
<table>
<tr>
<td><form:label path="file">Select a file to upload</form:label></td>
<td><input type="file" name="file" /></td>
</tr>
<tr>
<td><input type="submit" value="Submit" /></td>
</tr>
</table>
</form>
the most important part is to add the enctype="multipart/form-data" and the type of the input must be "file", then you can add for your rest controller the multipart param like this:
#RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public String submit(#RequestParam("file") MultipartFile file, ModelMap
modelMap) {
// here u can find your uploaded file
return "fileUploadView";
}
finally you need to crate multipart Bean in your spring context like this:
//you can defined it in xml way if your configuration in xml file
#Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver()
{
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(20848820);
return multipartResolver;
}
and also you need to add the upload file library at your dependency to Spring can use it :
dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version> // or you can find the last version
</dependency>
I usually use this way to upload files in my Spring applications , so I hope that you are need also.

Related

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'loginForm' available as request attribute

Getting java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'loginForm' available as request attribute. My login.jsp is as below.
<form:form method="POST" action="/loginPage" commandName = "loginForm">
<tr>
<td><form:label path="name">Username</form:label></td>
<td><form:input path="name" /></td>
</tr>
<tr>
<td><form:label path="age">Password</form:label></td>
<td><form:input path="age" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Submit"/>
</td>
</tr>
and my controller is
#RequestMapping(value="/loginPage",method = RequestMethod.POST)
public String processForm(#ModelAttribute("loginForm") LoginForm loginForm, BindingResult result,
Map model)
can anyone suggest how can i resolve this exception.
You need to add "loginForm" key to ModelMap before you start using it..
Example:
//This code needs to be invoked first
#RequestMapping(value="/onPageLoadOfLogin",method = RequestMethod.GET)
public String onLoadOfLoginPage(ModelMap m){
m.put("loginForm",new LoginForm());
}
model.put("loginForm",new LoginForm());
This means that, your command name should be exactly the same as the modelAttribute name... so if your commandName in your jsp file is "loginForm" then you model should add the attribute with the name "loginForm".
Please add model map attribute before rendering to login page.
<form:form method="POST" action="/loginPage" modelAttribute = "loginForm">
try adding modelAttribute in
also u need to first bind the form with the controller. To do this you can first perform a GET to perform the binding.
#RequestMapping(value="/loginPage",method = RequestMethod.GET)
public String processForm(#ModelAttribute("loginForm") LoginForm loginForm, BindingResult result,
Map model)
after this do POST. And submit button will do the binding of its own in POST method calling. Your form will be like
<form:form modelAttribute = "loginForm">

Which Signature to use in spring's controller methods

There are lots of possible signature while defining Spring's Controller method. I'm confused which one should i use and in which circumstances.
For example, I have below scenario.
I have to upload a file to server i have written a form for that
Below is HTML
<form action="uploadimage?id=${pencil.id}" method="post">
<table border="0">
<tr>
<td style="color:maroon;font-weight:bold;">Change/Upload Image</td>
<td><input type="file" name="image" /></td>
<td><input type="submit" value="upload" /></td>
<td><input type="hidden" name="pencilid" value="${pencil.id}" /></td>
</tr>
</table>
</form>
For this I'm writing controller method. While using #ModelAttribute it throws exception saying can't instantiate bean MaltipartFile as its an Interface and while using #RequestParam it returns 400 error code
using #requestParam
#RequestMapping(value="/uploadimage",method=RequestMethod.POST)
public ModelAndView uploadImage(#RequestParam ("pencilid") String id,#RequestParam("file") MultipartFile file)
{
System.out.println("In Controller");
Pencil pencil=null;
PencilService pencilService=ServiceFactory.getPencilService();
pencil=pencilService.getPencil(Integer.parseInt(id));
ModelAndView model= new ModelAndView("pencilview","pencil",pencil);
model.addObject("id",id);
//MultipartFile file=(MultipartFile)param.get("image");
System.out.println(file.getName());
return model;
}
Using #ModelAttribute
#RequestMapping(value="/uploadimage",method=RequestMethod.POST)
public ModelAndView uploadImage(#ModelAttribute ("pencilid") String id,#ModelAttribute("file") MultipartFile file)
{
System.out.println("In Controller");
Pencil pencil=null;
PencilService pencilService=ServiceFactory.getPencilService();
pencil=pencilService.getPencil(Integer.parseInt(id));
ModelAndView model= new ModelAndView("pencilview","pencil",pencil);
model.addObject("id",id);
//MultipartFile file=(MultipartFile)param.get("image");
System.out.println(file.getName());
return model;
}
Kindly let me know where i'm mistaking
in my Sping-servlet.xml i have defined multipartResolver as
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- setting maximum upload size -->
<property name="maxUploadSize" value="100000" />
</bean>
Let me know if anything else is required.
i think your form should have an attribute enctype like the following :
enctype="multipart/form-data"
if you are uploading file , you Use the #RequestParam for your file and for the other form fields that you have , like the following :
#RequestMapping(value="/upload", method=RequestMethod.POST)
public #ResponseBody String handleFileUpload(#RequestParam("name") String name,
#RequestParam("file") MultipartFile file){
}
in this example that is from the spring documentation , the handleFileUpload takes two parameters , the first is a normal String name , that is a normal field , the second is a file MultipartFile that is the file you want to upload .
Hope that Helps .

SPRING MVC post method call not working

By JSP has below :
<h2>Student Information</h2>
<form:form method="POST" action="/HelloWeb/addStudent">
<table>
and my java controller code has below
#RequestMapping(value = "/addStudent", method = RequestMethod.POST)
public String addStudent(#ModelAttribute("SpringWeb") Student student,
ModelMap model) {
when i try to hit the post doesnt work i,e /HelloWeb/addStudent,
I tried making both places /HelloWeb/addStudent or just /addStudent that doesnt work.
FYI : HelloWeb here is the DispatchServletName given in web,xml
I am trying example given in site
http://www.tutorialspoint.com/spring/spring_mvc_form_handling_example.htm
I apologize if i am asking very basic easisest issue, BUt tried this # late nite and fed up so requesting ppl to help/suggest
The attribute in jsp require modelAddribute or commandName which is the class instance of the domain object. You did not specify it. So the
<form:form method="POST" modelAttribute="SpringWeb" action="/HelloWeb/addStudent">.
There is a standard way to do form post submission in spring. You need to do GET request mapping to map/bind the Student table with jsp, and POST mapping to submit jsp form data. An example in your case would be.
#RequestMapping(value = "/addStudent", method = RequestMethod.GET)
public String addStudent(#ModelAttribute("SpringWeb") Student student) {
return "addstudentJsp"; // your jsp page name where the spring:form is placed
In jsp page do this
<h2>Student Information</h2>
<form:form modelAttribute="SpringWeb">
<form:input id="name" path="name" type="text" class="form-control" />
<form:errors path="name" cssClass="text-danger"></form:errors>
// your student fields
<button type="submit">submit</button>
</form:form>
Now again in your controller have a post request method like
#RequestMapping(value = "/addStudent", method = RequestMethod.POST)
public String addStudent(#ModelAttribute("SpringWeb") Student student, #BindingResult result) {
//Call to your data persistence layer like StudentService
}
The modelAttribute does the binding for you
I faced same problem, I just rename my project "HelloWeb" and the problem was solved.

Spring MVC update without redundant code?

I'm working on a Spring MVC controller and views to implement CRUD operations for a simple object named Partner. The update operation troubles me. It seems like I need to write several lines of code manually that I expected Spring MVC would take care of automatically. Is there a best practice that I'm missing here?
Here's my view:
<%# include file="include.jsp"%>
<form:form commandName="partner">
<input type="hidden" name="_method" value="PUT" />
<table>
<tr>
<td>Id:</td>
<td><form:input path="id" disabled="true" /></td>
</tr>
<tr>
<td>Name:</td>
<td><form:input path="name" /></td>
</tr>
<tr>
<td>Logo:</td>
<td><form:input path="logo" /></td>
</tr>
<tr>
<td>On-screen text:</td>
<td><form:textarea path="onScreenText" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Save Changes" /></td>
</tr>
</table>
</form:form>
And here's my controller method for the update operation:
#RequestMapping(value="/partner/{partnerId}", method=RequestMethod.PUT)
public ModelAndView updatePartner(#ModelAttribute Partner partner, #PathVariable int partnerId) {
EntityManager entityManager = DatabaseHelper.getEntityManager();
try {
Partner partnerToUpdate = entityManager.find(Partner.class, partnerId);
entityManager.getTransaction().begin();
partnerToUpdate.setId(partnerId);
partnerToUpdate.setName(partner.getName());
partnerToUpdate.setLogo(partner.getLogo());
partnerToUpdate.setOnScreenText(partner.getOnScreenText());
entityManager.persist(partnerToUpdate);
entityManager.getTransaction().commit();
}
finally {
entityManager.close();
}
return new ModelAndView("redirect:/partner");
}
The lines of code that trouble me are:
Partner partnerToUpdate = entityManager.find(Partner.class, partnerId);
partnerToUpdate.setId(partnerId);
partnerToUpdate.setName(partner.getName());
partnerToUpdate.setLogo(partner.getLogo());
partnerToUpdate.setOnScreenText(partner.getOnScreenText());
Do I really need to look up the existing Partner in the database and explicitly update each field of that object? I already have a Partner object with all the right values. Is there no way to store that object directly to the database?
I've already looked at Spring MVC CRUD controller best pactice, but that didn't quite answer my question.
As one possible suggestion, you could lookup the existing Partner object as part of model creation so that this model instance backs the form and Spring binds the fields directly to it. One way to achieve this would be to create an explicit method in the controller responsible for creating the model.
For example:
#ModelAttribute("partner")
public Partner createModel(#PathVariable int partnerId) {
Partner partner = entityManager.find(Partner.class, partnerId);
return partner;
}
And then you could remove the copying from the updatePartner method - because Spring will already have bound the form fields directly to the loaded Partner object.
#RequestMapping(value="/partner/{partnerId}", method=RequestMethod.PUT)
public ModelAndView updatePartner(#ModelAttribute("partner") Partner partner) {
EntityManager entityManager = DatabaseHelper.getEntityManager();
try {
entityManager.getTransaction().begin();
entityManager.persist(partner);
entityManager.getTransaction().commit();
}
finally {
entityManager.close();
}
return new ModelAndView("redirect:/partner");
}
One caveat - because the createModel method would get called for every request to the controller (not just updatePartner), the partnerId path variable would need to be present in all requests.
There's a post here which goes over a solution to that issue.
You can use merge to update the desired values, something like:
#RequestMapping(value="/partner/{partnerId}", method=RequestMethod.PUT)
public ModelAndView updatePartner(#ModelAttribute Partner partner, #PathVariable int partnerId) {
EntityManager entityManager = DatabaseHelper.getEntityManager();
try {
entityManager.getTransaction().begin();
partner.setId(partnerId);
entityManager.merge(partner);
entityManager.getTransaction().commit();
}
finally {
entityManager.close();
}
return new ModelAndView("redirect:/partner");
}
Also, I recommend You to use the DAO Pattern and Spring Transaction Support with #Transactional and #Repository

Spring 3.1 MVC and Security: both login and registration form (multiple forms) on same page get submitted

I'm using Spring (3.1), Spring MVC (3.1) and Spring Security (3.0) in combination and I've put together a single JSP page that has two forms on it; One is a form to login and the other is a form to register (i.e. create a new user).
For the register form, I use the Spring form tags, backed up by a controller to handle the request but for the login form I don't bother with the Spring form tags as I don't believe they're needed. There is also no controller that I need to write to handle the form submission as Spring Security takes care of authenticating so long as the request is submitted to j_spring_security_check.
The register form is working fine but the login form is a problem. It seems that when I click the submit button on the login form, the registration form is also submitted, or at least Spring thinks I'm trying to submit that form. Here is the JSP:
<form id="loginform" method="POST" action="<c:url value='j_spring_security_check'/>">
<label for="existing_email">Email:</label>
<input name="j_username" id="existing_email" type="text" value="${SPRING_SECURITY_LAST_USERNAME}" />
<label for="existing_password">Password:</label>
<input name="j_password" id="existing_password" type="password" />
<input id="login-form-submit" type="submit" value="Sign in" />
</form>
<form:form id="registrationform" modelAttribute="user" method="POST" action="register">
<form:label path="username" for="email">Email:</form:label>
<form:input path="username" name="username" id="email" type="text" />
<form:errors path="username" cssClass="formError" />
<form:label path="password" for="password">Password:</form:label>
<form:input path="password" name="password" id="password" type="password" />
<form:errors path="password" cssClass="formError" />
<input id="registration-form-submit" type="submit" value="Sign up" />
</form:form>
Notice that form tags for the input of type submit are not present and this seems to be a normal thing to do in the examples I've seen. Adding form tags to the submit button I guess doesn't make sense as it doesn't map to anything on the target object (user in this case).
When I click the "Sign in" button I get the following exception:
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/project1] threw exception [An exception occurred processing JSP page /WEB-INF/views/registration.jsp at line 29
28: <form:form id="registrationform" modelAttribute="user" method="POST" action="register">
29: <form:label path="username" for="username">Username:</form:label>
30: <form:input path="username" name="username" id="username" type="text" />
31: <form:errors path="username" cssClass="formError" />
32:
Stacktrace:] with root cause
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'user' available as request attribute
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:141)
This I recognise from cases where you forget to include the modelAttribute attribute in form:form, but of course I don't want to submit this form to my controller.
I have a feeling there is a mistake I'm making or a simple solution. Can anyone recommend a way around this or perhaps a different approach?
Here is the controller method that handles requests to register in case that's needed:
#RequestMapping(value = "**/register", method = RequestMethod.POST)
public String registerUser(#ModelAttribute("user") #Validated User user, BindingResult errors, ModelMap model) {
if (errors.hasErrors()) {
return "registration";
}
// Other stuff then...
return "profile"
}
If you are using "user" modelAttribute in form tag then a non-null request attribute must be present with name "user".
One way to add that in request attribute is what you did in your answer above. Other ways are:
(1) Add in ModelMap:
#RequestMapping(value = "/loginfailed", method = RequestMethod.GET)
public String loginFailed(ModelMap model) {
model.addAttribute("user", new User());
model.addAttribute("error", "true");
return "registration";
}
(2) Add in request scope (Using WebRequest or HttpServletRequest):
#RequestMapping(value = "/loginfailed", method = RequestMethod.GET)
public String loginFailed(ModelMap model, WebRequest webRequest) {
webRequest.setAttribute("user", new User(), WebRequest.SCOPE_REQUEST);
model.addAttribute("error", "true");
return "registration";
}
(3) Use #ModelAttribute on method:
#ModelAttribute("user")
public User user() {
return new User();
}
Please also see Using #ModelAttribute on a method and Using #ModelAttribute on a method argument
Also note that you don't have to use type attribute. See form:input and form:password.
I think the problem is specifically when a login fails and the same page is served up, albeit on a different URL path and so through a different controller method. Therefore my original suspicion that the issue is that both forms are submitted may be something of a red herring, though I still don't fully understand what's going on and that may yet have something to do with it. In any case, this is what corrected the problem for me:
I had a controller method that originally looked like this:
#RequestMapping(value = "/loginfailed", method = RequestMethod.GET)
public String loginFailed(ModelMap model) {
model.addAttribute("error", "true");
return "registration";
}
In the Spring Security context I specify /loginfailed as the path to go to by default if a login attempt fails. This is where it seems the user object is needed so if I alter the signature as follows it all works:
#RequestMapping(value = "/loginfailed", method = RequestMethod.GET)
public String loginFailed(#ModelAttribute("user") User user, BindingResult errors, ModelMap model) {
model.addAttribute("error", "true");
return "registration";
}
Any comments/clarification welcome from others.

Resources