<div dir="ltr"><div>Hi Cyril,<br></div><div><br></div><div>For seaside expiration I do not hook on EACH ajax call but with a global handler:</div><div><div><br></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>html document addLoadScript: (html jQuery document</div><div>                                onAjaxError: (self ajaxErrorHandler asFunction: #(&#39;event&#39; &#39;jqxhr&#39; &#39;settings&#39; &#39;exception&#39;))).</div></div><div><br></div><div><br></div><div>Note that this handler will take care of seaside expiration as well as errors in either rendering phase or callback phase from ajax calls. </div><div><br></div><div><br></div><div><div>ajaxErrorHandler</div><div>  &quot; If the ajax callback error was timeout...then we alert the user and forward to login again. If it was an ajax error callback, then we display a modal showing all the available error information. See #renderSupportForAjaxErrorHandlerOn: for more details.</div><div>Also... note that in DpQuuveProductionWalkbackErrorHandler &gt;&gt; open: (our custom Seaside error handler for GemStone), when there is an AJAX error, in the response object we write a JSON serialized dictionary with all the error information (see #respondFromAjaxRequestWith:continuation:). Therefore, what we must do here is to read the response (will be JSON), parse that, and get the useful information. Finally, refresh the </div><div>&#39;ajaxErrorDialog&#39; with the error info we got and finally show the dialog.</div><div>&quot;</div><div><br></div><div>  ^ &#39; if (jqxhr.status == 403) {</div><div>            alert(&quot;For security reasons we sign people out during periods of inactivity. Please sign in again.&quot;);</div><div>            window.location.href = settings.url.split(&quot;?&quot;)[0].replace(&quot;help&quot;,&quot;&quot;);</div><div>        } else {</div><div><br></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>// This is on purpose because sometimes with TinyMCE we would get status 0 and empty error...when there was no error</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>// The reason is explained in: <a href="http://bartwullems.blogspot.com.ar/2012/02/ajax-request-returns-status-0.html">http://bartwullems.blogspot.com.ar/2012/02/ajax-request-returns-status-0.html</a></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>if (jqxhr.readyState == 0 || jqxhr.status == 0) {  </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>    return; //Skip this error  </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span> };</div><div><br></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>// Lets write to console all error info possbile</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>  var requestResponse = {</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>    url: settings.url,</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>    method: settings.type,</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>    data: settings.data,</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>    httpStatus: jqxhr.status,</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>    error: exception || jqxhr.statusText,</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>    data: settings.data</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>  };</div><div><br></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">        </span></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>responseText = jqxhr.responseText;</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>responseText.replace(/[\\&quot;&#39;&#39;]/g, &#39;&#39;\\$&amp;&#39;&#39;).replace(/\u0000/g, &#39;&#39;\\0&#39;&#39;); </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>jsonValue = jQuery.parseJSON(responseText);</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>console.error(jsonValue);</div><div><br></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>$(&#39;&#39;#ajaxErrorDialog&#39;&#39;).find(&#39;&#39;.errorTitle&#39;&#39;).html(&#39;&#39;&lt;span style=&quot;color:#4F2817;&quot;&gt;&#39;&#39;+jsonValue.errorTitle+&#39;&#39;&lt;/span&gt;&#39;&#39;); </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>$(&#39;&#39;#ajaxErrorDialog&#39;&#39;).find(&#39;&#39;.exceptionDescription&#39;&#39;).html(&#39;&#39;&lt;span style=&quot;color:#4F2817;&quot;&gt;&#39;&#39;+jsonValue.exceptionDescription+&#39;&#39;&lt;/span&gt;&#39;&#39;); </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>$(&#39;&#39;#ajaxErrorDialog&#39;&#39;).find(&#39;&#39;.dateAndTime&#39;&#39;).html(&#39;&#39;&lt;span style=&quot;color:#4F2817;&quot;&gt;&#39;&#39;+jsonValue.dateAndTime+&#39;&#39;&lt;/span&gt;&#39;&#39;); </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>$(&#39;&#39;#ajaxErrorDialog&#39;&#39;).find(&#39;&#39;.continuationOop&#39;&#39;).html(&#39;&#39;&lt;span style=&quot;color:#4F2817;&quot;&gt;&#39;&#39;+jsonValue.continuationOop+&#39;&#39;&lt;/span&gt;&#39;&#39;); </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>$(&#39;&#39;#ajaxErrorDialog&#39;&#39;).find(&#39;&#39;.packagesVersions&#39;&#39;).html(&#39;&#39;&lt;span style=&quot;color:#4F2817;&quot;&gt;&#39;&#39;+jsonValue.packagesVersions+&#39;&#39;&lt;/span&gt;&#39;&#39;); </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>$(&#39;&#39;#ajaxErrorDialog&#39;&#39;).find(&#39;&#39;.sitePrefix&#39;&#39;).html(&#39;&#39;&lt;span style=&quot;color:#4F2817;&quot;&gt;&#39;&#39;+jsonValue.sitePrefix+&#39;&#39;&lt;/span&gt;&#39;&#39;); </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>$(&#39;&#39;#ajaxErrorDialog&#39;&#39;).find(&#39;&#39;.user&#39;&#39;).html(&#39;&#39;&lt;span style=&quot;color:#4F2817;&quot;&gt;&#39;&#39;+jsonValue.user+&#39;&#39;&lt;/span&gt;&#39;&#39;); <span class="gmail-Apple-tab-span" style="white-space:pre">                </span></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>$(&#39;&#39;#ajaxErrorDialog&#39;&#39;).find(&#39;&#39;.gemPid&#39;&#39;).html(&#39;&#39;&lt;span style=&quot;color:#4F2817;&quot;&gt;&#39;&#39;+jsonValue.gemPid+&#39;&#39;&lt;/span&gt;&#39;&#39;); <span class="gmail-Apple-tab-span" style="white-space:pre">        </span></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>$(&#39;&#39;#ajaxErrorDialog&#39;&#39;).find(&#39;&#39;.gemSessionID&#39;&#39;).html(&#39;&#39;&lt;span style=&quot;color:#4F2817;&quot;&gt;&#39;&#39;+jsonValue.gemSessionID+&#39;&#39;&lt;/span&gt;&#39;&#39;); </div><div><br></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                </span>$(&#39;&#39;#ajaxErrorDialog&#39;&#39;).modal(&#39;&#39;show&#39;&#39;);</div><div><br></div><div>        }&#39;</div></div><div><br></div><div><br></div><div><br></div><div>And then, I also render my &quot;ajaxErrorDialog&quot; which is the component/dialog rendered when there is an ajax error:</div><div><br></div><div><br></div><div><div>renderSupportForAjaxErrorHandlerOn: html</div><div>  html tbsModal</div><div>    id: &#39;ajaxErrorDialog&#39;;</div><div>    with: [ </div><div>          html</div><div>            tbsModalDialog: [ </div><div>              html</div><div>                tbsModalContent: [ </div><div>                  html</div><div>                    tbsModalHeader: [ </div><div>                      html tbsModalTitle</div><div>                        level: 4;</div><div>                        with: [ </div><div>                              html tbsAlert beDanger</div><div>                                with: [ </div><div>                                  html tbsGlyphIcon iconTime.</div><div>                                  html space.</div><div>                                  html text: &#39;Unexpected Error!&#39;.</div><div>                                  html span</div><div>                                    style: &#39;text-color: white&#39;;</div><div>                                    with: [ html tbsModalCloseIcon ] ] ] ].</div><div>                  html</div><div>                    tbsModalBody: [ </div><div>                      &quot;This is a template div that is filled/replaced with the real text from DpQuuve &gt;&gt; ajaxErrorHandler&quot;</div><div>                      html</div><div>                        text:</div><div>                          &#39;The operation you tried failed because of an unexpected error. You may want to either try again, sign out and sign in and try again, or contact us about the error. However, note that other aspects of the program should continue to work normally.&#39;.</div><div>                      html</div><div>                        break;</div><div>                        break.</div><div>                      html div</div><div>                        with: [ </div><div>                          html text: &#39;Error description: &#39;.</div><div>                          html span class: &#39;exceptionDescription&#39; ].</div><div>                      html break.</div><div>                      html div</div><div>                        with: [ </div><div>                          html text: &#39;Error ID: &#39;.</div><div>                          html span class: &#39;continuationOop&#39; ].</div><div>                      html break.</div><div>                      html div</div><div>                        with: [ </div><div>                          html text: &#39;Generated at: &#39;.</div><div>                          html span class: &#39;dateAndTime&#39; ].</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                                                        </span>html break.</div><div>                      html div</div><div>                        with: [ </div><div>                          html text: &#39;By user: &#39;.</div><div>                          html span class: &#39;user&#39; ].</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                                                        </span> html break.</div><div>                      html div</div><div>                        with: [ </div><div>                          html text: &#39;Site url: &#39;.</div><div>                          html span class: &#39;sitePrefix&#39; ].</div><div>                      html break.</div><div>                      html div</div><div>                        with: [ </div><div>                          html text: &#39;Packages: &#39;.</div><div>                          html span class: &#39;packagesVersions&#39; ].</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                                                        </span>html break.</div><div>                      html div</div><div>                        with: [ </div><div>                          html text: &#39;Gem PID: &#39;.</div><div>                          html span class: &#39;gemPid&#39; ].</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                                                        </span>html break.</div><div>                      html div</div><div>                        with: [ </div><div>                          html text: &#39;Gem Session ID: &#39;.</div><div>                          html span class: &#39;gemSessionID&#39; ].</div><div>                     </div><div>                      ]<span class="gmail-Apple-tab-span" style="white-space:pre">        </span>&quot;html tbsModalFooter: [ </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                                        </span>html tbsButton: &#39;Close&#39;.</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                                        </span>html tbsButton bePrimary; with: &#39;Save changes&#39; <span class="gmail-Apple-tab-span" style="white-space:pre">        </span></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                                </span> ]&quot; ] ] ]</div></div><div><br></div><div><br></div><div>Hope this helps. Let me know if it is clear. If it is not yet, I can do (and I should do!) a blog post explaining better. </div><div><br></div><div>Cheers,</div><div><br></div><div><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Sep 24, 2016 at 8:15 AM, Cyril Ferlicot D. <span dir="ltr">&lt;<a href="mailto:cyril.ferlicot@gmail.com" target="_blank">cyril.ferlicot@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">Le 24/09/2016 à 08:48, Johan Brichau a écrit :<br>
&gt; Hi Mariano,<br>
&gt;<br>
&gt; First button does a single ajax call and responds a js script.<br>
&gt; Second button does two ajax calls, first one without a response content, second one with a html response content.<br>
&gt;<br>
&gt; Both achieve the same end result but the second one requires two request-response cycles to your server.<br>
&gt; The second one will thus achieve the end result slower than the first one.<br>
&gt;<br>
&gt; We typically also try to optimize as much as possible into single ajax requests.<br>
&gt;<br>
&gt; Mind that you _can_ combine a single primary and multiple secondary callback blocks into a single ajax call.<br>
&gt; A primary callback is a callback that responds a content to the client (#script:, #html:, #json:, #text, ….)<br>
&gt; A secondary callback is a callback that does not respond content (#callback:value:, #callback:passengers:, #callback:json: , …)<br>
&gt; There is an exception to this rule, #callback: is implemented in the Seaside jQuery binding as a primary callback, even if it does not return any content.<br>
&gt;<br>
&gt; Although for this example, I would actually write it as follows, because the #callback: block is a primary callback.<br>
&gt;<br>
&gt;               html button<br>
&gt;                       bePush;<br>
&gt;                       onClick: (html jQuery id: ‘myDivId’ load html: [:r | | … do some other stuff …. then ... self renderMyDivOn: r.  ] )<br>
&gt;                       value: ‘Test’<br>
&gt;<br>
<br>
</span>Hi!<br>
<br>
With this example how is manage the case where the session expire?<br>
In general I do:<br>
<span class="gmail-"><br>
onClick: (html jQuery ajax<br>
        callback: [  ];<br>
        onSuccess: (  (html jQuery id: &#39;myDivId&#39;) load html: [ :r | self<br>
</span>renderMyDivOn: r.  ]);<br>
        onError: &#39;location.reload();&#39; &quot;probably session expiration&quot;);<br>
<span class="gmail-im gmail-HOEnZb"><br></span></blockquote><div><br></div><div><br></div><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-im gmail-HOEnZb">
&gt; Now, it also depends of the ‘myDivId’ is known when rendering the button or not, but in this simple example this would yield the same result ;)<br>
&gt;<br>
&gt; cheers<br>
&gt; Johan<br>
&gt;<br>
&gt;<br>
</span><div class="gmail-HOEnZb"><div class="gmail-h5">&gt; ______________________________<wbr>_________________<br>
&gt; seaside mailing list<br>
&gt; <a href="mailto:seaside@lists.squeakfoundation.org">seaside@lists.<wbr>squeakfoundation.org</a><br>
&gt; <a href="http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside" rel="noreferrer" target="_blank">http://lists.squeakfoundation.<wbr>org/cgi-bin/mailman/listinfo/<wbr>seaside</a><br>
&gt;<br>
<br>
<br>
</div></div><span class="gmail-HOEnZb"><font color="#888888">--<br>
Cyril Ferlicot<br>
<br>
<a href="http://www.synectique.eu" rel="noreferrer" target="_blank">http://www.synectique.eu</a><br>
<br>
2 rue Jacques Prévert 01,<br>
59650 Villeneuve d&#39;ascq France<br>
<br>
</font></span><br>______________________________<wbr>_________________<br>
seaside mailing list<br>
<a href="mailto:seaside@lists.squeakfoundation.org">seaside@lists.<wbr>squeakfoundation.org</a><br>
<a href="http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside" rel="noreferrer" target="_blank">http://lists.squeakfoundation.<wbr>org/cgi-bin/mailman/listinfo/<wbr>seaside</a><br>
<br></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature">Mariano<br><a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br></div>
</div></div>