I am encountering a problem which I am not able to find out why.
I am using spring mvc and I am sending ajax request to one of my controller.
$.get("<c:url value="/createcomment" />", {id: pageid , newcomment : newcomment})
.done(function(data){
$("#newcomment"+data.pageId).val('');
var html = '<tr><td>'+
'<div class="pull-left">'+
'<img class="img-rounded" src="resources/profile-pics/male/small.jpg" alt="">'+
'</div><div class="span4"><ul class="nav nav-stacked">'+
'<li><font size="2"><i class="icon-user"></i>'+data.account.firstName+' '+data.account.lastName+'</font></li>'+
'<li><font size="2">'+data.text+'</font></li><li><font size="1">'+data.postingDate+
'</font></li></ul></div></td></tr>';
$(html).inserAfter($("#tr"+data.pageId));
}
When i refresh the page and send the request i get the following desired object.
and when I send it second time again i get Some Document Object.
I don't understand what is happening wrong.
#RequestMapping(value="/createcomment",method=RequestMethod.GET)
public #ResponseBody Comment createComment(#RequestParam(value="id")final String pageId,#RequestParam(value="newcomment")final String text,
final HttpServletRequest request ,final WebRequest req){
final Comment comment = new Comment();
comment.setId(GenerateUID.generate());
comment.setText(text);
comment.setPostingDate(new Date());
comment.setPageId(Long.valueOf(pageId));
try {
return comment;
} catch (NumberFormatException e) {
return null;
} catch (SignInNotFoundException e) {
return null;
}
}
Just for additonal information i am using jQuery JavaScript Library v1.7.1
You might want to check if your method throws a NumberFormatException or SignInNotFoundException, in which case it returns null. Your network log shows that 0 bytes of data have been transferred.
Related
This question is follow up of Returning ModelAndView in ajax spring mvc
As the only answer says that we need to return json from Controller not ModelAndView. So the question is
what can be done to return ModelAndView ?
How the page will be rendered:-
will it have to be handled in success section of ajax call
Or Spring Controller will return the page as usually it does in Spring MVC
How the post data from ajax can be read in Controller.
Update 1:
As explained, I tried example. here is my code.
#Controller
public class AppController
{
#RequestMapping(value="/greeting",method=RequestMethod.POST)
#ResponseBody
public ModelAndView getGreeting(#RequestBody String json) throws IOException
{
JSONObject inputjsonObject = new JSONObject(json);
String name = inputjsonObject.getString("name");
ModelAndView modelAndView = new ModelAndView();
String result = "Hi "+name;
modelAndView.addObject("testdata", result);
modelAndView.addObject("user", getPrincipal());
modelAndView.setViewName("greetingHtmlPage");
return modelAndView;
}
// other stuff
}
In above controller method i can get data sucessfully. This method is called from a javascript on home.html. Below is javascript function
function callGreeting(){
var nameData={
name : document.getElementById("name").value
}
var dataInJson = JSON.stringify(nameData);
var csrf_token = document.getElementById("token").value;
$.ajax({
type: 'POST',
url: "greeting",
data: dataInJson,
cache:false,
beforeSend: function(xhr) {
xhr.setRequestHeader('X-CSRF-Token', csrf_token);
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
},
success: function (response) {
document.open();
document.write(response);
document.close();
},
error: function (data) {
alert("failed response");
}
}); }
I have the page rendered successfully. But the url of application does not changes from AjaxSpringMVC:8080/home to AjaxSpringMVC:8080/greeting even after new page was loaded. This happens by itself in Spring MVC if using without Ajax.
what can be done to return ModelAndView ?
You can return ModelAndView As usual:
public ModelAndView returnView( Model model ) {
model.addAttribute( "myStaff", "my staff as string" );
return new ModelAndView( "myView" );
}
How the page will be rendered:
You control how it is rendered, .
When you return ModelAndView, the response has an HTML page.
After the Ajax call, you can do $("#container").html(response) or something like that to display the HTML page wherever you want.
In other words, you get a whole html page of content from the controller.
However, I highly recommend that you just return json object and update your view with the json object. Ajax is mostly used to create good user experience by updating part of the view asynchronously, so getting a whole page with Ajax does not make sense to me.
How the post data from ajax can be read in Controller.
There are many ways, I like to send json body directly to controller
#ResponseBody
#RequestMapping(value = "/saveObj", method = RequestMethod.POST, consumes = "application/json")
public String saveObj(Model model, #RequestBody MyObj myObj) {
// do staff..
}
My Volley request can come back as either JSONArray (valid) or JSONObject (error message) and in order to correctly display the error response, I want to parse the failed JSONArray string as JSONObject. It appears that JSONException objects wrap the original text. Is it possible to get just the failed text in order to parse it differently?
Example:
org.json.JSONException: Value {"error":"User has not signed up to be a customer"} of type org.json.JSONObject cannot be converted to JSONArray
and I want to get just the JSON string component because it's a valid JSONObject.
Because your response is either JSONArray (valid) or JSONObject (error message), so you can refer to the following code:
// Check the response if it is JSONObject or JSONArray
Object json = new JSONTokener(response).nextValue();
if (json instanceof JSONObject) {
// do something...
} else if (json instanceof JSONArray) {
// do something...
}
Hope it helps!
I don't think it's actually possible to retrieve just the JSON string from inside a JSONException so in the end I took the answer from BNK and did what is probably the easiest solution in this situation.
The trick seems to be to receive a StringRequest and do the JSON processing once you know there's a valid string response. Here's how that looks in my project.
StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
activity.hideProgress();
try {
Object json = new JSONTokener(response).nextValue();
if (json instanceof JSONArray) {
// an array is a valid result
dataModel.loadData((JSONArray)json);
} else if (json instanceof JSONObject) {
// this is an error
showErrorMessageIfFound((JSONObject)json);
}
} catch (JSONException error) {
error.printStackTrace();
}
refreshTable();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
activity.hideProgress();
showVolleyError(error);
// check for a JSONObject parse error
}
});
First there's a StringRequest to retrieve the response. The error response displays the error with my custom error processor. The success response parses the JSON and uses the end result to display the correct thing to the end user.
I have a JSP page with textbox,drop down list and submit button. on-change of first dropdown list, items belonging to second drop down list should be populated dynamically in the dro down list.Using ajax call i'm calling spring controller where i have written logic to populate the list of items in second dropdown list. Requirement is i need to handle the exception in the spring controller and if any exception occurs redirect the entire page to error page which is other jsp page.
javascript function to get dynamic records to populate 2nd dropdown list records on change of 1st dropdownlist.
function showSID(Id)
{
var xmlHttp;
if (window.XMLHttpRequest)
{
xmlHttp= new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
xmlHttp= new ActiveXObject("Microsoft.XMLHTTP");
}
var url = contextPath+"/getAllSID.htm?Id="+Id;
xmlHttp.onreadystatechange = function() {
handleServerResponse(xmlHttp);
};
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
function handleServerResponse(xmlHttp)
{
if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
{
if (xmlHttp.responseText != "null")
{
//handled the response..
}
}
}
}
spring controller to populate records in 2nd dropdown list on change of first dropdown list:
#RequestMapping(value = "/getAllSID", method = RequestMethod.GET)
public void getAllSIDs(HttpServletRequest request,
HttpServletResponse response,
#ModelAttribute SIDDTO dto, BindingResult beException,
#RequestParam("SelectedList") String selList)
throws IOException {
try {
SIDDTO dynamicData = myService.getSIDDynamicData();//Database call
//logic..
response.setContentType("text");
response.resetBuffer();
response.getWriter().print(SID);
}
catch (Exception e)
{
LOGGER.error("Exception occured", e);
}
}
In the above controller, myService.getSIDDynamicData() retrieves data from database, sometimes database may be down or for any other reasons i may get some exceptions.So when some exception occurs i have to redirect to myErrorPage.jsp.
I have tried using response.sendRedirect("/myErrorPage.jsp"); but could not able to redirect to errorpage, may be the reason is my page is already loaded and only when i change the dropdown control hits the above controller and as page is already loaded it could not able to redirect to error page. Please suggest how to handle the exceptions in this scenario and redirect to JSP page(error page) whenever error occurs.Thanks.
Consider adding an exception-handler method to your Spring controller. This is a method that has an #ExceptionHandler annotation. In the exception handler you can set the HTTP status to something suitable. For example:
#ExceptionHandler(value = DataAccessException.class)
public final void handleException(final DataAccessException exception,
final HttpServletResponse response) {
if (exception instanceof RecoverableDataAccessException
|| exception instanceof TransientDataAccessException) {
response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
response.setIntHeader("Retry-After", 60);
} else {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
i want to show entered data of user in a registration form (like preview page) to confirm correctness of entered data and if they accept, then that data should go into the database.
here is my controller code:
#RequestMapping( value="/catalogue/FormPreview.action", method=RequestMethod.POST)
public ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command,CatalogueBase catalogueBase) throws Exception {
if(catalogueBase.getTitleNumber()!= null)
{
request.setAttribute("titleNo", catalogueBase.getTitleNumber());
request.setAttribute("title", catalogueBase.getTitle());
request.setAttribute("name", catalogueBase.getName());
request.setAttribute("address", catalogueBase.getAddress());
request.setAttribute("email", catalogueBase.getEmail());
.....
return new ModelAndView("catalogue/catalogueFormPreview","catalogueBase",catalogueBase);
}
else
{
return create(catalogueBase);
}
}
#RequestMapping( value="/catalogue/create.action", method=RequestMethod.POST)
public ModelAndView create(#ModelAttribute CatalogueBase catalogueForm) throws Exception {
ModelAndView mvc = null;
try{
List<CatalogueBase> catalogueBases = new ArrayList<CatalogueBase>(); //getCatalogueBase(request);
catalogueBases.add(catalogueForm);
List<CatalogueBase> catalogueBaseList = catalogueService.create(catalogueBases);
mvc = new ModelAndView("catalogue/catalogueList");
} catch (Exception e) {
e.printStackTrace();
}
return mvc;
}
and I show the preview page as jsp using EL like:
Title NO : ${titleNo}
Title : ${title}
......
......
<a onclick="doAjaxPost();">Confirm Data<span class="icon icon44"></a>
and in the head section of the jsp I am calling ajax like:
<script>
function doAjaxPost() {
var name = $('#name').val();
var education = $('#education').val();
var str = $("#form").serialize();
$.ajax({
type: "POST",
url: "../catalogue/create.action",
data: str,
success: function(response){
alert("Record Added Successfully");
},
error: function(e){
alert('Error: ' + e);
}
});
};
it is showing data on preview page, but after clicking on confirm data, (hyperlink in preview page)
it sends null values to the create method(Second method) please can anyone tell why it's sending nulls and how I can solve this
thanks.
In Preview Page, you are only displaying the text, you need to get your data there as well in preview page either as hidden(or by any other means, like saving in session if much entries are there then etc). so that when you submit after confirmation, you can read all parameters.
I have the following jQuery script:
$(document).ready(function() {
$("#resendActivationEmailLink").bind("click", function(event) {
$.get($(this).attr("href"), function() {
$("#emailNotActivated").html("<span>not yet activated. email sent!</span>");
}, "html");
event.preventDefault();
});
});
Basically, when a user clicks a link the following server-side method is invoked:
#RequestMapping(value = "/resendActivationEmail/{token}", method = RequestMethod.GET, produces = "application/json")
public #ResponseBody
String resendActivationEmail(#PathVariable("token") String token) {
preferencesService.resendActivationEmail(token);
return "dummy";
}
and some business logic is executed on the server but there is no real outcome from the server to be used on the client/browser side apart from an ajax success or an ajax failure.
Now what I am really not sure about is what my server-side method is supposed to return!
Currently it just returns the string dummy but of course this is only temporary. Should I go for no return type (void) or null or something else??
Note that I can change the datatype parameter of the jQuery get method.
EDIT:
I have altered my server-side method as follows:
#RequestMapping(value = "/resendActivationEmail/{token}", method = RequestMethod.GET)
public #ResponseBody void resendActivationEmail(#PathVariable("token") String token) {
preferencesService.resendActivationEmail(token);
}
#ResponseBody is required because this is an ajax call.
There is no point in returning a dummy value in this case. If you are not doing anything with the return value, then you can just do something like this:
#RequestMapping(value="/resendActivationEmail/{token}", method=RequestMethod.GET)
#ResponseStatus(org.springframework.http.HttpStatus.NO_CONTENT)
public void resendActivationEmail(#PathVariable String token) {
preferencesService.resendActivationEmail(token);
}
There will be a 204 response code instead of a 200 but that should be fine.
I'm assuming you are returning JSON from the server (from your server code: produces = "application/json").
Since you don't care about what gets returned, i.e. you are not handling the return value in your callback function, after $.get, then you can just return "{}", or if you want to handle the response you can go with something like:
{ "success": true }
// or
{ "error": "Error messages here" }