1. Flow diagram of a Spring MVC Request
  2. In addition to the below diagram (click to enlarge) note that Spring MVC controllers are singletons and should be kept stateless.

  3. How to do file uploads with Spring MVC 4.3.5
  4. source

    I had a form working in the Spring MVC way (Models, Validators and all) and was asked to add a file upload field. I.e. an <input> element with type='file'

    For that it was necessary to change the form from the following:

    <form:form id='the-form' modelAttribute="newAccountView" action="submit.do" method="POST"> … to the following:

    <form:form id='the-form' modelAttribute="newAccountView" action="submit.do" method="POST" enctype="multipart/form-data">

    This is very clearly stated in a number of guides.

    However, this alone does not work as I was met by a number of weird NPE exceptions (on the validators of that model). This was due to the fact that Spring was unable to retrieve any of the parameters present in the form due to the change of the form encoding (from the default application/x-www-form-urlencoded to multipart/form-data)

    To fix that I had to setup a multi-part resolver with my Spring application. So I added the following to my mvc-dispatcher-servlet.xml:

     <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
          <!-- one of the properties available; the maximum file size in bytes -->
          <property name="maxUploadSize" value="30000000"/>
     </bean>

    I also had to add the following dependency to my Ivy:

    <dependency org="commons-fileupload" name="commons-fileupload" rev="1.3.3" conf="run-time->default"/>

    After doing the above, I added a org.springframework.web.multipart.MultipartFile field in my Spring MVC model class for that view

    Inside, the controller it wasn't necessary to change the signature of the method at all. I was simply able to access the blob doing a:

    myViewModel.getCv().getSize()
    (where cv was the field I added to my view model)

    For completeness purposes, here's a simplified view of my method inside the controller:

        @RequestMapping(path="/submit", method=RequestMethod.POST)
        public String submit(HttpServletRequest request
                                   , @ModelAttribute("myModel") @Valid MyViewModel myViewModel
                                   , BindingResult result
                                   , Model model) {
            ...
            System.out.printf("%d bytes retrieved.\n", myViewModel.getCv().getSize());
            ...
        }
            

    NB: At the time of this writing I have not yet experimented using the alternative multi-part resolver provided by Spring: the StandardServletMultipartResolver one for Servlet 3.0 — see the source.

  5. Spring MVC hello world application for JBoss
  6. Checkout this project in my playground that shows how to deploy a simple Spring MVC application with a database back-end in JBoss (tested against JBoss EAP 6.4)