Ajax and error management

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Ajax and error management

Thelliez
While I successfully created my first JQuery modal dialog, I
encountered two issues regarding exception management:

===1===  At one point I had a bug in my code (I know, this never
happens ;-). The component rendering the dialog did not seem to
respond to user input.  Inspecting with Firebug, I found that the
server (GLASS) was returning a 505.  But the debugger (Seaside
Walkback html page) was not displayed.  Now, I understand that this is
an issue that has to do with Javascript exception handling.  But how
do you do that in Seaside?

In other words, the code below works.  But do you have any code
example on how to manage exception should my 'myComponent' not behave?

html div
      id: (html nextId);
      script: (html jQuery new dialog
          html: myComponent;
          title: 'Title';
        height: 180;
        width: 420;
          resizable: false;
        autoOpen: false;
          modal: true).
                                                                               
html anchor
      url: '#';
        onClick: (( html jQuery id: html lastId) dialog open );
        with: 'Test'


===2=== Likewise, I got a 403 when leaving my first calling page
opened for a while. I mean that attempting to open the above dialog
does not work anymore after a time that I think is the session
expiration.  I guess that the link under 'Test' calls
jquery/javascript, but then the javascript refers to a continuation
that is expired. (BTW, I am using Seaside 3.0 and GLASS).

Again, I would like to be able to intercept such exception/error and
provide something more user friendly.  Right now the dialog opens a
blank dialog.

Suggestions?
Thanks,
Thierry
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Ajax and error management

Johan Brichau-2
Thierry,

Exceptions in Seaside are handled by an instance of (a subclass of) WAExceptionHandler. Setting the exception handler is part of the application configuration.
For development, Seaside provides you with exception handlers (e.g. WAWalkbackErrorHandler) that return an exception page and that can open a debugger on the server-side (or they put a continuation on the objectlog in GLASS).
However, the problem with AJAX calls is that the browser will not render that response as a page refresh. Gracefully dealing with those exceptions requires a bit of javascripting. In addition, if you want to handle exceptions differently on the server-side, you need to implement your own subclass of WAExceptionHandler (or any of its subclasses).

For handling ajax errors differently on the client side (for example, refreshing the page anyway): provide a javascript function as the 'onError' parameter for the ajax call. You can do this for each ajax call separately, or you can define a global handler.
Some examples:
- http://stackoverflow.com/questions/377644/jquery-ajax-error-handling-show-custom-exception-messages
- http://api.jquery.com/ajaxError/

To change the server-side behavior. I think you can find your way by looking at the implementation of the existing handlers.
To give you yet another example, here is the principal code of an error handler we are using in production code. In combination with a global ajax error handler, it makes sure that a decent error message is put on the screen (in a kind of dialog window) whenever an error occurred server-side in an ajax callback.

handleDefault: anException
        [self logErrorToDisk: anException]
                ensure: [self requestContext respond: [ :response |
                                                                response
                                                                        internalError;
                                                                        contentType: WAMimeType textHtml;
                                                                        nextPutAll: (self rendererClass builder
                                                                                fullDocument: true;
                                                                                rootBlock: [ :root | root title: anException description ];
                                                                                render: [:html | html render:(NPProductionErrorDialog exception: anException)])]]


Hope this gets you on your way!
Johan

On 13 May 2011, at 22:50, Thierry Thelliez wrote:

> While I successfully created my first JQuery modal dialog, I
> encountered two issues regarding exception management:
>
> ===1===  At one point I had a bug in my code (I know, this never
> happens ;-). The component rendering the dialog did not seem to
> respond to user input.  Inspecting with Firebug, I found that the
> server (GLASS) was returning a 505.  But the debugger (Seaside
> Walkback html page) was not displayed.  Now, I understand that this is
> an issue that has to do with Javascript exception handling.  But how
> do you do that in Seaside?
>
> In other words, the code below works.  But do you have any code
> example on how to manage exception should my 'myComponent' not behave?
>
> html div
>      id: (html nextId);
>      script: (html jQuery new dialog
>         html: myComponent;
>         title: 'Title';
> height: 180;
> width: 420;
>         resizable: false;
> autoOpen: false;
>         modal: true).
>
> html anchor
>       url: '#';
> onClick: (( html jQuery id: html lastId) dialog open );
> with: 'Test'
>
>
> ===2=== Likewise, I got a 403 when leaving my first calling page
> opened for a while. I mean that attempting to open the above dialog
> does not work anymore after a time that I think is the session
> expiration.  I guess that the link under 'Test' calls
> jquery/javascript, but then the javascript refers to a continuation
> that is expired. (BTW, I am using Seaside 3.0 and GLASS).
>
> Again, I would like to be able to intercept such exception/error and
> provide something more user friendly.  Right now the dialog opens a
> blank dialog.
>
> Suggestions?
> Thanks,
> Thierry
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Ajax and error management

Thelliez
Thanks Johan for your answers.

I think that what I am looking for is a way to call from Seaside the
Ajax error callback function.

The definition of a load call in JQuery is as follows:

.load( url, [ data ], [ complete(responseText, textStatus, XMLHttpRequest) ] )
          url  A string containing the URL to which the request is sent.
          data  A map or string that is sent to the server with the request.
          complete(responseText, textStatus, XMLHttpRequest)  A
callback function that is executed when the request completes.


The following code in Seaside

html div
      id: (html nextId);
      script: (html jQuery new dialog
                html: myComponent;
                title: 'Title';
                height: 180;
                width: 420;
                resizable: false;
                autoOpen: false;
                modal: true).

 html anchor
        url: '#';
        onClick: (( html jQuery id: html lastId) dialog open );
        with: 'Test'


creates the following Jquery code:

<script type="text/javascript">/*<![CDATA[*/function
onLoad(){$("#id1").dialog({"autoOpen":false,"open":function(){$("#id1").load("http://here/app",["_s=InQqr610owmLtmMN","_k=ZRkC14tzdCC76Rkw","2"].join("&"))},"title":"Title","height":180,"width":420,"resizable":false,"modal":true});/*]]>*/</script>


What I would like is something managing the load function errors, as
described in http://fishdujour.typepad.com/blog/2009/05/handling-errors-using-jqueryload.html

The example method at JQAllFunctionalTests >> renderTimeoutOn:
provides a global error trapping, but not an error mechanism for a
particular Ajax call (as far as I understand it).


I would like to code something like:

html div
      id: (html nextId);
      script: (html jQuery new dialog
                html: myComponent;
                title: 'Title';
                height: 180;
                width: 420;
                resizable: false;
                autoOpen: false;
                modal: true
                complete: ( html javascript
                        'function(response, status, xhr) {
                                                       if (status ==
"error") { alert('oh oh'); }).


That would translate in something like:

<script type="text/javascript">/*<![CDATA[*/function
onLoad(){$("#id1").dialog({"autoOpen":false,"open":function(){$("#id1").load("http://here/app",["_s=InQqr610owmLtmMN","_k=ZRkC14tzdCC76Rkw","2"].join("&"),function(response,
status, xhr) { if (status == "error") { alert('oh oh');
})},"title":"Title","height":180,"width":420,"resizable":false,"modal":true});/*]]>*/</script>


Thierry
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: [GS/SS Beta] [Seaside] Ajax and error management

Johan Brichau-2
Thierry,

An investigation of the JQDialog>>html: learns me that it's a convenience method for the onOpen callback.
As such, if you want to pass on an onError function to the #load function, your example should be implemented along the following lines:

html div
    id: (html nextId);
    script: (html jQuery new dialog
              autoOpen: false;
                onOpen: (html jQuery ajax load html: myComponent; onError: (html javascript ....));
              title: 'Title';
              height: 180;
              width: 420;
              resizable: false;
              autoOpen: false;
              modal: true).


On 15 May 2011, at 06:59, Thierry Thelliez wrote:

> Thanks Johan for your answers.
>
> I think that what I am looking for is a way to call from Seaside the
> Ajax error callback function.
>
> The definition of a load call in JQuery is as follows:
>
> .load( url, [ data ], [ complete(responseText, textStatus, XMLHttpRequest) ] )
>         url  A string containing the URL to which the request is sent.
>         data  A map or string that is sent to the server with the request.
>         complete(responseText, textStatus, XMLHttpRequest)  A
> callback function that is executed when the request completes.
>
>
> The following code in Seaside
>
> html div
>     id: (html nextId);
>     script: (html jQuery new dialog
>               html: myComponent;
>               title: 'Title';
>               height: 180;
>               width: 420;
>               resizable: false;
>               autoOpen: false;
>               modal: true).
>
> html anchor
>       url: '#';
>       onClick: (( html jQuery id: html lastId) dialog open );
>       with: 'Test'
>
>
> creates the following Jquery code:
>
> <script type="text/javascript">/*<![CDATA[*/function
> onLoad(){$("#id1").dialog({"autoOpen":false,"open":function(){$("#id1").load("http://here/app",["_s=InQqr610owmLtmMN","_k=ZRkC14tzdCC76Rkw","2"].join("&"))},"title":"Title","height":180,"width":420,"resizable":false,"modal":true});/*]]>*/</script>
>
>
> What I would like is something managing the load function errors, as
> described in http://fishdujour.typepad.com/blog/2009/05/handling-errors-using-jqueryload.html
>
> The example method at JQAllFunctionalTests >> renderTimeoutOn:
> provides a global error trapping, but not an error mechanism for a
> particular Ajax call (as far as I understand it).
>
>
> I would like to code something like:
>
> html div
>     id: (html nextId);
>     script: (html jQuery new dialog
>               html: myComponent;
>               title: 'Title';
>               height: 180;
>               width: 420;
>               resizable: false;
>               autoOpen: false;
>               modal: true
>               complete: ( html javascript
> 'function(response, status, xhr) {
>                                                      if (status ==
> "error") { alert('oh oh'); }).
>
>
> That would translate in something like:
>
> <script type="text/javascript">/*<![CDATA[*/function
> onLoad(){$("#id1").dialog({"autoOpen":false,"open":function(){$("#id1").load("http://here/app",["_s=InQqr610owmLtmMN","_k=ZRkC14tzdCC76Rkw","2"].join("&"),function(response,
> status, xhr) { if (status == "error") { alert('oh oh');
> })},"title":"Title","height":180,"width":420,"resizable":false,"modal":true});/*]]>*/</script>
>
>
> Thierry

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Ajax and error management

Philippe Marschall
In reply to this post by Johan Brichau-2
2011/5/14 Johan Brichau <[hidden email]>:

> Thierry,
>
> Exceptions in Seaside are handled by an instance of (a subclass of) WAExceptionHandler. Setting the exception handler is part of the application configuration.
> For development, Seaside provides you with exception handlers (e.g. WAWalkbackErrorHandler) that return an exception page and that can open a debugger on the server-side (or they put a continuation on the objectlog in GLASS).
> However, the problem with AJAX calls is that the browser will not render that response as a page refresh. Gracefully dealing with those exceptions requires a bit of javascripting. In addition, if you want to handle exceptions differently on the server-side, you need to implement your own subclass of WAExceptionHandler (or any of its subclasses).
>
> For handling ajax errors differently on the client side (for example, refreshing the page anyway): provide a javascript function as the 'onError' parameter for the ajax call. You can do this for each ajax call separately, or you can define a global handler.
> Some examples:
> - http://stackoverflow.com/questions/377644/jquery-ajax-error-handling-show-custom-exception-messages
> - http://api.jquery.com/ajaxError/
>
> To change the server-side behavior. I think you can find your way by looking at the implementation of the existing handlers.
> To give you yet another example, here is the principal code of an error handler we are using in production code. In combination with a global ajax error handler, it makes sure that a decent error message is put on the screen (in a kind of dialog window) whenever an error occurred server-side in an ajax callback.
>
> handleDefault: anException
>        [self logErrorToDisk: anException]
>                ensure: [self requestContext respond: [ :response |
>                                                                response
>                                                                        internalError;
>                                                                        contentType: WAMimeType textHtml;
>                                                                        nextPutAll: (self rendererClass builder
>                                                                                fullDocument: true;
>                                                                                rootBlock: [ :root | root title: anException description ];
>                                                                                render: [:html | html render:(NPProductionErrorDialog exception: anException)])]]
>
>
> Hope this gets you on your way!

Nice summary. Note that there is WARequest >> #isXmlHttpRequest that
allows you to write special error handling code for AJAX. If you want
to handle the error on the client side you need to set the HTTP status
code (WARespnse >> #status:) to some server error (5xx). Note that
there are at least two ways to display an error page with JavaScript
error handling code. Either by redirecting to it with window.location
or by just simply changing the DOM.

Cheers
Philippe
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Ajax and error management

Thelliez
ok thanks. Almost there...

Now I am trying to figure out how to pass arguments to a Javascript function.

onError: is supposed to pass three parameters.  But the alert test
below generates double quotes around 'Arg1 =' + arg1. Is there a
different way to generate a JS function from Seaside?


html div
     id: (html nextId);
      script: (html jQuery new dialog
               onOpen: (html jQuery ajax html: myComponent;
                                              onComplete:   ( JSFunction new
                                                            arguments: (Array with:
'arg1' with: arg2 with: 'arg3');
                                                           add: (JSStream new
                                                    nextPutAll: 'alert';
                                                    argument: '''Arg1 = '' + arg1';
                                                   yourself);
                                                        yourself));




Thanks,
Thierry
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

RE: Ajax and error management

Boris Popov, DeepCove Labs (SNN)
WARenderCanvas builder render:
                [:html |
                (html anchor)
                        onClick: (html javascript alert: 1);
                        with: 'click me']

'<a onclick="alert(1)" href="javascript:void(0)">click me</a>'

WARenderCanvas builder render:
                [:html |
                (html anchor)
                        onClick: (html javascript alias: 'console';
call: 'log' withArguments: #(1 2 3));
                        with: 'click me']

'<a onclick="console.log(1,2,3)" href="javascript:void(0)">click me</a>'

-Boris

-----Original Message-----
From: [hidden email]
[mailto:[hidden email]] On Behalf Of Thierry
Thelliez
Sent: 16 May 2011 16:19
To: Seaside - general discussion
Subject: Re: [Seaside] Ajax and error management

ok thanks. Almost there...

Now I am trying to figure out how to pass arguments to a Javascript
function.

onError: is supposed to pass three parameters.  But the alert test below
generates double quotes around 'Arg1 =' + arg1. Is there a different way
to generate a JS function from Seaside?


html div
     id: (html nextId);
      script: (html jQuery new dialog
               onOpen: (html jQuery ajax html: myComponent;
                                              onComplete:   ( JSFunction
new
                                                            arguments:
(Array with:
'arg1' with: arg2 with: 'arg3');
                                                           add:
(JSStream new
                                                    nextPutAll: 'alert';
                                                    argument: '''Arg1 =
'' + arg1';
                                                   yourself);
                                                        yourself));




Thanks,
Thierry
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Ajax and error management

Thelliez
Boris,

For the methods of JQAjaxSetup " onComplete:, onError:, onSuccess:,
onXhr:   I am trying to access the arguments that are supposed to be
passed.

For now, the following code:

         onComplete:   ( JSFunction new arguments: (Array with:
'arg1' with: arg2 with: 'arg3');
                                     add: (JSStream new
                                                    nextPutAll: 'alert';
                                                    argument: '''Arg1
= '' + arg1';
                                                   yourself);

generates:

        "complete":function(arg1){alert("'Arg1 = ' + arg1")}

The double quotes are not wanted.  Looking at the code, the
javascript: and javascriptContentOn: are intercepting the strings and
automatically adding the quotes.

The goal is to implement something like what can be seen at:
http://fishdujour.typepad.com/blog/2009/05/handling-errors-using-jqueryload.html

>From the article:

     $('#results').load('test/' + $(this).attr('href') + ' #wrap', "",
function(responseText, textStatus, XMLHttpRequest) {
        switch (XMLHttpRequest.status) {
         case 200: break;
         case 404:
          $('#results').html('<p>Looks like the results have not been
uploaded to the server yet. Please check back later.</p>');
          break;
         default:
          $('#results').html('<p>' + XMLHttpRequest.status + ': ' +
XMLHttpRequest.statusText + '. Please contact the club and let them
know.</p>');
         break;
   }


So going back to Seaside, I do not know what to do after this line:

      onError:   ( JSFunction new arguments: (Array with:
'responseText' with: 'textStatus' with: 'XMLHttpRequest');
                                     +++ Code here to generate the
following function  +++


function(XMLHttpRequest, textStatus, exception) {

   switch (XMLHttpRequest.status) {
    case 200: break;
    case 404:
     $('#results').html('<p>Looks like the results have not been
uploaded to the server yet. Please check back later.</p>');
     break;
    default:
     $('#results').html('<p>' + XMLHttpRequest.status + ': ' +
XMLHttpRequest.statusText + '. Please contact the club and let them
know.</p>');
     break;


Or is there another way to do that?

Thanks,
Thierry
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

RE: Ajax and error management

Boris Popov, DeepCove Labs (SNN)
Thierry,

Complex functions like these are best implemented in JavaScript on your
file library, you can then generate a much simpler call using Seaside's
abstraction to that function.

Regards,

-Boris

-----Original Message-----
From: [hidden email]
[mailto:[hidden email]] On Behalf Of Thierry
Thelliez
Sent: 16 May 2011 18:25
To: Seaside - general discussion
Subject: Re: [Seaside] Ajax and error management

Boris,

For the methods of JQAjaxSetup " onComplete:, onError:, onSuccess:,
onXhr:   I am trying to access the arguments that are supposed to be
passed.

For now, the following code:

         onComplete:   ( JSFunction new arguments: (Array with:
'arg1' with: arg2 with: 'arg3');
                                     add: (JSStream new
                                                    nextPutAll: 'alert';
                                                    argument: '''Arg1 =
'' + arg1';
                                                   yourself);

generates:

        "complete":function(arg1){alert("'Arg1 = ' + arg1")}

The double quotes are not wanted.  Looking at the code, the
javascript: and javascriptContentOn: are intercepting the strings and
automatically adding the quotes.

The goal is to implement something like what can be seen at:
http://fishdujour.typepad.com/blog/2009/05/handling-errors-using-jqueryl
oad.html

>From the article:

     $('#results').load('test/' + $(this).attr('href') + ' #wrap', "",
function(responseText, textStatus, XMLHttpRequest) {
        switch (XMLHttpRequest.status) {
         case 200: break;
         case 404:
          $('#results').html('<p>Looks like the results have not been
uploaded to the server yet. Please check back later.</p>');
          break;
         default:
          $('#results').html('<p>' + XMLHttpRequest.status + ': ' +
XMLHttpRequest.statusText + '. Please contact the club and let them
know.</p>');
         break;
   }


So going back to Seaside, I do not know what to do after this line:

      onError:   ( JSFunction new arguments: (Array with:
'responseText' with: 'textStatus' with: 'XMLHttpRequest');
                                     +++ Code here to generate the
following function  +++


function(XMLHttpRequest, textStatus, exception) {

   switch (XMLHttpRequest.status) {
    case 200: break;
    case 404:
     $('#results').html('<p>Looks like the results have not been
uploaded to the server yet. Please check back later.</p>');
     break;
    default:
     $('#results').html('<p>' + XMLHttpRequest.status + ': ' +
XMLHttpRequest.statusText + '. Please contact the club and let them
know.</p>');
     break;


Or is there another way to do that?

Thanks,
Thierry
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Ajax and error management

Thelliez
I finally found a simple way to do it :-)  The issue was not really
about the complexity of the JS function, but I could not find how to
hook to the onError call.

Here a solution:


onError:  ( 'alert(xhr.status); alert(thrownError);' asFunction: (
Array with: 'xhr' with: 'ajaxOptions' with: 'thrownError' ) ) );



Thierry
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside