I am trying to get the response from the spring controller to Angularjs get request
Here is the java code
#RequestMapping(method = RequestMethod.GET, value = "/getEmployee")
public ResponseEntity<List<EmployeeModel>> getEmployee() {
System.out.println("get List");
List<EmployeeModel> em=employeeService.getEmployee();
return new ResponseEntity<List<EmployeeModel>>(em, HttpStatus.OK);
i have the list of EmployeeModel in em variable
but somehow i am not able to get it in the data of angularjs response(success)
Here is the angularjs code
$scope.listEmployee = function() {
$http({
method : 'GET',
url : '/Employee/getEmployee'
}).success(function(data, status, headers, config) {
console.log("data.token " + data);
}).error(function(data, status, headers, config) {
console.log("data.token " + data.token);
});
};
browser Status Code:406 Not Acceptable
Please help
Add following lines to your pom.xml
dependency groupId org.codehaus.jackson jackson-mapper-asl 1.7.1
Try adding following all HTTP headers to your request in following manner
HttpHeaders headers= new HttpHeaders(); List medias = new ArrayList(); medias.add(MediaType.ALL); headers.setAccept(medias);
And add headers as a second argument before sending response
. It will ensure data format is acceptable to any kind of accept header .
Related
For various REST api endpoints, the user_id will reach the backend, needed for further processing and then, sent back as a response to the front end.
I have a feeling I can do this through the header instead of passing it as a path parameter each time, except I can't seem to find the relevant information yet.
At the moment I send the response as a ResponseEntity. I would like, if possible, to keep this option.
I am using Java and Spring Boot.
example based on
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/ResponseEntity.html
edited to add readign header from request
#RequestMapping("/handle")
public ResponseEntity<String> handle(HttpServletRequest httpRequest) {
String userId= httpRequest.getHeader("user_id");
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("user_id", userId);
return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED);
}
I have decided that the best approach for my scenario, where I only need to fetch the user id and then respond back with it, is to use the #RequestHeader("userId") Long userId annotation.
Let's have a look at how I had configured the enpoint initially:
#PostMapping(path = "/add-follower/{userIdForFollowing}/{currentUserId}")
public ResponseEntity<String> addFollower(#PathVariable ("userIdForFollowing") Long userIdForFollowing, #PathVariable Long currentUserId)
{
Follow newFollow = followService.returnNewFollow(userIdForFollowing, currentUserId);
newFollow = followService.saveFollowToDb(newFollow);
return new ResponseEntity<>("Follow saved successfully", HttpStatus.OK);
}
Now, let's look at how I refactored the endpoint to fetch the id's from the header and return them in the response:
#PostMapping(path = "/add-follower")
public ResponseEntity<String> addFollower(#RequestHeader("userIdForFollowing") Long userIdForFollowing, #RequestHeader("currentUserId") Long currentUserId)
{
Follow newFollow = followService.returnNewFollow(userIdForFollowing, currentUserId);
newFollow = followService.saveFollowToDb(newFollow);
//here I will add more code which should replace the String in the ResponseEntity.
return new ResponseEntity<>("Follow saved successfully", HttpStatus.OK);
}
I have already created Rest Endpoint in Java spring boot. It returns appropriate response when I request it via Postman. But when I use react fetch it does not show any response in browser if return is Json.
Spring boot controller:
#RestController
#RequestMapping(path = "/v1/test")
#AllArgsConstructor(onConstructor_ = {#Autowired})
public class TestController {
...
}
Below endpoint is returning appropriate response.
#GetMapping(value = "/helloWorld", produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseStatus(HttpStatus.OK)
public String getHelloWorld() {
return "Hello, World1!";
}
But when I try to hit below endpoint it returns null when I make fetch request. But it returns appropriate response when I hit it via postman.
#GetMapping(value = "/testEndpoint", produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseStatus(HttpStatus.OK)
public String returnTestResponse() {
HashMap<String, Object> map = new HashMap<>();
map.put("key1", "value1");
map.put("results", "value2");
return "{\"a\":1, \"b\":\"foo\"}";
}
Also tried returning POJO object. But still no response.
#GetMapping(value = "/testModel", produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseStatus(HttpStatus.OK)
public SearchResultsModel testModel() {
this.myService.getSearchResult();
}
React fetch call:
await fetch(ALL_ARTICLES_ENDPOINT, {
mode: 'no-cors',
method: 'GET',
redirect: 'follow',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
}).then(response => {
console.log(response);
})
.then(data => {
console.log('Success:', data);
}).catch((error) => {
console.error('Error:', error);
});
Postman have couple hidden headers which are being sent with all requests.
Check Hide auto-generated headers
What you are missing in react call is is Accept header with application/json value
EDIT:
Just saw that you are returning string as json. You need to wrap it in POJO object and return it in returnTestResponse class
SECOND EDIT:
This will work. Try to implement your POJO
#GetMapping(value = "/testEndpoint", produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseStatus(HttpStatus.OK)
public YourObject returnTestResponse() {
HashMap<String, Object> map = new HashMap<>();
map.put("key1", "value1");
map.put("results", "value2");
return new YourObject(map);
}
Issue was caused by adding mode: 'no-cors' option in fetch request. This option helped me to get rid of cors error but it means that in return I won't be able to see body and headers in chrome.
To resolve the issue I removed mode: 'no-cors' and added #CrossOrigin annotation on my spring boot controller.
I want to send a POST request with my angular client to my spring-boot server.
The server receive sucessfully the data and anwser with 200 Code and body with a string that contains "ok".
But the client receive null as anwser.
Angular code :
httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Accept': 'application/json',
'Access-Control-Allow-Methods': 'POST, GET'
})
};
this.http.post(this.URL, JSON.stringify(this.alert), this.httpOptions)
.subscribe((result: string) => {
if (result == null || result === 'error') {
//if fail;
} else {
//if success;
}
console.log('result :' + result);
})
Spring-boot code :
#CrossOrigin(origins = "http://localhost:9000")
#PostMapping(value = "/url")
public ResponseEntity objDataController(#RequestBody ObjData objData) {
HttpHeaders resHeader = new HttpHeaders();
resHeader.set("origin", "http://localhost:8080");
resHeader.set("Content-Type", "application/json");
resHeader.set("Accept", "application/json");
//some code
return ResponseEntity.ok()
.headers(resHeader)
.body("ok");
}
At console.log get :
result :null
Thanks
Had a similar problem and it helped specifying the response-type:
const headers = new HttpHeaders({'Content-Type': 'application/json'});
this.httpClient.delete(url, {headers: headers, responseType: 'text'});
It's the chrome console messing with you, when it comes to observables, it can't interpret the value correctly. I guess if you use the result inside the 'If success' block, it is bound to work
Ok, I fix my problem, I change this:
return ResponseEntity.ok()
.headers(resHeader)
.body("ok");
By:
Gson gson = new Gson();
return ResponseEntity.ok()
.headers(resHeader)
.body(gson.toJson("ok", String.class));
Thanks you for your anwsers !
I am using ng-file-upload in Angular on client side to send a file(image,text etc) to Spring Boot Application.
I have Client side running in Xampp with url "localhost" while have spring instance running separately with url "localhost:8080".Cors on both sides are enabled and other all requests are successfully entertained.
Client Side Code:
Upload.upload({
url: 'http://localhost:8080/file/upload',
method:'POST',
data: {
uploadedPicture: file,
uploadedFrom: 'recipe'
},
}).then(function(response) {
$timeout(function() {
$scope.result = response.data;
});
}, function(response) {
if (response.status > 0) $scope.errorMsg = response.status + ': ' + response.data;
}, function(evt) {
$scope.progress = parseInt(100.0 * evt.loaded / evt.total);
});
Server Side Code:
#CrossOrigin
#RequestMapping(method = RequestMethod.POST, value = "/file/upload")
public String handleFileUpload(#RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
if (!file.isEmpty()) {
try {
Files.copy(file.getInputStream(), Paths.get(ROOT, file.getOriginalFilename()));
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded " + file.getOriginalFilename() + "!");
} catch (IOException|RuntimeException e) {
redirectAttributes.addFlashAttribute("message", "Failued to upload " + file.getOriginalFilename() + " => " + e.getMessage());
}
} else {
redirectAttributes.addFlashAttribute("message", "Failed to upload " + file.getOriginalFilename() + " because it was empty");
}
return "redirect:/";
}
I have tried the cors by sending get request from same code to the same resource with get method which is working.but when i send post request with a multipart form data (image or any other file) it rejects OPTIONS request.
OPTIONS http://localhost:8080/file/upload
XMLHttpRequest cannot load http://localhost:8080/file/upload. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. The response had HTTP status code 403.
I have Tested This resource by postman also and it uploaded file without error.
EDIT: I have tried by changing the http to https and it is giving the error as OPTIONS https://localhost:8080/file/upload net::ERR_TIMED_OUT_ problem is same as it cannot find the required resource
Any thoughts over this issue??
Looking at your error message I see:
No 'Access-Control-Allow-Origin' header is present
Are you sure the proper headers are being added?
We used a Filter to ensure all requests had these Headers added correctly:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST,GET, OPTIONS, DELETE
Access-Control-Max-Age: 3600
Access-Control-Allow-Headers: x-requested-with
Here is the Filter class we used:
SimpleCORSFilter.java
#Component
public class SimpleCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
Just change #CrossOrigin annotation to:
#CrossOrigin(origins = "*", methods = {RequestMethod.POST, RequestMethod.OPTIONS}, allowedHeaders = {"Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"}, exposedHeaders = {"Access-Control-Allow-Origin", "Access-Control-Allow-Credentials"})
try this extension in chrome , it may help you with the problem
https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=fr
First check your security settings, since you obviously get 403 as Status Code. Maybe your redirect at the end causing problems, try without it.
Here is a code sample, I was using a while ago to add CORS-headers:
#RequestMapping(value="/GetSomething", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public ResponseEntity<String> getSomething() throws IOException {
HttpHeaders responseHeaders = new HttpHeaders();
//need for cross-domain requests
responseHeaders.add("Access-Control-Allow-Origin", "*");
//this one is needed, if your browser should send cookies
responseHeaders.add("Access-Control-Allow-Credentials", "true");
...
responseHeaders.setContentLength(resp.getBytes("UTF-8").length);
return new ResponseEntity<String>(resp, responseHeaders, HttpStatus.OK);
}
EDIT: removed session-parameter
EDIT2: can you check, if the code in your POST-request is actually being executed? Make some logs in the function. If your code is not executed, then you clearly have security setup issue and your request doesn't go through security layer. CORS is client-based functionality, it can only block data AFTER the browser get it from server!
I had faced this problem before in my current project, after a lot RND and some experiments, i have found that the problem was with the content type, whenever there is a image upload will take a place to upload content type is matter a much here.
I haven't test this, but let me know after try this by replace in your code near...
var fd = new FormData();
fd.append('uploadedPicture', file);
fd.append('uploadedFrom', 'recipe');
Upload.upload({
url: 'http://localhost:8080/file/upload',
method: 'POST',
data: fd,
transformRequest: angular.identity,
headers: {'Content-Type': undefined},
}).then(function (response) {
$timeout(function () {
$scope.result = response.data;
});
}, function (response) {
if (response.status > 0)
$scope.errorMsg = response.status + ': ' + response.data;
}, function (evt) {
$scope.progress = parseInt(100.0 * evt.loaded / evt.total);
});
Let me know please after try this.
It makes no sense to return a redirect from an Ajax call. Firstly determine if the issue is with the form post or with the subsequent action. To do so change your Controller as below:
#CrossOrigin
#RequestMapping(method = RequestMethod.POST, value = "/file/upload")
#ResponseBody
public String handleFileUpload(#RequestParam("file") MultipartFile file) {
String status = null;
if (!file.isEmpty()) {
try {
Files.copy(file.getInputStream(), Paths.get(ROOT, file.getOriginalFilename()));
status = "okay";
} catch (IOException|RuntimeException e) {
status = "error";
}
} else {
status = "error";
}
return "status"; // a literal string
}
I would also note that the params sent from the front-end do not match what the backend expects. Where in the front-end do you specify a parameter named 'file' which is what the controller is going to map to the specified RequestParam?
The library in question has an end to end example using Spring MVC here:
https://github.com/danialfarid/ng-file-upload/wiki/spring-mvc-example
Note how the parameter names match on both sides.
Add the content type see this answer it may help Request not found ajax spring mvc and origins = "/**"
I am pretty new in Spring MVC and I have the following problem trying to handle an AJAX request that send an array of int to a controller method.
So I have the following situation. I have this JQuery function:
// It is global and it is initiazilized by another function:
var checkedRowList = new Array();
// SOME OTHER CODE THAT INIZIALIZED THE checkedRowList array here
...............................................
...............................................
...............................................
$('#validaButton').click(function() {
alert("validazione");
alert("CHECKED ROWS: " + checkedRowList.length);
alert(checkedRowList[0]);
$.ajax({
type: "POST",
data: {'checkedRowList' : checkedRowList},
url: "validaProgetti"
}).done(function(response) {
alert("SUCCESS");
}).error(function(xhr) {
alert("ERROR");
manageError(xhr);
});
});
So the checkedRowList is correctly initizialized (I checked it) and I use the ajax() function to send it toward the validaProgetti resource using a POST request.
Then into a controller class I have this method that have to handle the previous request:
#RequestMapping(value = "validaProgetti", method=RequestMethod.POST)
public String validaProgetti(#RequestParam List<Integer> checkedRowList, Model model, HttpServletRequest request) {
System.out.println("Numero progetti da validare: " + checkedRowList);
return "blablabla";
}
As you can see it handle HTTP Post request toward the validaProgetti resource. And Inside it I have specify the RequestParam List checkedRowList to retry the array passed by the AJAX request.
But it don't work because when the AJAX request is performed it don't enter into the validaProgetti() method and it shown the alert("SUCCESS"); popup.
Why? What am I missing? How can I fix this situation?
as I see you missed two things.
The first one is that in the Spring Web MVC controller. You don't pass a RequestParam but RequestBody.
#RequestMapping(value = "validaProgetti", method=RequestMethod.POST)
public #ResponseBody String validaProgetti(#RequestBody List<Integer> checkedRowList) {
System.out.println("Numero progetti da validare: " + checkedRowList);
return "blablabla";
}
The second one is related with your Ajax request. You should send javascript array formatted as JSON. This is done via the function JSON.stringify(), which converts js value into json.
$('#validaButton').click(function() {
alert("validazione");
alert("CHECKED ROWS: " + checkedRowList.length);
alert(checkedRowList[0]);
$.ajax({
type: "POST",
data: JSON.stringify(checkedRowList),
url: "validaProgetti",
contentType:"application/json"
}).done(function(response) {
alert("SUCCESS");
}).error(function(xhr) {
alert("ERROR");
manageError(xhr);
});
});
Also you may change the request mapping when defining in java code. Since it is a relative path, it would be confusing in some cases.
#RequestMapping(value = "/validaProgetti", method=RequestMethod.POST)
public #ResponseBody String validaProgetti(#RequestBody List<Integer> checkedRowList) {
System.out.println("Numero progetti da validare: " + checkedRowList);
return "blablabla";
}