How to trigger a function in Javascript - javascript

If the user doesn't input a correct string it will fail the try. it's fine
My only problem is that I want to send the exception to the error function in the ajax. ATM is sending it to the success.
How do I trigger some sort of error so it sends to the error function in ajax?
public static String call(String input) {
try {
//doesn't matter. it will fail this try
}
} catch (Exception e) {
return e.getMessage(); // I want to send this to the error function in ajax
}
return "Good job";
}
AJAX
$.ajax({
url: '/call',
type: 'get',
data: {input: input},
success: function (resultString) {
//it sends to here instead of error
},
error: function () {
// i want to see it here
}
})

This question is use case dependent, as the correct answer depends on the type of error, business rules and other factors like information exposure.. but to try sending you in the correct direction, you will need to send an HTTP error code, probably a 400 as in https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400
This is an example of a how a servlet can do it (this is also case dependent as the method to use depends on you back end tech):
catch ( MalformedFileUriException e ) {
response.setStatus( HttpServletResponse.SC_BAD_REQUEST );
log.warn( "...", e );
}
catch ( UnsupportedLocaleException e ) {
response.setStatus( HttpServletResponse.SC_BAD_REQUEST );
log.warn( "...", e );
}
catch ( Exception e ) {
response.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
log.error( "...", e );
}

public static String call(String input) {
try {
//doesn't matter. it will fail this try
}
} catch (Exception e) {
echo json_encode(array("status"=>false,"msg"=>e.getMessage())); // I want to send this to the error function in ajax
}
echo json_encode(array("status"=>true,"msg"=>"Good job"));
}
JS
$.ajax({
url: '/call',
type: 'get',
data: {input: input},
success: function (resultString) {
var d = $.parseJSON(resultString);
if(d.status){
//do stuff
}else{
alert(d.msg);//Your alert message
}
}
})
AJAX doesn't catch the error thrown by server in error function. You need to do it manually to let AJAX know if it was a success or an error. You need to use json_encode and set status true or false.
Check in your AJAX if status is false it means the error was thrown from the server.
PS - I don't know the json_encode syntax in JAVA so I have used the syntax of PHP. Please replace it. But you will get the idea from this.

The ajax success or error gets executed when the AJAX call completes successfully or fails respectively. So basically it does not care what result you are returning from backend. if your backend fails to return any data, only then the AJAX will run into an ERROR block. so if you want to distinguish between your try block returning data and error block returning data you have to apply some logic in your success part of AJAX.
So my approach would be to send the data as a list of text and value rather than a string. you can set the [text] part as "OK" when your backend return data from a try block or else you can set the [text] block as "Error" in case of catch block returning. And the [Value] of list would be the desired values.
So conclusion use list<> in place of string as a return type, and set the [Text] and [Value] field as required.

Related

Why ajax call send null to servlet? [duplicate]

This question already has answers here:
How should I use servlets and Ajax?
(7 answers)
HTTP request parameters are not available by request.getAttribute()
(1 answer)
Closed 3 years ago.
I'm trying to send the username to the servlet through an ajax call to check its availability, but the servlet show a null pointer exception.
I've also tried with the XMLHttpRequest instead of $.ajax.
This is my Javascript file:
$(document).ready(function() {
$("#reg-form").submit(function() {
var res = true;
if (!testUser()) {
res = false;
$("#erruser").css("display", "block");
$("#username").addClass("errclass");
} else {
$("#erruser").css("display", "none");
$("#username").removeClass("errclass");
}
return res;
});
});
function testUser() {
var el = $("#username").val();
var b = false;
$.ajax({
type: "POST",
url: "CheckUserServlet",
data: { user: el },
dataType: "json",
success: function(bool) {
alert(bool);
if (bool == "si") b = true;
},
error: function() {
alert("errore");
}
});
return b;
}
This is my servlet doPost method:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username=request.getAttribute("user").toString();
System.out.println("username servlet= "+username);
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
if (!ud.doRetrieveByUser(username)) {
response.getWriter().write("si");
return;
}
response.getWriter().write("no");
return;
}
Thanks!
CLIENT SIDE
Your test user function will always return false regardless of if the server is operating correctly because $.ajax() is an async function. There are a few ways around this. In your case, without knowing much more about what you are building, I would suggest removing the return value from your test user function, and moving your logic into the success/failure areas in the ajax callback. This way, the ajax call just does it's thing and lets the success function modify your page however you want.
function testUser() {
var el = $("#username").val();
$.ajax({
type: "POST",
url: "CheckUserServlet",
data: { user: el },
dataType: "json",
success: function(bool) {
alert(bool);
// put logic here
if (bool === "si") {
$("#erruser").css("display", "block");
$("#username").addClass("errclass");
} else {
$("#erruser").css("display", "none");
$("#username").removeClass("errclass");
}
},
error: function() {
alert("errore");
}
});
}
I would also suggest setting up the initial state of your page so that while this request is happening the user is shown something that makes sense. Answer the following question: "what do I show my users when the page does not know yet if it is a test user" and then set the initial state of the page accordingly
SERVER SIDE
I've always found interacting with java & JSON data a bit clunky, and your issue seems like something I've grappled with in the past.
Your question is "why is ajax sending null to the server". It may seem like that but what is really happening is that your server doesn't understand how to interpret the data it is getting. Take a look at this question about getting a JSON payload.. You need to tell your server how to parse the data coming from the client. If you were to inspect the data being sent, I would expect it looks something like this {"user":"blablabla"}.
If you have a class definition already, use that. For this I am using something that looks like this:
public class UserRequest {
String user;
}
// get the body as a string. Requires https://commons.apache.org/proper/commons-io/
String body = IOUtils.toString(request.getReader())
// parse the json with gson. Requires https://github.com/google/gson
Gson g = new Gson();
User u = g.fromJson(body, UserRequest.class);
String username = u.user;

Ajax can success() handle two type of return?

Working in a C# ASP.NET project with JavaScript/Jquery/jqGrid.
New task is to have a page to i) accept an Excel input file, ii) use the column ID to look up additional information, and iii) generate a new Excel file using some columns from input file and all columns returned from database.
I have completed that, but just want to do a bit more error handling. In the stored procedure, if everything works fine, it returns a data table (or in Oracle term, a CURSOR). If there is an error, I have added a catch block and return an error message.
I modify the AJAX call. Beside adding dataType as 'text', I expect the return as XML.
$.ajax({
// POST
// URL: url to call that stored procedure
dataType: text,
success: function (response) {
// now the response is XML (don't know why...
// specify dataType as 'text', but get XML...)
// If response contains 'string' tag, report error.
},
failure: ...
})
Here is what I used to do. I don't specify the dataType but somehow that works.
$.ajax({
// POST
// ... rest is same but without the dataType
success: function (response) {
Download( response )
// The file is already and placed in Download directory.
// Call 'Download()' will actually make the download happen
// But here response is just a path to the Download directory +
// download file name.
And Download() is:
function Download(url) {
document.getElementById('my_iframe').src = <%=ResolveUrl("~/")%> +url;
return false
};
How can I have the success function handle both type of response?
(Just for your information: The front-end page is ASP.NET. Button click will call a JavaScript function. The function calls a web service function via $.ajax(). As there are many rows, the web service function calls a function in a database class many times - each time pass in just one ID. The function will in return call stored procedure.)
Edit: Thanks for solution from Mustapha Larhrouch. Here are some points that I have to adjust:
Add dataType.
If response is XML, check if error.
If not XML, just download.
And here is my code:
$.ajax({
// POST
// URL
dataType: "text",
success: function (response) {
if (isXML(response)) {
var xmlDoc = $.parseXML(response);
$xml = $(xmlDoc);
var errMsg = $xml.find("string").text();
if (errMsg != "" ) {
// pop up a dialog box showing errMsg
}
}
else {
Download(response);
}
you can check if the response is an xml if it's parse it, if not the response is a string. and you can use this function to check if the response is an xml :
function isXML(xml){
try {
xmlDoc = $.parseXML(xml); //is valid XML
return true;
} catch (err) {
// was not XML
return false;
}
}
$.ajax({
// POST
// ... rest is same but without the dataType
success: function (response) {
if(isXML(response){
Download( response )
}
else{
//report as error
}

Sending a string to ActionResult using ajax

I am trying to send a string to my ActionResult in the controller. I have followed many tutorials and read hundreds of stackoverflows but can't get it to work. I am trying to send a string with the value of a radiobutton.
My ActionResult code is:
[HttpPost]
public ActionResult Opslaan(string theStatus)
{
if(theStatus!= null)
Database.UpdateAanvraagStatusByGuid(Session["Guid"].ToString(), theStatus);
return new RedirectResult(Request.UrlReferrer.OriginalString);
}
My code to send the variable via AJAX:
$("#opslaan").click(function (e) {
e.preventDefault();
var theStatus = $('input[name=StatusOptions]:checked').val();
$.ajax({
type: "POST",
url: "/Aanvraag/Opslaan",
data: theStatus,
success: function (result) {
if (result.Success) {
alert("Uw wijzigingen zijn opgeslagen.");
} else {
alert(result.Message);
}
}
});
});
When I click my button called "opslaan" the program does not execute te AJAX. Alerts around it do go off.
Thanks in advance :)
Edit Fabio's answer like this:
$("#opslaan").click(function (e) {
e.preventDefault();
var theStatus = $('input[name=StatusOptions]:checked').val();
$.ajax({
type: "POST",
url: "/Aanvraag/Opslaan?theStatus= " + theStatus ,
//data: { 'theStatus': theStatus } ,
success: function (result) {
if (result.Success) {
alert("Uw wijzigingen zijn opgeslagen.");
} else {
alert(result.Message);
}
}
});
});
Note the query string at the end of the url property. Even though string IS a nullable type, if you don't have any route configuration like "/Aanvraag/Opslaan/theStatus", the routing system will not find a match.
There are a few things to note here:
Your original solution DID show an alert, that means a request went to the server, and a response has arrived.
Fabio's answer didn't work because you (as I guess) don't have any route like "/Aanvraag/Opslaan/theStatus". Even though string is a nullable type - so the routing system will allow a string parameter to have no incoming value from the request - the url parameter set by the client told the routing system 'Hey please forward me to something that is configured to a url like "/Aanvraag/Opslaan/theStatus"'. I am sure You don't have any route set up with that pattern so the routing system will fail to find a matching Controller/Action method pair, that results in a 404.
Your original solution didn't cause this problem, because you sent the theStatus parameter as data, and your url was "/Aanvraag/Opslaan". This means even the default route will be able to find out that the Controller is 'Aanvraag' and the controller is 'Osplaan'. From then on, Model Binding was able to bind your theStatus parameter to the action method parameter. (If it wasn't, the proper action method would strill be called, just with a null value given to the parameter.) However, your response didn't send any object with property Success back, so your if statement went to the else branch.
All in all, you can either send the theStatus parameter as data and let the model binding system to bind it to your action method parameter, or use routing to do that for you. In this latter case, you must either configure a proper routing entry or use a query string like in my modified version.
For the if statement to work, you need to send back something that does have a Success property, like Fabio did.
It might be helpful:
[HttpPost]
public ActionResult Opslaan(string id)
{
if(id != null)
Database.UpdateAanvraagStatusByGuid(Session["Guid"].ToString(), id);
// do your logic to check if success is true or false
return Json(new { Success = true, Message = "something" });
}
Javascript:
$("#opslaan").click(function (e) {
e.preventDefault();
var theStatus = $('input[name=StatusOptions]:checked').val();
$.ajax({
type: "POST",
url: "/Aanvraag/Opslaan/ " + theStatus ,
//data: { 'theStatus': theStatus } ,
success: function (result) {
if (result.Success) {
alert("Uw wijzigingen zijn opgeslagen.");
} else {
alert(result.Message);
}
}
});
});
EDIT
Just to see if it works, change the name of the parameter in the Action and Javascript.

How to receive messages from backend asynchronously?

I need to verify usernames, so when user enters the username it should be sent to backend to verify its availability. I have the following code but have doubt in receiving the available or unavailable message from backend.
function verifyUsername(value){
if(window.XMLHttpRequest)
{
xmlhttp = new XMLHttpRequest();
}
else
{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if(xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
document.getElementById("mymessage").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("get","verifyUsername?username="+value,false);
xmlhttp.send();
}
....
<div id="mymessage"></div>
....
Server End Psuedo Code (actual implementation: Java)
....
if(verify(username))
return "Username is not available";
else
return "username is available";
I'll give a jQuery example of this, I won't bother with the pure JavaScript version. What you are looking for is a callback function to fire once the ajax request has been returned.
// listen to a click event on a button OR something
$("#buttonName").on("click", function(event){
// prevent any default activity
event.preventDefault();
// get your value
var value = $("#mymessage").val();
// jQuery ajax event
$.ajax({
url : "verifyUsername?username="+value,
type: 'GET'
}).done(function ( data ) {
if ( console && console.log ) {
console.log( "Data returned :"+data )
// do something else
}
}):
.done() is the success callback option, there are others as well:
// jQuery ajax event
$.ajax({
url : "verifyUsername?username="+value,
type: 'GET'
})
// successful callback
.done(function(){ // success })
// fail/error callback
.fail(function(){ // fail })
// completed callback
.always(function(){ // will always execute, even if request fails })
});
Reference : http://api.jquery.com/jQuery.ajax/
If I am understanding the problem correctly, it is, "returning the correct response back from the server-side".
The actual implementation is mentioned as Java, so I am assuming there is a backend Servlet that the Ajax request submits to.
You would need to get a handle on the HttpServletResponse object in your doGet method(as you are using get), add your logic to verify the username and the send the response text back.
Something like
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException
{
String username = request.getParameter(username);
String responseText = "";
boolean isUserAval;
//add your logic to verify username setting isUserAval to true/false accordingly
response.setContentType("text/html");
PrintWriter out = response.getWriter();
if(isUserAval)
{
responseText = "Username is available";
}
else
{
responseText = "Username is not available";
}
out.println(responseText);
out.close();
}
Use this function below... You'll also notice, request will have a readystate and stuff like that, your looking for prolly statusCode between 200-202, and ready state of 4, and a statusText of OK
var request = $.get(url, function(event){
//If your within your application your url can be the method you need
//I.E. Ruby URL post would be /api/v1/users/find_user_by_ID
//This URL Points to the api/v1 folder than the users controller
//Than finally the method inside the controller (find_user_by_ID)
}
I also believe that whatever your doing, doesn't need to be in javascript, if your using PHP or Ruby, you can simply add php or ruby tags and create if statements, than use javascript to add and remove classes, or toggle hide and show dependent on what happened in each step.

Getting nothing when doing cross domain AJAX request with YQL

I am using the following code to do the cross domain AJAX request with YQL :
function requestCrossDomain( site, callback ) {
function cbFunc(data) {
// If we have something to work with...
alert("inside call back");
if ( data.results[0] ) {
// Strip out all script tags, for security reasons.
// BE VERY CAREFUL. This helps, but we should do more.
data = data.results[0].replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '');
// If the user passed a callback, and it
// is a function, call it, and send through the data var.
if ( typeof callback === 'function') {
callback(data);
}
}
// Else, Maybe we requested a site that doesn't exist, and nothing returned.
else throw new Error('Nothing returned from getJSON.');
}
// If no url was passed, exit.
if ( !site ) {
alert('No site was passed.');
return false;
}
// Take the provided url, and add it to a YQL query. Make sure you encode it!
var yql = 'http://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent('select * from html where url="' + site + '"') + '&format=xml&callback=cbFunc';
// Request that YSQL string, and run a callback function.
// Pass a defined function to prevent cache-busting.
$.getJSON( yql, cbFunc );
console.log("outside call back");
}
and calling the above as follow :
requestCrossDomain('http://www.cnn.com', function(results) {
alert(results);
});
When i am running the above code in firefox, although response (in firebug console) is showing the content of website inside callback function (cbFunc) yet it is showing nothing as alert.Also the result of console.log("inside call back") at line 5 is not printing in firebug console.
can anyone suggest me where things are going wrong or any explanation for above ?
btw i have already gone through :
http://tek-insight.blogspot.in/2010/05/cross-domain-ajax-request-proxy-json.html
http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-cross-domain-ajax-request-with-yql-and-jquery/
Possible explanation in related stackoverflow questions.
$.getJSON accepts as callback function for 'success' response. But if error were returned (404, 500, etc) then it will not call this function.
You need to add extra functions in order to catch other scenarios of responses:
$.getJSON( yql, cbFunc)
.done(function() { console.log( "second success" ); })
.fail(function(jqxhr, textStatus, error) { console.log( "error", textStatus, error ); })
.always(function() { console.log( "complete" ); });

Categories

Resources