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"}

3 Answers 3

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;
}
Sign up to request clarification or add additional context in comments.

1 Comment

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"}
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

Comments

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;
  }
}]);

3 Comments

That did not work as well. I'm still getting nulls on all the fields.
What fields are you getting null? What does it look in the request payload?
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.