4

I am calling a spring boot REST service from my angular UI. It worked good as long as the Spring Boot Rest service was executed as a Spring boot App. But once i converted it to a WAR file and deployed on a Jboss 6.2.4 server, i am getting 404. I see that REST service call from the UI is successful but the request JSON is not getting passed. On the request JSON i am passing 2 strings and an uploaded excel file.

This is my angular UI http call

App.service('getHeatMapDataService', ['$http', '$q', function ($http,      $q) {
this.getHeatMapData = function (scope) {
    var url = 'http://localhost:8080/rest-services/fusiontables/upload';
    var deferred = $q.defer();
    $http({
            method: 'POST',
            url: url,
            headers: {
                'Content-Type': undefined
            },
            data: {
                stateCd: scope.stateCd,
                addressExtras: scope.addressExtras,
                uploadFile: scope.upFile
            },
            transformRequest: function (data, headersGetter) {
                var formData = new FormData();
                angular.forEach(data, function (value, key) {
                    formData.append(key, value);
                });

                var headers = headersGetter();
                delete headers['Content-Type'];
                return formData;
            }
        })
        .success(function (data) {
            deferred.resolve(data);
            console.log("Success");
            console.log(data);
        })
        .error(function (data, status) {
            deferred.reject(status);
            console.log("Failed");
        });
    return deferred.promise;
}
}]);

This is my Spring boot Rest controller when it was working

@RequestMapping(value="/upload", method=RequestMethod.POST)
@ResponseBody
public String getBoundaries(HeatMapUploadCommand uploadCommand) {
    logger.info("Heat Map Controller invoked " + uploadCommand);
    return null;
}

This is my upload command

public class HeatMapUploadCommand {

private String stateCd;
private String addressExtras;
private MultipartFile uploadFile;

After i deployed on Jboss, the request still hits the Spring Boot app but then it has all request params as null.

This is the request payload

------WebKitFormBoundaryvCCnl3nhIgoW1MwR
Content-Disposition: form-data; name="stateCd"

CA
------WebKitFormBoundaryvCCnl3nhIgoW1MwR
Content-Disposition: form-data; name="addressExtras"

1234
------WebKitFormBoundaryvCCnl3nhIgoW1MwR
Content-Disposition: form-data; name="uploadFile"; filename="CAdata.xlsx"
Content-Type: application/vnd.openxmlformats-    officedocument.spreadsheetml.sheet


------WebKitFormBoundaryvCCnl3nhIgoW1MwR--

I tried changing the controller as

@RequestMapping(value="/upload", method=RequestMethod.POST)
@ResponseBody
public String getBoundaries(@RequestParam(value="stateCd") String stateCd,
        @RequestParam(value="addressExtras") String addressExtras,
        @RequestParam(value="uploadFile") MultipartFile file) {
    System.out.println("Heat Map Controller invoked " + stateCd);
    return null;
}

Still no luck. This is the response i got.

{"timestamp":1464840821648,"status":400,"error":"Bad    Request","exception":"org.springframework.web.bind.MissingServletRequestParameterException","message":"Required String parameter 'stateCd' is not     present","path":"/rest-services/fusiontables/upload"}
tindu edward
  • 299
  • 1
  • 3
  • 17

3 Answers3

3

I think you missed @RequestBody.

When you use $http with data property, the data is passed in request body.

$http({
    method: 'POST',
    url: url,
    data: {
        stateCd: scope.stateCd,
        addressExtras: scope.addressExtras,
        uploadFile: scope.upFile
    },

I think that once you add @RequestBody, it may be working.

@RequestMapping(value="/upload", method=RequestMethod.POST)
@ResponseBody
public String getBoundaries(@RequestBody HeatMapUploadCommand uploadCommand) {
    logger.info("Heat Map Controller invoked " + uploadCommand);
    return null;
}
JK.Lee
  • 261
  • 3
  • 9
  • Now i get HTTP status 415 Unsupported Media Type. {"timestamp":1464874683832,"status":415,"error":"Unsupported Media Type","exception":"org.springframework.web.HttpMediaTypeNotSupportedException","message":"Content type 'multipart/form-data;boundary=----WebKitFormBoundarymRKqwcUfa6CJzALs;charset=UTF-8' not supported","path":"/rest-services/fusiontables/upload"} – tindu edward Jun 02 '16 at 13:39
1

Finally figured it out.

I had to add a Multipartresolver bean.

@Configuration
public class WebConfig extends WebMvcAutoConfiguration {
@Bean
public MultipartResolver multipartResolver() {
    return new CommonsMultipartResolver();
}

}

That fixed the issue. Seems like when i run it as a spring boot app, spring already takes care of it but when deployed as a WAR file this bean should be configured

tindu edward
  • 299
  • 1
  • 3
  • 17
0

Can you try with this Spring Controller method:

@RequestMapping(value="/upload", method=RequestMethod.POST)
@ResponseBody
public String getBoundaries(MultipartHttpServletRequest request, HttpServletResponse response) throws IOException {
    String stateCd = request.getParameter("stateCd");
    String addressExtras = request.getParameter("addressExtras");
    ......
    Iterator<String> iterator = request.getFileNames();
    while (iterator.hasNext()) {
            MultipartFile multipartFile = request.getFile(iterator.next());
            .....
    }
    .........
}

And the Angular Service:

App.service('getHeatMapDataService', ['$http', '$q', function ($http,$q) {
  this.getHeatMapData = function (scope) {
    var url = 'http://localhost:8080/rest-services/fusiontables/upload';
    var deferred = $q.defer();
    var formData = new FormData();
    formData.append('stateCd', scope.stateCd);
    formData.append('addressExtras', scope.stateCd);
    formData.append('file', scope.upFile);

    $http.post( url, formData, {
        headers: { 'Content-Type': undefined },
        transformRequest: angular.identity
    }).success(function (result) {
        console.log('200');
    }).error(function () {
        console.log('400-500');
    });
    return deferred.promise;
  }
}]);
Rana_S
  • 1,520
  • 2
  • 23
  • 39
  • That did not work as well. I'm still getting nulls on all the fields. – tindu edward Jun 02 '16 at 20:48
  • What fields are you getting null? What does it look in the request payload? – Rana_S Jun 02 '16 at 20:59
  • I've included the request payload in my question. When i get the whole thing as a @RequestBody String and print it out, its getting printed out in the controller. But when i use request.getParameter("stateCd"), its returning nulls. Regarding the angular service, i tried this too... but same result. It seems this is because controller is not able to identify the content type of the request payload. – tindu edward Jun 02 '16 at 21:45