Calling a RESTful service on an external domain via JQuery - java

I'm trying to calling a Java RESTful service by an html page, but I always get errors like the below:
No 'Access-Control-Allow-Origin' header is present on the requested resource", 405 (Method Not Allowed)
My simplest Java code is:
#SuppressWarnings({ "unchecked", "rawtypes" })
#RequestMapping(value = "/prenotazioni/{id}", method = RequestMethod.POST)
public ResponseEntity<Prenotazione> updatePrenotazione(HttpServletResponse response, #PathVariable int id, #RequestBody Prenotazione obj) {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
try {
prenotazioneService.updatePrenotazione(id, obj);
} catch (Exception e) {
return new ResponseEntity(e.getMessage(), HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<Prenotazione>(obj,HttpStatus.OK);
}
And the html code is:
$('#btnSalva').on('click', function(e){
//Creo la stringa JSON nel formato atteso dal servizio RESTful
var obj = '{"aula":{"id":' + $("#id_aula").val() + '},"id_utente":1,"data_inizio":"' + $("#datetimepicker1").data().DateTimePicker.date() + '","data_fine":"' + $("#datetimepicker2").data().DateTimePicker.date() + '"}';
var id = $("#id_evento").val();
var url = "http://localhost:8080/gestione_aule/prenotazioni/" + id;
//With $.post I've got error: No 'Access-Control-Allow-Origin
$.post( "http://localhost:8080/gestione_aule/prenotazioni/" + id, obj );
//With $.ajax I've got error: 405 (Method Not Allowed)
/*$.ajax({
url: "http://localhost:8080/gestione_aule/prenotazioni/" + id,
type: "POST",
crossDomain: true,
data: obj,
dataType: "jsonp",
success:function(result){
alert(JSON.stringify(result));
},
error:function(xhr,status,error){
alert(status);
}
});*/
/*$.postJSON = function(url, data, callback) {
return jQuery.ajax({
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
'type': 'get',
'url': url,
'data': JSON.stringify(data),
'dataType': 'jsonp',
'complete': function(e){
alert("c " + e);
},
'success': function(e){
alert("s " + e);
},
'error': function(e){
alert("e " + e);
}
});
};
$.postJSON(url, obj, function(e){alert(e);});*/
});
I've tried:
with and without specify response header in java servlet
mapping PUT and POST method
using $.post $.ajax
setting dataType json and jsonp
and many other combinations :)
But anyone worked for me... any suggest please?
Note: as I wrote in the code with $.post I've got error: No 'Access-Control-Allow-Origin, with ajax I've got error: 405 (Method Not Allowed)
Thans

The problem here that CORS (cross domain support) has 2 types of request:
Simple - such as HEAD, GET and POST. POST with content-type: application/x-www-form-urlencoded, multipart/form-data or text/plain
The rest requests are called Preflight requests
Your CORS request is a Preflight one. In Preflight requests the browser fires 2 requests:
OPTIONS - asking the server to verify that the origin, method and additional headers are trusted
The actual request - in your case POST
To fix the issue your case, add a new mapping that will handle the OPTIONS request:
#RequestMapping(value = "/prenotazioni/{id}", method = RequestMethod.OPTIONS)
public void updatePrenotazione(HttpServletResponse response, #PathVariable int id) {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");
response.addHeader("Access-Control-Allow-Headers", "accept, content-Type");
}

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.

Posting a JSON to a Spring Controller

I'm learning to pass a JSON object through ajax to a Spring Controller.
Found an article, that seems to explain how its done: http://hmkcode.com/spring-mvc-json-json-to-java/
From that point i added a #RequestMapping to the Controller:
#RequestMapping(value = "/get-user-list", method = RequestMethod.POST)
public #ResponseBody String testPost(#RequestBody ResourceNumberJson resourceNumberDtoJson) {
System.out.println(">>>>>>>>>>>>>>>>>>>>>> I AM CALLED");
return "111";
}
Then i'm forming my ajax post:
var json = {
"login" : "login",
"resource_number" : "111",
"identifier" : "1111",
"registrator_number" : "11111111111111"
};
console.log(JSON.stringify(json));
$.ajax({
type : "POST",
url : "/get-user-list",
dataType : "text",
data : JSON.stringify(json),
contentType : 'application/json; charset=utf-8',
mimeType: 'application/json',
success: function(data) {
alert(data.id + " " + data.name);
},
error:function(data,status,er) {
alert("error: "+data+" status: "+status+" er:"+er);
}
});
which is runned from "get-user-list" page.
When i'm trying to run this, i recieve a HTTP 415 error. Spring 4, Jackson 2.4
Cant understand what i'm doing wrong.
HTTP 415 means, that the media type is not supported.
Try changing your #RequestMapping annotation to
#RequestMapping(value = "/get-user-list",
method = RequestMethod.POST,
consumes="application/json")
You should also consider testing your REST-service with a client like RESTClient, Postman or even cURL to make sure it is working correctly before you start implementing the jQuery client.

Angular Spring file upload

I'm trying to hit the Spring RestController and just getting:
o.s.web.servlet.PageNotFound : Request method 'POST' not supported
I believe something is missing to map the controller.
<div class="col-sm-1" style="background-color:#cccccc;" align="center"><span class="file-input btn btn-primary btn-file">Import file<input type="file" onchange="angular.element(this).scope().uploadScriptFile(this.files)"></input></span></div>
$scope.uploadCtrFile = function(files) {
console.log(">>>>>>>>>>>>>>>>uploadCtrFile");
var fd = new FormData();
//Take the first selected file
fd.append("file", files[0]);
console.log(">>>>>>>>>>>>>>>>uploadCtrFile angular.toJson: "
+ angular.toJson(fd, 2));
$http.post('/rest/uploadCtrFile/', fd,{
withCredentials: true,
headers: {'Content-Type': undefined },
transformRequest: angular.identity
}).success(function(fd, status, headers, config) {
$scope.success = ">>>>>>>>>>>>>>>>uploadCtrFile Success: "+JSON.stringify({data: fd});
console.log($scope.success);
})
.error(function(fd, status, headers, config) {
$scope.success = ( "failure message: " + JSON.stringify({data: fd}));
console.log($scope.success);
});
};
The controller looks like...
#RequestMapping(value = "/uploadCtrFile/", headers = "'Content-Type': 'multipart/form-data'", method = RequestMethod.POST)
#ResponseBody
public void uploadCtrFile(MultipartHttpServletRequest request, HttpServletResponse response) {
Iterator<String> itr=request.getFileNames();
MultipartFile file=request.getFile(itr.next());
String fileName=file.getOriginalFilename();
log.debug(">>>>>>>>>>>>>>>>>>>submitted uploadCtrFile: "+fileName);
}
The front end shows these messages...
">>>>>>>>>>>>>>>>uploadCtrFile angular.toJson: {}" tl1gen.js:607:0
"failure message: {"data": {"timestamp":1457380766467,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/rest/uploadCtrFile/"}}"
What am I missing ?
You send undefined as the value of Content-Type, here:
headers: {'Content-Type': undefined }
But your controller requires the Content-Type with multipart/form-data value:
#RequestMapping(..., headers = "'Content-Type': 'multipart/form-data'", ...)
You should either send the correct Content-Type header in your request, like:
headers: {'Content-Type': 'multipart/form-data'}
or remove the headers options from your controller definition:
#RequestMapping(value = "/uploadCtrFile/", method = RequestMethod.POST)

Undefined Javascript Error When AJAX Call Fails

I have a Spring MVC controller being called by AJAX and returns JSON. If the call succeeds without error, I am returning a string message with the key "message". Likewise, if an exception is caught, I return a string error also with the key "message". I also return a HTTP error response.
In my Javascript, I output this "message" in an alert. The alert displays the message in the event of a successful call. If the call is unsuccessful, I get a Javascript error that "data is undefined".
Why is "data" accessible when successful but not when the call fails, and what correction do I need to make this work?
I am a newbie to AJAX calls with Spring so any general feedback/critique of my solution below is welcome and appreciated.
N.B. The alerts in the Javascript and the messages themselves are dummy implementations until I correctly provide user feedback by modifying the DOM.
The Controller
#RequestMapping(value = "/getMovieData", method = RequestMethod.POST, produces = "application/json")
#ResponseBody
public Map<String, Object> getMovieData(#RequestBody Map<String, Object> json, HttpServletResponse response) {
String movieId = json.get("id").toString();
Map<String, Object> rval = new HashMap<String, Object>();
try {
Movie movie = movieService.getMovieData(movieId);
rval.put("message", "You have succeeded");
rval.put("movie", movie);
} catch (Exception e) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
rval.put("message", "You have an error - " + e.getMessage());
}
return rval;
}
The Javascipt
function getMovieData(data) {
var request = $.ajax({
type : 'POST',
url : '<c:url value="/getMovieData" />',
dataType : "json",
contentType : "application/json; charset=utf-8",
data : data,
});
request.done(function(data) {
alert("Success: " + data.message);
populateMovieFields(data.movie);
});
request.fail(function(xhr, status, error, data) {
alert("status: " + status);
alert("error: " + error);
alert("Fail: " + data.message);
});
}
The JSON response is available inside the jqXHR object passed as the first parameter.
request.fail(function(jqXHR, textStatus, errorThrown) {
alert("Fail: " + jqXHR.responseJSON.message);
});

JQuery Ajax Requests behaving unexpectedly

I am using Jquerys Ajax method to talk to my web service. The code seems OK, but I just monitored HTTP traffic using HTTPFox firefox plugin and I noticed unexpected results. To begin with, I am setting the ContentType as application/json and my web service is also producing JSON data but HTTPFox indicates Content Type for my HTTP requests as application/vnd.sun.wadl+xml (NS_ERROR_DOM_BAD_URI).
The Request Method is GET as set in my Ajax request, but HTTPFox indicates my Request method as OPTIONS. And while the Request succeeds and data is returned, the onSuccess method of my Ajax request is not called. Instead, the onError method is called. HTTP Fox is able to capture the data from my web service as response. See the image for HTTP Fox.
Finally, all other request from other processes in my browser seem OK but my HTTP requests are flagged 'RED' by HTTP Fox. The request from other pages and processes seem OK.( GREEN or WHITE).
I have attached screenshot of HTTPFox highlighted on one of my Request. The flagged ones are also from my application.
Image:
I have also pasted the Ajax code I am using to make the HTTP Requests.
window.onload = function() {
var seq_no = getParameterByName("seq_no");
var mileage = getParameterByName("mileage");
document.getElementById("seq_no").value = seq_no;
document.getElementById("mileage").value = mileage;
var param = 'vehReg='+encodeURIComponent(document.getElementById('vehReg').value);
// alert(param);
loadVehicleInfo(param);
};
function loadVehicleInfo(params) {
$("#message").html('<p><font color="green">Loading...</font></p>');
$.ajax({
type: "GET",
url: "http://localhost:8080/stockcloud/rest/vehicles/info",
data: params,
contentType: "application/json; charset=utf-8",
dataType: "json",
success:
function(data,status) {
$("#message").empty();
$("#message").html('<p>'+getAsUriParameters(data)+'</p>');
},
error :
function(XMLHttpRequest, textStatus, errorThrown) {
$("#message").html("<p> <font color='red'>The following error occurred: " +textStatus+ ': '+errorThrown+ "</font>");
}
});
};
function getAsUriParameters (data) {
return Object.keys(data).map(function (k) {
if (_.isArray(data[k])) {
var keyE = encodeURIComponent(k + '[]');
return data[k].map(function (subData) {
return keyE + '=' + encodeURIComponent(subData);
}).join('&');
} else {
return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]);
}
}).join('&');
};
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
Server side Code for the request:
#Path("/vehicles")
public class VehiclesService {
#GET
#Path("info")
#Produces("application/json")
public Response getVehicleInfo(#DefaultValue("__DEFAULT__") #QueryParam("vehReg") String vehReg) {
// Send SOAP Message to SOAP Server
ServerResponse resp = new ServerResponse();
if("__DEFAULT__".equals(vehReg)) {
resp.setError("Vehicle registration must be supplied as a query parameter: ?vehReg=<THE REG NO>");
resp.setResult(false);
Response.status(Response.Status.BAD_REQUEST).entity(resp).build();
}
try {
// actual code to return the car info and return XML string with the info.
connection.disconnect();
String xml = URLDecoder.decode(s.toString(),"UTF-8");
xml = xml.replace("<", "<").replace(">", ">").replace("<?xml version='1.0' standalone='yes' ?>", "");
System.out.println(xml);
resp.setVehicle(new VehicleParse().parse(xml));
resp.setResult(true);
} catch(Exception e) {
resp.setResult(false);
resp.setError(e.getMessage());
e.printStackTrace();
Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(resp).build();
}
return Response.status(Response.Status.OK).entity(resp).build();
}
}
Is there something I am not doing right?
Thanks.

Categories

Resources