In my spring mvc project i have 2 controller, one of them mapped like that:
#Controller()
#RequestMapping("/draft")
I am trying to send some data from ajax like that:
$.ajax({
type : 'get',
url : 'http://localhost:8080/FootballManager/draft/draftplayer',
dataType : "json",
data : {
'playerID' : playerID,
'username' : username,
'leaguename' : leaguename
},
response : 'text',
success : function(data) {
if (data == 1) {
alert("player drafted");
} else {
alert("player not drafted");
}
},
error : function(XmlHttpRequest, textStatus, errorThrown) {
_requesComplete = true;
alert("error= " + errorThrown);
}
and method in controller:
#RequestMapping(value="/draftplayer",method = RequestMethod.GET)
public #ResponseBody
String draftPlayer(#RequestParam("playerID") int playerID,
#RequestParam("username") String username, #RequestParam("leaguename") String leaguename,HttpSession session) {
try {
...
return "1";
} catch (Exception e) {
return "0";
}
}
And I always get Bad Request, but if I put this method into another controller, which has no #RequestMapping annotation in class reference, and change url to
url : 'http://localhost:8080/FootballManager/draftplayer',
it works perfectly. I spent a lot of time for this issue, why it happens like that? (Sorry for my english..)
Problem solved. I have method in my controller, which mapped like draft/{leaguename}, and when in send request to draft/draftplayer, it mapped to first method
Related
In my code, i have two RequestMapper in my Controller which is designed this way :
#Controller
#RequestMapping("/myHostel.html")
public class HostelController
{
#RequestMapping(method = RequestMethod.GET)
public ModelAndView getText()
{
// do some cool stuff but not the point here
}
#RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public String getMyUrl()
{
String myVariable;
return "{\"myUrl\": \""+myVariable+"\""}";
}
}
And my ajax code :
function openNewTab() {
$.ajax({
url : 'myHostel.html',
type: "POST",
dataType: "json",
beforeSend: function(xhr) {
xhr.setRequestHeader("Accept", "application/json");
},
success : function(response){
console.log(response);
window.open(response.url, '_blank');
},
error: function(jqXHR, exception, errorThrown)
{
console.log(jqXHR.status);
console.log(exception);
console.log(errorThrown);
}
});
}
and my button is kinda like this :
<button tabindex="0" id="mySweetButton" class="btn btn-primary"
onclick="openNewTab();" >
Open a new tab
</button>
And what i get is :
200
parsererror
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
--
I've tried with putting a session variable in the model and a making a window.open(URL_IN_SESSION);
But if you reload the page, it's calling it again.
Making a c:remove on the variable when it's not used to cancel this problem but to no avail.
I have to get a variable from my ModelView after some previous call and open it in ajax (or javascript whatever as long as it works) to have my main page and my new tab with the custom URL.
If anyone has a idea on what i'm doing wrong ? (I need a custom URL made in my controller by previous GET call with user choices.)
Thank you for reading !
Solved by making just another GET requestMapping using no parameters and with value = ("/myHostel.html/getMyUrl.html")
One of the problem was the filters that only allowed .html url for the mapping.
The other was the JSON, just using :
#RequestMapping(method = RequestMethod.GET, value = "/getUrl.html")
public ResponseEntity<String> sendUrl()
{
return new ResponseEntity<>(getMyUrl(), HttpStatus.OK);
}
And parsing the return in ajax :
function openNewTab() {
$.ajax({
url : 'myHostel.html/getUrl.html',
type: 'GET',
dataType: 'text',
success : function(data){
window.open(data, '_blank');
}
});
}
And it solved the problem.
I have a SpringMVC/Thymeleaf applications where the following Ajax handling works perfectly fine if I return a boolean. However, as soon as the method is void, then I get the error
Unexpected end of JSON input in Firebug. This is a POST request.
#ResponseBody
#PostMapping("/addOrUpdate")
public void /*boolean works!*/ addOrUpdate(#RequestBody String json) throws Exception {
service.addOrUpdateUserRoles(json);
/*boolean works - return true;*/
}
JS
$.ajax({
type : "post",
dataType : 'json',
contentType : 'text/plain',
url : 'addOrUpdate',
data : id
})
.then(function() {
//...
})
.fail(function(jqXHR, textStatus, errorThrown) {
//...
});
If I just remove #ResponseBody from the method definition, Thymeleaf complains,
org.thymeleaf.exceptions.TemplateInputException: Error resolving template [addOrUpdate], template might not exist or might not be accessible by any of the configured Template Resolvers
I followed the ResponseEntity example here, but it didn't help -- same error, JS goes into the Error section with Unexpected End of Input.
#ResponseBody
#PostMapping("/addOrUpdate")
public ResponseEntity addOrUpdate(#RequestBody String json) throws Exception {
service.addOrUpdate(json);
return new ResponseEntity(HttpStatus.OK);
}
With dataType : 'json', you are telling jQuery that you're expecting JSON as a response. An empty response is no valid JSON, and the error message Unexpected end of JSON input is telling you exactly that.
If you intend not to return anything from the addOrUpdate controller method, remove the #ResponseBody annotation, as there is no response body, and stick to the ResponseEntity but use HttpStatus.NO_CONTENT instead to inform clients in your response that there's no content to be expected. Also, change your dataType to something that may be empty, like 'text'.
As the exception says, the point of failure is input.
You need to send json format input.
$.ajax({
type : "post",
dataType : 'json',
contentType : 'text/plain',
url : 'addOrUpdate',
data : {id: id}
...
FINAL SOLUTION based on digitalbreed's answer
Controller
#PostMapping("/addOrUpdate")
public ResponseEntity<String> addOrUpdate(#RequestBody String json) throws Exception {
try {
service.addOrUpdate(json);
return new ResponseEntity<String>(HttpStatus.OK); // No exceptions
}
catch (Exception e) {
log.error("Error", e);
return new ResponseEntity<String>(HttpStatus.BAD_REQUEST); // This will enable JS to catch the Exception from Ajax
}
}
JS
$.ajax({
type : "post",
dataType : 'text', // Returns a ResponseEntity, not JSON (Void method)
contentType : 'text/plain',
url : 'addOrUpdate',
data : somedata
})
.then(function() {
//...
})
.fail(function(jqXHR, textStatus, errorThrown) {
//... - will come here for a ResponseEntity of 'Bad Request'
});
I'm getting this in the console when I'm trying to update data in my database, using spring mvc and ajax from my jsp.
http://localhost:8080/my_project/activerutilisateur/user 405 (Méthode Non Autorisée)
See my code below:
DAO
public Utilisateur updateUtilisateur(Utilisateur utilisateur) {
sessionFactory.getCurrentSession().update(utilisateur);
return utilisateur;
}
Controller
#RequestMapping(value="/activerutilisateur/{username}", method=RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public Utilisateur activerUtilisateur(#PathVariable String username, #RequestBody Utilisateur utilisateur) {
utilisateur = service.getUtilisateurById(username);
utilisateur.setEnable(true);
return service.updateUtilisateur(utilisateur);
}
Ajax request
<script>
function activerUtilisateur(username) {
var user = {"username" : username}
$.ajax({
contentType: 'application/json',
type: 'POST',
url: 'activerutilisateur/',
data : JSON.stringify(user),
error: function(xhr,error,textStatus){
console.log(textStatus);
},
complete: function(data) {
console.log(data);
console.log('complete done');
},
success: function(data) {
alert('success done');
}
});
}
</script>
It's the only method which doesn't work in the project
Someone could please help me to find what I did wrong?
Thanks
I finally found what's wrong here :
https://matthewbusche.com/blog2/2016/08/06/using-csrf-with-spring-security-and-ajax-calls/
It's due to csrf
Your controller is a POST method, but you are reading the pathVariable, instead of any request body, normally in POST call you need to send Payload to your controller. And in Ajax, you are passing
url: 'activerutilisateur/'+username ----> for PathVariable
data: {'username' : username} ----> There is no requestBody in Controller for this payload.
You should update your controller to have a Request Body as an Argument.
Edited: I ran below code and its working fine in my local machine
JSP/JS Code:
<script>
function activerUtilisateur(username) {
var user = {
"username" : username
}
$.ajax({
contentType: 'application/json',
type: 'POST',
url: 'activerutilisateur/',
data : JSON.stringify(user),
error: function(data){
console.log('Motif erreur : '+data);
},
complete: function(data) {
console.log('complete done');
},
success: function(data) {
console.log('success done');
}
});
}
</script>
Controller Code:
#RequestMapping(value = "/activerutilisateur/", method = RequestMethod.POST)
#ResponseBody
public Utilisateur activerUtilisateur(#RequestBody Utilisateur user) {
service.activerUtilisateur(username);
return user;
}
Model code:
public class Utilisateur {
private String username ;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
Also, it seems you have enabled csrf protection, so check Sending CSRF Token from JS for sending csrf token in the call to the controller.
I suppose that this is your Utilisateur model class :
public class Utilisateur {
private String username ;
// getter & setter
}
In your Controller :
#RequestMapping(value="/activerutilisateur/", method=RequestMethod.POST)
#ResponseBody
public Utilisateur activerUtilisateur(#RequestBody Utilisateur user) {
return service.activerUtilisateur(user.getUsername());
}
In your Ajax Call :
<script type="text/javascript">
function activerUtilisateur(username){
var user = {
"username" : username
}
$.ajax({
type: 'POST',
url: 'activerutilisateur/',
data : JSON.stringify(user)
error: function(xhr, error, textStatus){
console.log('Motif erreur : '+textStatus);
},
success:function(data){
console.log(data);
}
});
}
</script>
I have a ResponseEntiy that receives a comment:
#RequestMapping(value="/save-comment", method=RequestMethod.POST)
#ResponseBody
public ResponseEntity<?> saveComment(#RequestParam("name") String comment, #RequestParam("id") long id) {
SiteUser user = authController.getUser();
String cleanedCommentBody = htmlPolicy.sanitize(comment);
StatusUpdate status = statusUpdateService.getOneById(id);
Comment createdcomment = new Comment();
createdcomment.setCommentdate(new Date());
createdcomment.setCommenttext(cleanedCommentBody);
createdcomment.setStatusUpdate(status);
createdcomment.setSiteUser(user);
commentService.createComment(createdcomment);
return new ResponseEntity<>(null, HttpStatus.OK);
}
The code in my JSP works fine.... it sends the values to my Controller method and the method receives it, process the information and saves the new comment in the database, but after that, showing the same page.... it gives me the error. But other POST request I have work fine.
http://192.168.160.128:8080/viewonestatus/58
Exception: org.springframework.web.HttpRequestMethodNotSupportedException:
Request method 'POST' not supported
Failed URL: http://192.168.160.128:8080/viewonestatus/58
Exception message: Request method 'POST' not supported
The AJAX snippet is that gives an ok code is:
.....
<c:url var="saveComment" value="/save-comment" />
.....
function saveComment(text) {
//alert("El texto es...text " + text);
editComment(text, "${status.id}", "${saveComment}");
}
function editComment(text, id, actionUrl) {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
jqXHR.setRequestHeader(header, token);
});
$.ajax({
'url' : actionUrl,
data : {
'name' : text,
'id' : id
},
type : 'POST',
success : function() {
alert("Ok");
},
error : function() {
alert("error");
}
});
}
I have a transaction object and I am trying to send the object to the front page. I have no problem when I try to send a string, but I couldn't send an object.
So this is my controller:
#RequestMapping(value="/result/helloajax", method=RequestMethod.GET)
#ResponseBody
public MyTransaction helloahjax() {
System.out.println("hello Ajax");
MyTransaction tran = MyTransaction.getInstance();
tran.setId(123);
return tran;
}
#RequestMapping(value="/result", method=RequestMethod.GET)
public String show() {
return "result";
}
and this is my ajax call
button
<div class="result"></div>
function doajax() {
$.ajax({
type : 'GET',
url : '${pageContext.request.contextPath}/result/helloajax',
success : function(response) {
$('.result').html(response.id);
},
error: function() {
alert("asda");
}
});
};
I search around and see that other developers used "response.result.id" but I couldn't make it neither. Any suggestion please.
I would suggest to change your code like below.
1.Include JSON library to your classpath and add produces="application/json" attribute to RequestMapping for the helloahjax method.
#RequestMapping(value="/result/helloajax", method=RequestMethod.GET,produces="application/json")
2.Include dataType in your ajax call,like below
$.ajax({
type : 'GET',
dataType : 'json',
url : '${pageContext.request.contextPath}/result/helloajax',
success : function(response) {
var obj = JSON.parse(response);
//Now you can set data as you want
$('.result').html(obj.id);
},
error: function() {
alert("asda");
}
});
The URL would change to below when you are returning JSON from the controller method. In this case you don't need to parse the response. Instead you can directly access the object variables as response.abc
${pageContext.request.contextPath}/result/helloajax.json