Sending #RequestBody from node js to Spring Boot Rest API - java

After spending more than half a day still not able to get down to whats wrong with the following:
Trying to send form data from NodeJSto Spring Rest API.
Node JS:
var inputData = { base : req.body.base, test : req.body.test }
var queryParams = {
host: '127.0.0.1',
port: 8080,
path: '/start',
method: 'POST',
headers: {'Content-type': 'application/json'},
body: inputData //Used JSON.stringify(inputData) - didn't work
};
Using http module to send request:
var req = http.request(queryParams, function(res) {
//do something with response
});
req.end();
Spring Rest:
#RequestMapping(value = "/start", method = RequestMethod.POST, consumes = "application/json")
#ResponseBody
public String startApp(#RequestBody String body) {
System.out.println(body);
return "{\"msg\":\"Success\"}";
}
Using postman I am able to see the same inputData going through the Rest. But when sent from NodeJS, all I see is
{
timestamp: 1506987022646,
status: 400,
error: 'Bad Request',
exception: 'org.springframework.http.converter.HttpMessageNotReadableException',
message: 'Required request body is missing: public java.lang.String ApplicationController.startApp(java.lang.String)',
path: '/start'
}
Using spring-boot-starter parent in the maven.
Am I missing anything here? Any suggestions would be greatly appreciated!

I don't think that you put request body in queryParams will work.
You can try using req.write() to write data to request body as follows:
...
req.write(inputData);
req.end();
...

Related

Axios. Spring MVC returns a 415 response

I am using Vue.js, axios and Spring.
On the page I have the following axios code
axios({
method: 'post',
url: '/user/info',
params: {
'_csrf' : document.getElementById('csrf_id').value,
'name' : 'job',
'age' : '25',
},
headers: {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json'}
});
And on the server I have a receiving method like this
#Controller
#RequestMapping("/user")
public class UserInfo {
#ResponseBody
#PostMapping(value = "/info", consumes = "application/x-www-form-urlencoded", produces = "application/json" + ";charset=utf8")
public String info(#RequestParam(value = "name") String name, #RequestParam(value = "age") String age) {
System.out.println(name);
System.out.println(age);
return "ok";
}
}
Axios makes a request to the server, but the server returns a 415 response.
The request headers are missing the application/x-www-form-urlencoded content type. I suspect the problem lies precisely in this.
Tell me, what am I doing wrong?
HttpMethod Post is a method of writing and transmitting data in the request body.
In your case, you put data through params. If you execute code as you write, data will be sent such as /user/info?_csrf=value&name=job&age=25 and there will be no data in the request body.
To get the response you want, you can modify it as below.
axios({
method: 'post',
url: '/user/info',
data: '_csrf=csrf&name=job&age=25',
headers: {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json'}
});
change params keyword to data and write data like querystring.

How to pass parameters from cordova HTTP to Spring controller

In my ionic 5.0.0 application I'm using cordova's native HTTP to make the rest calls. Below is the code snippet of my logout function.
But when i execute this function i'm getting following error.
"advanced-http: \"data\" argument supports only following data types: String"
logout() {
this.setData("url", "/web/oauth/revoke-token");
let apiUrl = this.getBaseUrl() + this.getData("url");
const headers = {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'Authorization': 'Basic Y2hyR3liUnBxQUR3X2VDemw5dzc0cHU4dXNnYTpKdmZ1azgyYnBUQlVnNDJ6NU1hZFhXOWJPeElh'
};
const params = {
'companyId': this.getData("COMPANY_ID"),
'token': this.getData("ACCESS_TOKEN"),
'client_id': this.getData("CLIENT_ID"),
'token_type_hint': 'access_token'
};
this.nativeHttp.post(apiUrl, params, headers).then(response => {
console.log("success response: "+response);
})
.catch(error => {
console.log("error response: "+error);
});
console.log("finished");
}
Here is my Spring controller which receives the params.
#RequestMapping(value = "/oauth/revoke-token", method = RequestMethod.POST)
#ResponseBody
public ResponseEntity<Object> logout(HttpServletRequest request) {
String clientId = request.getParameter(OAuth2Constants.CLIENT_ID);
String token = request.getParameter(OAuth2Constants.TOKEN);
String tokenTypeHint = request.getParameter(OAuth2Constants.TOKEN_TYPE_HINT);
String companyId = request.getParameter(WebConstants.COMPANY_ID_PARAMETER);
}
But unfortunately all params receives in the controller as null.
Can someone help me?
Finally I found a solution for the issue. Simply set the data serializer for http request as follows before doing the post call.
this.nativeHttp.setDataSerializer( "urlencoded" );

Rest types, JSON or HTML forms with the same URL

I am trying to create a RESTful service and encounter a type conflict within the application. Right now, I deal with this problem by using two different URLs, but this leads to other problems and doesn't feel right.
// Controller to get a JSON
#RequestMapping(value = "/stuff/{stuffId}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public stuffDto getStuff(#PathVariable String stuffId) {
return //JSON DTO//
}
// Controller to get an HTML Form
#RequestMapping(value = "/stuff/{stuffId}/form", // <- nasty '/form' here
method = RequestMethod.GET)
public String getStuffForm(#PathVariable String stuffId, ModelMap model) {
// Prepares the model
return "JSP_Form";
}
And on the JavaScript side:
function loadStuffForm(url) {
$.ajax({
type : 'GET',
url : url,
success : function(response) {
showStuffForm(response);
}
});
}
How can I merge both controllers so it will return the right type of data based on what the client accepts? By default it would return a JSON. I want to add 'text/html' somewhere in the ajax query to get the Form instead. Any idea?
You can use Content Negotiation to communicate to the server and tell it what kind of a response you're expecting form it. In your particular scenario, you as a client using an Accept header tell the server to serve a text/html or application/json. In order to implement this, use two different produces with that same URL:
// Controller to get a JSON
#ResponseBody
#RequestMapping(value = "/stuff/{stuffId}", method = GET, produces = "application/json")
public stuffDto getStuff( ... ) { ... }
// Controller to get an HTML Form
#RequestMapping(value = "/stuff/{stuffId}", method = GET, produces = "text/html")
public String getStuffForm( ... ) { ... }
In your requests to /stuff/{id} endpoint, if you send Accept: text/html in headers, the HTML form would return. Likewise, you would get the JSON response by sending Accept: application/json header.
I'm not a JQuery expert but you can check this answer out on how to send an Accept header in $.ajax requests.

Unable to upload file from Angular client to Spring Java server: Says 400 error

When I am uploading a file from Postman rest client to the server(spring application deployed on a remote machine), I am able to upload the file without any issue.
But when I try to write a rest client in angular.js, and send over the request, I get 400 Bad Request Error. I know it's because of some syntax issue between what is send from client and what server is expecting.
Server side code:
#CrossOrigin(origins = "*")
#RequestMapping(value="/upload", method=RequestMethod.POST, consumes = {"multipart/form-data"})
public #ResponseBody String handleFileUpload(#RequestParam("files") MultipartFile file){
.
.
.
.
}
Client side code:
$scope.uploadFiles = function () {
alert("inside");
var request = {
method: 'POST',
url: 'http://IP ADDRESS and PORT NUMBER/upload',
data: formdata,
headers: {
'Content-Type': undefined
}
};
$http(request)
.success(function (response) {
alert("success: "+response);
})
.error(function (err) {alert("error: "+err);
});
}
I have uploaded the code here for file upload using Spring and AngularJS:
https://gist.github.com/abdulrafique/9219f7164fdf5dc6dfa8da110be6a04e

Putting multipart request does not work

Why doesn't this work? I am trying this against my Spring 3.2 MVC application. It works with POST requests.
curl -X PUT http://localhost:8080/bananas/1 --form data='{"description":"Hei", "status":"REJECTED"};type=application/json'
java.lang.IllegalArgumentException: Failed to obtain request part:
data. The part is missing or multipart processing is not configured.
#RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public ResponseEntity updateQuestion(#PathVariable final int id,
#RequestPart(value = "data") final Banana banana,
#RequestPart(value = "image", required = false) final MultipartFile imageFile) {
In reality PUT requests are supposed to work on Request Body (or payload) and not on Request Parameters. In that sense, servlet API & spring's handling is correct.
A better easier way to pass no data element from your jquery and javascript call.Pass your parameter as part of url.Means Set parameter in the url field.otherwise u have to do your code using GET.
var x=10;
$.ajax({
url: "/ritesh/" + x + "/patil" + "?param1=param2Val&..",
type: "PUT",
data: "",
success: function(response) {
// ....
}
});

Categories

Resources