title: Dropwizard and Fileupload using angularJS with multiple controllers
body: <p>I am noob in Dropwizard and angularJs and trying to use file upload using DropWizard and AngularJs (in front). My use case is as follows : 
  A wizard like interface with Steps such that Steps 1 will ask for user to upload 2 files, then Step 2 will ask for user to provide 2 inputs (text field) and click validate. </p>
  
  <p>I used 3 controllers for this :<br>
  1. MainController (in the body) used to create an explainer using angularJs <a href="https://github.com/likeastore/ngDialog" rel="nofollow">ngDialog script</a>.<br>
  2. Upload Controller inside Maincontroller to upload files.<br>
  3. Validate Controller to take input from user to validate the text.  </p>
  
  <p>For some reason I could not make it to work to a point that i decided to use different framework now. This would be my last try.  Below is some code snippets </p>
  
  <pre><code>&lt;head&gt;
  .....
  .....    
  &lt;script src="bower_components/angular/angular.min.js"&gt;&lt;/script&gt;
  &lt;script src="bower_components/angular/angular-messages.js"&gt;&lt;/script&gt;
  &lt;script src="bower_components/angular-resource/angular-resource.js"/&gt;
  &lt;script src="bower_components/angular-route/angular-route.js"&gt;&lt;/script&gt;
  &lt;script src="js/ngDialog.min.js"&gt;&lt;/script&gt;
  &lt;script src="js/app.js"&gt;&lt;/script&gt;
  &lt;/head&gt;
  &lt;body ng-app="myValidatorApp" ng-controller="MainCtrl"&gt;
         &lt;div class="buttons"&gt;
          &lt;a href="#" ng-click="open()" class="demo"&gt;Explainer&lt;/a&gt;
          &lt;a href="#step1" class="btn btn-dark btn-lg"&gt;Go to Step 1&lt;/a&gt;               
         &lt;/div&gt;
      &lt;/div&gt;
  &lt;!-- Step 1 --&gt;
  &lt;section id="step1" class="services bg-section" ng-controller="UploadCtrl"&gt;
      &lt;div class="container"&gt;
          &lt;div class="row text-center"&gt;
            &lt;div class="col-lg-10 col-lg-offset-1"&gt;
            &lt;h2&gt;Step 1 - Upload Weight Data&lt;/h2&gt;
            &lt;form id="fileupload1" action="/service/upload/weight" method="POST" enctype="multipart/form-data"&gt;
              &lt;!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload --&gt;
              &lt;div class="row fileupload-buttonbar"&gt;
              &lt;div class="col-lg-7"&gt;
                  &lt;span&gt;
                      &lt;span&gt;Upload Weight data&lt;/span&gt;
                  &lt;/span&gt;
                  &lt;!-- The fileinput-button span is used to style the file input field as button --&gt;
                  &lt;span class="btn btn-success fileinput-button" ng-class="{disabled: disabled}"&gt;
                      &lt;i class="glyphicon glyphicon-plus"&gt;&lt;/i&gt;
                      &lt;span&gt;Add File...&lt;/span&gt;
                      &lt;input type="file" name="WeightData" multiple ng-disabled="disabled"&gt;
                  &lt;/span&gt;
                  &lt;span&gt;
                   &lt;button type="button" class="btn btn-light" ng-click="upload('modulus')"&gt;
                       &lt;i class="glyphicon glyphicon-upload"&gt;&lt;/i&gt;
                       &lt;span&gt;Start upload&lt;/span&gt;
                   &lt;/button&gt;
                  &lt;/span&gt;
              &lt;/div&gt;
              &lt;!-- The global progress state --&gt;
              &lt;div class="col-lg-5 fade" data-ng-class="{in: active()}"&gt;
                  &lt;!-- The global progress bar --&gt;
                  &lt;div class="progress progress-striped active" data-file-upload-progress="progress()"&gt;
                      &lt;div class="progress-bar progress-bar-success" data-ng-style="{width: num + '%'}"&gt;&lt;/div&gt;
                  &lt;/div&gt;
                  &lt;!-- The extended global progress state --&gt;
                  &lt;div class="progress-extended"&gt;&amp;nbsp;&lt;/div&gt;
              &lt;/div&gt;
              &lt;/div&gt;
            &lt;/form&gt;
            &lt;br/&gt;
            &lt;br/&gt;
            &lt;form id="fileupload2" action="/upload/sortcode" method="POST" enctype="multipart/form-data"&gt;
              &lt;!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload --&gt;
              &lt;div class="row fileupload-buttonbar"&gt;
              &lt;div class="col-lg-7"&gt;
                  &lt;span&gt;
                      &lt;span&gt;Upload Substitution data&lt;/span&gt;
                  &lt;/span&gt;
                  &lt;!-- The fileinput-button span is used to style the file input field as button --&gt;
                  &lt;span class="btn btn-success fileinput-button" ng-class="{disabled: disabled}"&gt;
                      &lt;i class="glyphicon glyphicon-plus"&gt;&lt;/i&gt;
                      &lt;span&gt;Add File...&lt;/span&gt;
                      &lt;input type="file" name="sortcodeData" multiple ng-disabled="disabled"&gt;
                  &lt;/span&gt;
               &lt;span&gt;
                   &lt;button type="button" class="btn btn-light" ng-click="upload('sortcode')"&gt;
                       &lt;i class="glyphicon glyphicon-upload"&gt;&lt;/i&gt;
                       &lt;span&gt;Start upload&lt;/span&gt;
                   &lt;/button&gt;
               &lt;/span&gt;    
                  &lt;!-- The global file processing state --&gt;
                  &lt;span class="fileupload-process"&gt;&lt;/span&gt;
              &lt;/div&gt;
              &lt;!-- The global progress state --&gt;
              &lt;div class="col-lg-5 fade" data-ng-class="{in: active()}"&gt;
                  &lt;!-- The global progress bar --&gt;
                  &lt;div class="progress progress-striped active" data-file-upload-progress="progress()"&gt;
                      &lt;div class="progress-bar progress-bar-success" data-ng-style="{width: num + '%'}"&gt;&lt;/div&gt;
                  &lt;/div&gt;
                  &lt;!-- The extended global progress state --&gt;
                  &lt;div class="progress-extended"&gt;&amp;nbsp;&lt;/div&gt;
              &lt;/div&gt;
          &lt;/div&gt;
            &lt;/form&gt;
              &lt;/div&gt;    
          &lt;/div&gt;
          &lt;!-- /.row --&gt;
      &lt;/div&gt;
      &lt;!-- /.container --&gt;
      &lt;div align="center"&gt;
          &lt;a href="#step2" class="btn btn-dark btn-lg"&gt;Go to Step 2&lt;/a&gt;
      &lt;/div&gt;  
  &lt;/section&gt;
  &lt;!-- Validation --&gt;
  
  &lt;section id="#step2" class="services bg-section" ng-controller="ValidateCtrl"&gt;
          &lt;div class="container"&gt;
          &lt;div class="row text-center"&gt;
              &lt;div class="col-lg-10 col-lg-offset-1"&gt;
               &lt;h2&gt;Step 2 - Provide Sortcode and AccountNumber&lt;/h2&gt;
               &lt;div class="row"&gt;
                 &lt;form name="userForm" novalidate&gt;
                      &lt;!-- sortcode field --&gt;
                      &lt;div class="form-group" ng-class="{'has-error': userForm.sortcode.$touched &amp;&amp; userForm.sortcode.$invalid }"&gt;
                          &lt;label&gt;Sort Code (6 digit)&lt;/label&gt;
                          &lt;input type="text" name="sortcode" class="form-control" ng-model="main.sortcode" ng-minlength="6" ng-maxlength="6" required&gt;
                          &lt;!-- ngMessages goes here --&gt;
                          &lt;p ng-show="userForm.sortcode.$error.empty" class="message-block"&gt;Sortcode is required.&lt;/p&gt;
                          &lt;p ng-show="userForm.sortcode.$error.minlength" class="message-block"&gt;Sortcode is too short.&lt;/p&gt;
                          &lt;p ng-show="userForm.sortcode.$error.minlength" class="message-block"&gt;Sortcode is too long.&lt;/p&gt;
                      &lt;/div&gt;
                      &lt;!-- account number field --&gt;
                      &lt;div class="form-group" ng-class="{'has-error': userForm.accountnumber.$touched &amp;&amp; userForm.accountnumber.$invalid }"&gt;
                          &lt;label&gt;Account Number (8 digit)&lt;/label&gt;
                          &lt;input type="text" name="accountnumber" class="form-control" ng-model="main.accountnumber" ng-minlength="8" ng-maxlength="8" required&gt;
                          &lt;!-- ngMessages goes here --&gt;
                          &lt;p ng-show="userForm.accountnumber.$invalid &amp;&amp; !userForm.accountnumber.$pristine" class="message-block"&gt;Account Number is required.&lt;/p&gt;
                          &lt;p ng-show="userForm.accountnumber.$error.minlength" class="message-block"&gt;Account Number is too short&lt;/p&gt;
                          &lt;p ng-show="userForm.accountnumber.$error.minlength" class="message-block"&gt;Account Number is too long.&lt;/p&gt;
                      &lt;/div&gt;
                      &lt;div class="form-group"&gt;
                              &lt;button type="submit" class="btn btn-danger"&gt;Validate&lt;/button&gt;
                      &lt;/div&gt;
                  &lt;/form&gt;
                &lt;/div&gt;
                &lt;!-- /.row (nested) --&gt;
                  &lt;/div&gt;
               &lt;!-- /.col-lg-10 --&gt;
           &lt;/div&gt;
           &lt;!-- /.row --&gt;
          &lt;/div&gt;
          &lt;!-- /.container --&gt;
       &lt;/section&gt;
  </code></pre>
  
  <p>My app.js</p>
  
  <pre><code>     var UploadCtrl = function ($scope, $http)
  {
      var serviceURI = "/service/";
      $scope.upload = function(uploadType) {
              if(uploadType == "modulus"){
                  var response = $http.post('/service/upload/modulusweight', $scope.jsonObj);
                  response.success(function(data, status, headers, config) {
                    $scope.resetSearch();
                    });
  
                  response.error(function(data, status, headers, config) {
                    alert("AJAX failed to get data, status=" + status);
                  });  
              } else if(uploadType == "sortcode"){
                  var response = $http.post('/service/upload/sortcode', $scope.jsonObj);
                  response.success(function(data, status, headers, config) {
                    $scope.resetSearch();
                    });
  
                  response.error(function(data, status, headers, config) {
                    alert("AJAX failed to get data, status=" + status);
                  });  
              }
          }
  };
  </code></pre>
  
  <p>My FileUploadResource.java</p>
  
  <pre><code>@Path("/upload")
  @Produces(MediaType.APPLICATION_JSON)
  public class FileUploadResource {
  
  
      private String uploadPath;
  
  
      public FileUploadResource(String uploadPath) {
          this.uploadPath = uploadPath;
      }
  
  
      @Path("/modulusweight")
      @POST
      @Timed
      @UnitOfWork
      @Consumes(MediaType.MULTIPART_FORM_DATA)
      @Produces(MediaType.APPLICATION_JSON)
      public Response uploadFile(FormDataMultiPart form) {
  
           FormDataBodyPart filePart = form.getField("modulusWeightData");
  
           ContentDisposition headerOfFilePart =  filePart.getContentDisposition();
  
           InputStream fileInputStream = filePart.getValueAs(InputStream.class);
  
           String filePath = uploadPath +"/"+ headerOfFilePart.getFileName();
  
          // save the file to the server
          saveFile(fileInputStream, filePath);
  
          String output = "File saved to server location using FormDataMultiPart : " + filePath;
  
          return Response.status(200).entity(output).build();
  
      }
  
      // save uploaded file to a defined location on the server
      private void saveFile(InputStream uploadedInputStream, String serverLocation) {
  
          try {
              OutputStream outpuStream = new FileOutputStream(new File(
                      serverLocation));
              int read = 0;
              byte[] bytes = new byte[1024];
  
              outpuStream = new FileOutputStream(new File(serverLocation));
              while ((read = uploadedInputStream.read(bytes)) != -1) {
                  outpuStream.write(bytes, 0, read);
              }
              outpuStream.flush();
              outpuStream.close();
              uploadedInputStream.close();
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
  }
  </code></pre>
  
  <p>And everytime I click on button nothing happens.<br>
  But when I use postman to send request directly I get error like </p>
  
  <pre><code>{
    "code": 415,
    "message": "HTTP 415 Unsupported Media Type"
  }
  </code></pre>
  
  <p>This is different issue. I am more interested to know why button clicks are not working. </p>