ajax call to jax-rs with jquery issue - java

I'm trying to call a Webservice that consumes a json object with post method .I did it then It wont work again don't know what is the problem.
here is my method
#POST
#Path("/post")
#Consumes("application/json")
#Produces("application/json")
public Response testClient(Client c) throws IOException {
System.out.println(c.getAdresseCl());
ResponseBuilder builder = Response.ok(c.getAdresseCl());
builder.header("Access-Control-Allow-Origin", "*");
builder.header("Access-Control-Max-Age", "3600");
builder.header("Access-Control-Allow-Methods", "*");
builder.header(
"Access-Control-Allow-Headers",
"X-Requested-With,Host,User-Agent,Accept,Accept-Language,Accept-Encoding,Accept-Charset,Keep-Alive,Connection,Referer,Origin");
return builder.build();
}
to call this I used this
$.ajax({
type: 'POST',
url: "http://localhost:9080/FournisseurWeb/jaxrs/clients/post",
data: '{"adresseCl":"tunis"}',
dataType:'json',
contentType: "application/json; charset=utf-8",
success: function (msg) {
alert(msg);
},
error: function (xhr, ajaxOptions, thrownError) {
alert('error');
}
});
well I remark that when I set the contentType to application/json the method changes to OPTIONS .
and when I don't use the content type I got "415 Unsupported Media Type " I dont know how to fix this. I passed too much time without results :(thank you for helping me

When attempting to make cross-domain AJAX requests in certain browsers, it is a common to see the HTTP Method change to OPTIONS in lieu of a more meaningful error message.
I noticed in your URL that you're including the protocol, domain, and port, which supports the theory that you're actually trying to make an AJAX request to a different domain/port combination than the originating context.
To clarify, even if your request is originating from localhost and targeting localhost, the ports (9080) and protocols (http) must also match.
Thus, if the page you loaded is "http://localhost:8080" and you're trying to make an AJAX request to "http://localhost:9080", the request will fail, may throw same-domain security errors, 415 Unsupported Media Type, and/or change the HTTP Method to OPTIONS.
One way to make sure you avoid this mistake is to only use full or relative paths when making AJAX requests, such as:
url: "/FournisseurWeb/jaxrs/clients/post",
This forces you to always make requests to the same domain.
Cross-domain Requests
If you do indeed require the ability to make cross-domain requests, this is possible, but only through two methods.
First, you can use a proxy, where you make an HTTP request to your domain and then forward the request onto another server. Servers need not be concerned with same-domain policies when sending and receiving data from one another.
Second, you can use JSONP, also known as script tag remoting, which involves exploiting the <script> element's ability to send requests across different domains.
// added callback= query parameter to convert this to JSONP
$.ajax({
type: 'POST',
url: "http://localhost:9080/FournisseurWeb/jaxrs/clients/post?callback=",
data: '{"adresseCl":"tunis"}',
dataType:'json',
contentType: "application/json; charset=utf-8",
success: function (msg) {
alert(msg);
},
error: function (xhr, ajaxOptions, thrownError) {
alert('error');
}
});
NOTE: When using JSONP, your server must respond with the JSON wrapped up in a function call identified by the callback parameter. See the jQuery documentation for more in-depth details .
Other than that, you must make AJAX requests to the same domain the page was loaded from.

this is the method that consumes a text xml fomat and map it to an object to persist it next
#POST
#Path("/inscription")
#Produces(MediaType.TEXT_HTML)
public Response testClient(String s) {
ResponseBuilder builder = null;
try {
final String xmlString = s;
final StringReader xmlReader = new StringReader(xmlString);
final StreamSource xmlSource = new StreamSource(xmlReader);
final JAXBContext jaxbContext = JAXBContext
.newInstance(Client.class);
final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
final Client client = (Client) unmarshaller.unmarshal(xmlSource,
Client.class).getValue();
System.out.println("nomCl : " + client.getNomCl());
System.out.println("prenomCl : " + client.getPrenomCl());
System.out.println("emailCl : " + client.getEmailCl());
System.out.println("numTel : " + client.getNumTel());
System.out.println("long_ : " + client.getLong_());
System.out.println("lat : " + client.getLat());
System.out.println("LoginCl : " + client.getLoginCl());
System.out.println("PasswordCl : " + client.getPasswordCl());
System.out.println("adresseCl : " + client.getAdresseCl());
EntityManagerFactory factory;
factory = Persistence.createEntityManagerFactory("FournisseurWeb");
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
em.persist(client);
em.getTransaction().commit();
em.close();
factory.close();
builder = Response.ok("true");
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
builder = Response.ok("false");
builder.header("Access-Control-Allow-Origin", "*");
builder.header("Access-Control-Max-Age", "3600");
builder.header("Access-Control-Allow-Methods", "POST");
builder.header(
"Access-Control-Allow-Headers",
"X-Requested-With,Host,User-Agent,Accept,Accept-Language,Accept-Encoding,Accept-Charset,Keep-Alive,Connection,Referer,Origin");
return builder.build();
}
builder.header("Access-Control-Allow-Origin", "*");
builder.header("Access-Control-Max-Age", "3600");
builder.header("Access-Control-Allow-Methods", "POST");
builder.header(
"Access-Control-Allow-Headers",
"X-Requested-With,Host,User-Agent,Accept,Accept-Language,Accept-Encoding,Accept-Charset,Keep-Alive,Connection,Referer,Origin");
return builder.build();
}
I use to call this method using ajax with this sample :
var x="<client><nomCl>Taarit</nomCl><prenomCl>Aymen</prenomCl><emailCl>aymen.taarit#gmail.com</emailCl><numTel>222</numTel><long_>1.66</long_></client>";
$.ajax({
url: 'http://localhost:9080/FournisseurWeb/jaxrs/clients/cl',
type: 'post',
scriptCharset: "utf-8" ,
dataType:"xml",
data: x,
success: function(data, status) {
console.log(data);
}
});
this is a jax-rs call with ajax POST using cross domain so hope that it helps :)
NOTE: The cross-domain call without JSONP is legal here because the server is returning the following header, which enables cross-domain AJAX!
builder.header("Access-Control-Allow-Origin", "*");
See Mozilla Developer Center page on Access-Control-Allow-Origin for more details.

Related

POST request with multipart data in spring mvc

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 = "/**"

How to correctly handle this AJAX request that send an array to a Spring MVC controller method? Why it can't work?

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

Consume Cookie and JSON with JAX-RS Jersey Service

I am sending these data to Restful Web Service (Jersey) using jQuery code and the method POST:
var dataString = {"id":1,"status":"passed","session":"nothing"};
$.post("https://localhost:8443/pv01/ws/user/cookie", dataString);
And with this data, I am sending a cookie. The data in te cookie come from an external API.
The problem what I am facing is how to receive the cookie value and the dataString together.
Here's my Java code to read a Cookie :
#POST
#Path("cookie")
public String cookie(#CookieParam("L14c") String str) {
Logger.getLogger(Main.class.getName()).log(Level.INFO, "message : " + str );
return str;
}
And for the data, I can do like this :
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Path("cookie")
public String cookie(DataString dataString) {
Logger.getLogger(Main.class.getName()).log(Level.INFO, "message : " + dataString );
return "ok";
}
But when I combine the two methods to accept cookie and the JSON dataString, I got Error 415, Unsupported media type!
I tried to look on HTTP Headers, but I can access only cookies.
The problem is with the jQuery request. It looks like the Content-Type is defaulting to application/x-www-form-urlencoded. You should use a Browser debugger like Firebug. Makes it easier to spot these kind of things.
From what I've tested, it should work with something like
$.ajax({
url: theUrl,
type: "POST",
data: JSON.stringify(dataString),
dataType: "json",
contentType: "application/json",
success: function(response) {
alert(JSON.stringify(response));
}
});

400 Bad Request!! when I try to send ajax request to Servlet in spring mvc

/*ajax request to servlet to perform update operation*/
var savedata={
video_Title:videotitle,
video_duration:videoduration,
video_Url:videourl,
video_Description:videodescription
};
$.ajax({
url:'videoUpdate',
type:'POST',
cache:false,
data: savedata,
contentType: "application/json; charset=utf-8",
success: function(response) {
alert("Updated Successfully");
},
error:function()
{
alert("oops sorry something went wrong. we apologize for the inconvenience");
}
});
/*Controller Class*/
#RequestMapping(value ="videoUpdate",method = RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody Status updateVideo(#RequestBody Video video) {
try {
System.out.println("update servlet");
dataServices.updateVideo(video);
return new Status(1,"video updated Successfully");
}
catch (Exception e) {
return new Status(0,e.getMessage().toString());
}
}
My question is how to receive ajax-json request data in my servlet class.Is this is the correct way to catch a set of data from ajax in spring mvc.Or other annotation is required for avoiding 400 error!?
The 400 Bad Request seldom happens because the url viz videoUpdate could not be mapped to appropriate mapping.
This could be because you might not be passing the arguments required to make to point cut.
I would suggest you to inspect following portion of your code:
var savedata={
video_Title:videotitle,
video_duration:videoduration,
video_Url:videourl,
video_Description:videodescription
};
And make sure you are passing required parameters.
If you specify
contentType: "application/json; charset=utf-8",
that means you are expecting JSON data in return - if it's not valid JSON then it goes to the error block.
You are probably returning a string :
return new Status(0,e.getMessage().toString());
Try omitting the contentType line. Also posting browser console errors might help us determine the problem easier.
Note: If you want to specify the outgoing data type there's a dataType setting.
Assuming the URL you are hitting is correct, you could look at whether the fields of the Video class exactly match the JSON you are POSTing

XMLHttpRequest Exception 101 when i try to call POST rest with jquery

i'm using jquery ,jersey and json.
when i try to call a post service i receive this error
Origin null is not allowed by Access-Control-Allow-Origin.
undefined * Error: NETWORK_ERR: XMLHttpRequest Exception 101
My client code
$.ajax({url: jurl, type: 'POST', dataType : 'json', headers: {accept:"application/json"},data: inData , cache : false, async : false, contentType : "application/json; charset=utf-8",
My server Code
#POST
#Path(ReferentialPath.PLAYER_RESOURCE_PATH)
#Consumes(MediaType.APPLICATION_JSON)
public Response createPlayer(CreatePlayerIn cPlayer) {
try {
String res = dao.create(player);
UriBuilder ub = uriInf.getAbsolutePathBuilder();
URI createdUri = ub.path(res).build();
return Response.created(createdUri).build();
} catch (Exception e) {
}
}
Would anybody tell me what could be the problem
you seem to be trying to POST to another domain.
possible problem wiki
possible solution :you should read this SO question
Here I guess there must be some firewall between your client and server. HTTP Code 101 represents that your http request be filtered by your net work device. so change your net work and directly connect your server. and try again.

Categories