custom error handling results in: "Error: context not in self"

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

custom error handling results in: "Error: context not in self"

Nick
Hi,

I'm using a hidden iframe in my file upload component. If an error occurs during uploading, the error page is rendered in the hidden iframe - which means I end up debugging by inspecting the http responses in the browsers development tools. Not ideal so I thought I'd trap the error and present the page myself. In the exception trap I send a script to the page which redirects the parent window to the error page - 'parent.parent.window.location.replace(..error url..)' This works well apart from when I click on the "debug" link, the debugger in the Pharo reports: "Error: context not in self" and doesn't shows an unrelated (to the original error) stack trace.

I've patched together my error handling code, by examining the error handling filter in Seaside. I've had to add an accessor on WASession>>#continuations, which probably indicates there is an easier way to achieve my goal:

handleException: ex
| session requestContext key continuation renderContinuation |
requestContext := self requestContext.
session := requestContext session.
key := requestContext request fields at: session actionField.
continuation := session continuations at: key.
renderContinuation := continuation createRenderContinuation.
session presenter show: (WAWalkback current exception: ex) onAnswer: [:answer | 
answer ifTrue: [ 
self flag: #todo. "work out why I get the error: 'Error: context not in self'"
GRPlatform current openDebuggerOn: ex ] ].

"redirect the main page to the error location"
self requestContext respond: 
[ :response | 
response
contentType: WAMimeType textHtml;
nextPutAll: (WARenderCanvas builder
fullDocument: true;
scriptGeneratorClass: JQScriptGenerator; "removes the onload from body"
render: [ :html | 
html script: 'parent.parent.window.location.replace("', renderContinuation registerForUrl  greaseString, '")' ] )]

I've a horrible feeling I'm missing an obvious, simpler solution

Thanks,

Nick

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

Re: custom error handling results in: "Error: context not in self"

Julian Fitzell-2
Nick and I sorted this out this evening. I assume he'll write up a summary... ;)

On Tue, Aug 30, 2011 at 10:05 AM, Nick Ager <[hidden email]> wrote:
Hi,

I'm using a hidden iframe in my file upload component. If an error occurs during uploading, the error page is rendered in the hidden iframe - which means I end up debugging by inspecting the http responses in the browsers development tools. Not ideal so I thought I'd trap the error and present the page myself. In the exception trap I send a script to the page which redirects the parent window to the error page - 'parent.parent.window.location.replace(..error url..)' This works well apart from when I click on the "debug" link, the debugger in the Pharo reports: "Error: context not in self" and doesn't shows an unrelated (to the original error) stack trace.

I've patched together my error handling code, by examining the error handling filter in Seaside. I've had to add an accessor on WASession>>#continuations, which probably indicates there is an easier way to achieve my goal:

handleException: ex
| session requestContext key continuation renderContinuation |
requestContext := self requestContext.
session := requestContext session.
key := requestContext request fields at: session actionField.
continuation := session continuations at: key.
renderContinuation := continuation createRenderContinuation.
session presenter show: (WAWalkback current exception: ex) onAnswer: [:answer | 
answer ifTrue: [ 
self flag: #todo. "work out why I get the error: 'Error: context not in self'"
GRPlatform current openDebuggerOn: ex ] ].

"redirect the main page to the error location"
self requestContext respond: 
[ :response | 
response
contentType: WAMimeType textHtml;
nextPutAll: (WARenderCanvas builder
fullDocument: true;
scriptGeneratorClass: JQScriptGenerator; "removes the onload from body"
render: [ :html | 
html script: 'parent.parent.window.location.replace("', renderContinuation registerForUrl  greaseString, '")' ] )]

I've a horrible feeling I'm missing an obvious, simpler solution

Thanks,

Nick

_______________________________________________
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: custom error handling results in: "Error: context not in self"

Nick
Nick and I sorted this out this evening. I assume he'll write up a summary... ;)
 
Indeed. If I understood the problem it's that capturing the exception in a closure isn't sufficient, you need to break-off a continuation containing the process to be debugged, then use that continuation to debug the problem.

The #handleException: code becomes:

handleException: ex
| renderContinuation shouldDebug |
renderContinuation := self createRenderContinuation.
[
shouldDebug := self session presenter call: (WAWalkback current exception: ex) ]
on: WARenderNotification 
do: [ :exDontCare |
"redirect the main page to the error location"
self requestContext respond: 
[ :response | 
response
contentType: WAMimeType textHtml;
nextPutAll: (WARenderCanvas builder
fullDocument: true;
scriptGeneratorClass: JQScriptGenerator; "removes the onload from body"
render: [ :html | 
html script: 'parent.parent.window.location.replace("', renderContinuation registerForUrl greaseString, '")' ] )] ].

shouldDebug ifTrue: [ 
GRPlatform current openDebuggerOn: ex ]

Explanation:

#call: creates a continuation. However we trap the WARenderNotification to allow us to render our own response. #call ,  #answer:(s) true if the user clicks to debug the process. When #call: returns, it restores the state prior to being called and the code continues executing at:

 shouldDebug ifTrue: [ GRPlatform current openDebuggerOn: ex ]

As the state has been restored we can open a debugger on the exception and debug the original problem.

For comparison, our first implementation captured the continuation explicitly,  though we decided the above solution was neater:

the lines:

    shouldDebug := self session presenter call: (WAWalkback current exception: ex) ]
on: WARenderNotification 
do: [ :exDontCare |

where replaced by:

shouldDebug := GRPlatform current seasideSuspendFlowDo: [ :cc |
session presenter show: (WAWalkback current exception: ex) onAnswer: [:answer | cc value: answer ].

with the call to self requestContext respond: [...] inside the #seasideSuspendFlowDo:

I extracted the code to create the render continuation into a method #createRenderContinuation. If I understand correctly in Seaside3.1 there will be methods on WARequestContext to allow you to create continuations, which for example can be used to create a url for a callback from inside an actionContinuation block.

I hope I haven't made the explanation more confusing than the code....

Nick
 
On Tue, Aug 30, 2011 at 10:05 AM, Nick Ager <[hidden email]> wrote:
Hi,

I'm using a hidden iframe in my file upload component. If an error occurs during uploading, the error page is rendered in the hidden iframe - which means I end up debugging by inspecting the http responses in the browsers development tools. Not ideal so I thought I'd trap the error and present the page myself. In the exception trap I send a script to the page which redirects the parent window to the error page - 'parent.parent.window.location.replace(..error url..)' This works well apart from when I click on the "debug" link, the debugger in the Pharo reports: "Error: context not in self" and doesn't shows an unrelated (to the original error) stack trace.

I've patched together my error handling code, by examining the error handling filter in Seaside. I've had to add an accessor on WASession>>#continuations, which probably indicates there is an easier way to achieve my goal:

handleException: ex
| session requestContext key continuation renderContinuation |
requestContext := self requestContext.
session := requestContext session.
key := requestContext request fields at: session actionField.
continuation := session continuations at: key.
renderContinuation := continuation createRenderContinuation.
session presenter show: (WAWalkback current exception: ex) onAnswer: [:answer | 
answer ifTrue: [ 
self flag: #todo. "work out why I get the error: 'Error: context not in self'"
GRPlatform current openDebuggerOn: ex ] ].

"redirect the main page to the error location"
self requestContext respond: 
[ :response | 
response
contentType: WAMimeType textHtml;
nextPutAll: (WARenderCanvas builder
fullDocument: true;
scriptGeneratorClass: JQScriptGenerator; "removes the onload from body"
render: [ :html | 
html script: 'parent.parent.window.location.replace("', renderContinuation registerForUrl  greaseString, '")' ] )]

I've a horrible feeling I'm missing an obvious, simpler solution

Thanks,

Nick

_______________________________________________
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



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

Re: custom error handling results in: "Error: context not in self"

Julian Fitzell-2
On Thu, Sep 1, 2011 at 10:59 AM, Nick Ager <[hidden email]> wrote:
If I understand correctly in Seaside3.1 there will be methods on WARequestContext to allow you to create continuations, which for example can be used to create a url for a callback from inside an actionContinuation block. 

More accurately, you'll be able to get the current continuation from the request context. You can use that you create new continuations.
 
I hope I haven't made the explanation more confusing than the code....

 Seemed clear enough to me, but then I helped write it. :)

Thanks for writing it up.

Julian

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