Spring boot is not getting the params in the request body.
The controller is defined like:
#PostMapping("/login")
public #ResponseBody User login(#RequestBody String username, #RequestBody String password) {
return userService.login(username,password);
}
And the fetch in React
const LogFunc = async () => {
let url = new URL("http://localhost:8080/user/login");
let params = {
username: username,
password: password
}
console.log(JSON.stringify(params));
return fetch(url, {
method: 'POST',
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
body: JSON.stringify(params)
When i console.log it, it prints it like
{"username":"allanosi","password":"cap"}
which is correct but when Spring receive it, it prints:
Required request body is missing: public com.formacion.back.entities.User com.formacion.back.controllers.UserController.login(java.lang.String,java.lang.String)]
On the network part it says that it's a bad Request but I have no idea why it is.
Thanks in advance.
Can you try this? Just replace the annotation with this.
#RequestMapping(
value = "/login",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
Another guess, spring boot is waiting string not object that's why you might getting request body is missing error. You can try this:
public #ResponseBody User login(#RequestBody Map<String, String> userData) {
// your code
}
Maybe you can try this:
const fdata = new FormData();
fdata.append('username', 'diego');
fdata.append('password', '1242342');
fetch(url, {
method: 'POST',
headers: ...,
body: fdata,
});
I had the same problemas as you and this approach has fixed my problem.
Related
I'm currently stuck sending a request to my server and can not get a response. I have tried it on postman and it runs completely fine. However, when I try to put it on react, the back-end always response with a bad request.
Here is my code for the back-end
#GetMapping(value = "/searchPatient")
public ResponseEntity<?> searchPatients(#RequestParam String id_num,
#RequestParam String name) {
List<PatientForSearchDto> patientForSearchDtos = patientService.viewSearchedPatient(id_num, name);
return ResponseEntity.status(HttpStatus.OK).body(
new ResponseObject("ok", "Success", patientForSearchDtos)
);
}
Here is my code for Front end (react)
async function sendRequest () {
const formData = new FormData();
formData.append('id_num', id_num);
formData.append('name', name);
console.log(formData)
console.log(formData.get('name'))
console.log(formData.get('id_num'))
const config = {
method: 'get',
url: 'http://localhost:8080/api/searchPatient',
// headers : {
// 'Content-Type': 'from-data'
// },
data : formData
};
await axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
setPatientList(response.data.data.object)
})
.catch(function (error) {
console.log(error);
});
}
Here is what I get when sending request via postman
enter image description here
Here is when sending request using react
enter image description here
From the Axios docs about Request Config data param:
// data is the data to be sent as the request body
// Only applicable for request methods 'PUT', 'POST', 'DELETE , and
'PATCH'
So, data with GET method is not supported.
Can't you use params instead?
I have some issues in file uploading using spring rest and react and axios,
my back-end code is
#PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity uploadFile(#RequestParam MultipartFile file) {
return ResponseEntity.ok().build();
}
and I can upload file using postman, but by using axios I got some errors.
nested exception is org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
here is my code:
let formData = new FormData();
formData.append("file", this.state.selectedFile);
axios({
method: "post",
url: url,
data: {
formData
}
})
also if I put
headers: { "Content-Type": "multipart/form-data" }
I got error too,
can anyone tell me what are my mistakes please?
It may be beacause you are creating a new object and sending the data inside the object
Try this data: formData
let formData = new FormData();
formData.append("file", this.state.selectedFile);
axios({
method: "post",
url: url,
data: { formData},
{...axios.default.headers,
...{headers: { "Content-Type": "multipart/form-data" }}
}
})
You dont need to put any headers as it will automatically , decides the parameters of headers , when you do it manually you need to explicitly decides few parameters which is quite difficult to judge , so dont give headers
Currently I have an axios post request that works fine for sending the data to Spring Boot backend. But it just wraps single list of data to json and sends it as requested body:
Example:
sendAllData(data) {
return axios.post(API_URL + "receiveData", JSON.stringify(data),
{ headers: { "Content-Type": "application/json; charset=UTF-8" },
}).then(response=> console.log("repsonse", response.status)) // is 201
}
And it receives it on backend:
#RequestMapping(path = "/receiveData", method = RequestMethod.POST)
public ResponseEntity<Void> receiveData(#RequestBody Collection<ActivePOJO> activitePOJOS) {
//DO WORK WITH activePOJOS DATA
return new ResponseEntity<>(HttpStatus.CREATED);
}
However, apart from that information, I also need to send some other info like user.id (as example), so I need my backend to receive something like this:
public ResponseEntity<Void> receiveData(#RequestBody Collection<ActivitePOJO> activePOJOS, Long userID)
But I don't know which way should I prepare axios post for something like that. Should I use params instead of body?
You can use params and body together in a request with axios. To send userID as a param:
sendAllData(data) {
return axios.post(API_URL + "receiveData", JSON.stringify(data),
{ headers: { "Content-Type": "application/json; charset=UTF-8" },
params: { userID: 1 }, //Add userID as a param
}).then(response=> console.log("repsonse", response.status)) // is 201
And receive userID in controller with #RequestParam annotation:
public ResponseEntity<Void> receiveData(#RequestBody Collection<ActivitePOJO> activePOJOS, #RequestParam("userID") Long userID){
// here you can access userID value sent from axios
}
The third parameter is config and you can pass params to it along with header as a separate key. Refer this. https://github.com/axios/axios#axiosposturl-data-config
sendAllData(data) {
return axios
.post(API_URL + 'receiveData', JSON.stringify(data), {
headers: { 'Content-Type': 'application/json; charset=UTF-8' },
params: { userId: 2 },
})
.then((response) => console.log('response', response.status));
} // is 201
I'm trying to make a get request with some params to a Spring get method. I'm using angular to make a call and this is my example
var apiUrl = 'api/trupci-filter';
var req = {
method: 'GET',
url: apiUrl,
headers: {
'Content-Type': "application/x-www-form-urlencoded" or "application/json"
},
data: {
klasa: "1",
promjer:"1",
duzina: "1"
}
}
console.log(req)
return $http(req)
And this is my get method in Spring:
#GetMapping("/trupci-filter")
#Timed
public ResponseEntity<List<Trupci>> getTrupciWithFilter(
#RequestParam(value = "klasa", required = false) String klasa,
#RequestParam(value = "promjer", required = false) String promjer,
#RequestParam(value = "duzina", required = false) String duzina )
The call is successful but the params are always null. I can't find any solution to this simple thing and I'm losing my mind.
Can anybody help me?
HTTP GET request can't have data element, its for request body like for HTTP POST, PUT etc. Please use params for query string parameters.
var req = {
method: 'GET',
url: apiUrl,
params: {
klasa: "1",
promjer:"1",
duzina: "1"
}
}
Angular Code:
getAuthorizationStatus: function () {
var deferred = $q.defer();
$http({
method: "POST",
url: url,
data: {
username: $scope.username,
password: $scope.password
},
contentType: 'application/json',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
}).success(deferred.resolve)
.error(deferred.reject);
return deferred.promise;
},
My Server side code:
[HttpPost]
public int ValidateUser([FromBody]Credentials credentials)
{
try
{
string username = credentials.username;
string password = credentials.password;
//Do stuff
}
catch (Exception ex)
{
throw ex;
return -1;
}
return -1; // not valid user
}
The problem I am having is I am able to hit the Api Method but the data inside is always null. I have tried several combinations like this:
data: JSON.stringify({
"username" : "username",
"password":"mypassword"
}),
No dice.
What am I doing in wrong ?
Enclose your data in $.param()
Example :
data: $.param({ username: $scope.username,password: $scope.password })
I would instead trying to change the default and appropriate behavior of $http's POST, instead let the server read the data from the right place. Taken from MVC controller : get JSON object from HTTP body?:
[HttpPost]
public ActionResult Index(int? id)
{
Stream req = Request.InputStream;
req.Seek(0, System.IO.SeekOrigin.Begin);
string json = new StreamReader(req).ReadToEnd();
InputClass input = null;
try
{
// assuming JSON.net/Newtonsoft library from http://json.codeplex.com/
input = JsonConvert.DeserializeObject<InputClass>(json)
}
catch (Exception ex)
{
// Try and handle malformed POST body
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
//do stuff
}
It turns out that MVC doesn't really bind the POST body to any
particular class. Nor can you just fetch the POST body as a param of
the ActionResult (suggested in another answer). Fair enough. You need
to fetch it from the request stream yourself and process it.
Using [FromBody] beside the action input param is enough to get the data from request. Your problem is that you override the content-type in your Angular code through headers:
contentType: 'application/json',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' //*** Remove this!
}
It must be 'application/json' in order to send json data. Just remove that headers and it should work normally.