Discussion:
setPageRefreshOnBacktrackEnabled problem?
Ondřej Čada
2012-04-26 13:17:19 UTC
Permalink
Hello there,

either setPageRefreshOnBacktrackEnabled does not work, or I am missing something fundamental.

In my "class Application extends ERXApplication" I do "setPageRefreshOnBacktrackEnabled(true)". All the HTTP headers are generated all right, far as I can say:

===
12 ~P/WebObjects> curl -D - <my app URL>
HTTP/1.1 200 Apple
Date: Thu, 26 Apr 2012 13:05:20 GMT
Server: Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r
cache-control: private
cache-control: no-cache
cache-control: no-store
cache-control: must-revalidate
cache-control: max-age=0
expires: Sun, 22-Apr-2012 20:37:15 GMT
pragma: no-cache
set-cookie: wosid=YCGjnZm0l4GhkbB33k27C0; version="1"; path=/cgi-bin/WebObjects/CEBOIS.woa
set-cookie: woinst=1; version="1"; path=/cgi-bin/WebObjects/CEBOIS.woa
connection: close
content-length: 5452
MS-Author-Via: DAV
Content-Type: text/html; charset=UTF-8

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
...
===

In my session there is "SomeClass foo".

In one of my pages, there is (essentially) this:

===
<wo:if condition=$session.foo> OK <wo:str value=$session.foo.title/> </wo>
<wo:else>
<wo:hyperlink action=$selectFoo1>Foo1</wo>
<wo:hyperlink action=$selectFoo2>Foo2</wo>
</wo>
===

with the actions trivial "WOComponent selectFoo1() { session().foo=foo1; return null; }" and similar with Foo2. (There is also a "select Foo" action in the OK part which does session().foo=null, but that's not important here, it works perfectly.)

It works perfectly -- till I use backtrack. With backtrack, it goes all wrong :(

1. page is opened, shows "Foo1 Foo2"
2. "Foo1" is clicked, shows correctly the "OK Foo1.title" contents
3. back button is used --> oops, shows again "Foo1 Foo2"!

Here I probably am missing something -- given I have set pageRefreshOnBacktrackEnabled=true, it should show still OK, since my session still contains non-null foo, should it not?

Anyway, seems no part of my application gets activated at this moment; not even appendToResponse logs anything.

4. "Foo2" is clicked --> oops, shows again "OK Foo1.title"

whilst none of the selectFoo1/selectFoo2 actions is ever called. appendToResponse is called, though.

What am I missing, and, more important, how to fix the problem? I don't care whether
(a) back keeps showing the "OK Foo1.title" contents (
(b) back goes to "Foo1 Foo2" AND selection works all right.

I've googled out a trick based on contextID comparation, but that one fails with automatic refresh (which it considers to be same as "back") :(

Thanks and all the best,
---
Ondra Čada
OCSoftware: ***@ocs.cz http://www.ocs.cz
private ***@ocs.cz http://www.ocs.cz/oc
Chuck Hill
2012-04-26 19:18:31 UTC
Permalink
Hi Ondra!
Post by Ondřej Čada
Hello there,
either setPageRefreshOnBacktrackEnabled does not work, or I am missing something fundamental.
It works. :-P
Post by Ondřej Čada
===
12 ~P/WebObjects> curl -D - <my app URL>
HTTP/1.1 200 Apple
Date: Thu, 26 Apr 2012 13:05:20 GMT
Server: Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r
cache-control: private
cache-control: no-cache
cache-control: no-store
cache-control: must-revalidate
cache-control: max-age=0
expires: Sun, 22-Apr-2012 20:37:15 GMT
pragma: no-cache
set-cookie: wosid=YCGjnZm0l4GhkbB33k27C0; version="1"; path=/cgi-bin/WebObjects/CEBOIS.woa
set-cookie: woinst=1; version="1"; path=/cgi-bin/WebObjects/CEBOIS.woa
connection: close
content-length: 5452
MS-Author-Via: DAV
Content-Type: text/html; charset=UTF-8
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
...
===
In my session there is "SomeClass foo".
===
<wo:if condition=$session.foo> OK <wo:str value=$session.foo.title/> </wo>
<wo:else>
<wo:hyperlink action=$selectFoo1>Foo1</wo>
<wo:hyperlink action=$selectFoo2>Foo2</wo>
</wo>
===
with the actions trivial "WOComponent selectFoo1() { session().foo=foo1; return null; }" and similar with Foo2. (There is also a "select Foo" action in the OK part which does session().foo=null, but that's not important here, it works perfectly.)
It works perfectly -- till I use backtrack. With backtrack, it goes all wrong :(
1. page is opened, shows "Foo1 Foo2"
2. "Foo1" is clicked, shows correctly the "OK Foo1.title" contents
3. back button is used --> oops, shows again "Foo1 Foo2"!
Here I probably am missing something -- given I have set pageRefreshOnBacktrackEnabled=true, it should show still OK, since my session still contains non-null foo, should it not?
Probably. Is this the first access to your application? If so, it could be making a new page instance each time.
Post by Ondřej Čada
Anyway, seems no part of my application gets activated at this moment; not even appendToResponse logs anything.
Is anything getting to application.dispatchRequest()?
Post by Ondřej Čada
4. "Foo2" is clicked --> oops, shows again "OK Foo1.title"
whilst none of the selectFoo1/selectFoo2 actions is ever called. appendToResponse is called, though.
That is consistent with setPageRefreshOnBacktrackEnabled(true).
Post by Ondřej Čada
What am I missing, and, more important, how to fix the problem? I don't care whether
(a) back keeps showing the "OK Foo1.title" contents (
(b) back goes to "Foo1 Foo2" AND selection works all right.
I've googled out a trick based on contextID comparation, but that one fails with automatic refresh (which it considers to be same as "back") :(
Check what is happening to the contextID when this is going on.


Chuck
--
Chuck Hill Senior Consultant / VP Development

Practical WebObjects - for developers who want to increase their overall knowledge of WebObjects or who are trying to solve specific problems.
http://www.global-village.net/gvc/practical_webobjects
Ondřej Čada
2012-04-27 01:57:36 UTC
Permalink
Chuck,
Post by Chuck Hill
Post by Ondřej Čada
either setPageRefreshOnBacktrackEnabled does not work, or I am missing something fundamental.
It works. :-P
Well, so I am missing something of importance. Not a big surprise :)
Post by Chuck Hill
Post by Ondřej Čada
In my session there is "SomeClass foo".
===
<wo:if condition=$session.foo> OK <wo:str value=$session.foo.title/> </wo>
<wo:else>
<wo:hyperlink action=$selectFoo1>Foo1</wo>
<wo:hyperlink action=$selectFoo2>Foo2</wo>
</wo>
===
with the actions trivial "WOComponent selectFoo1() { session().foo=foo1; return null; }" and similar with Foo2. (There is also a "select Foo" action in the OK part which does session().foo=null, but that's not important here, it works perfectly.)
It works perfectly -- till I use backtrack. With backtrack, it goes all wrong :(
1. page is opened, shows "Foo1 Foo2"
2. "Foo1" is clicked, shows correctly the "OK Foo1.title" contents
3. back button is used --> oops, shows again "Foo1 Foo2"!
Here I probably am missing something -- given I have set pageRefreshOnBacktrackEnabled=true, it should show still OK, since my session still contains non-null foo, should it not?
Probably. Is this the first access to your application? If so, it could be making a new page instance each time.
Works consistently -- anytime I try the sequence, first or tenth time, the above's what happens.
Post by Chuck Hill
Post by Ondřej Čada
Anyway, seems no part of my application gets activated at this moment; not even appendToResponse logs anything.
Is anything getting to application.dispatchRequest()?
Nope, it is not. Nothing happens at 'back' at all, far as I can say. See also below.
Post by Chuck Hill
Post by Ondřej Čada
4. "Foo2" is clicked --> oops, shows again "OK Foo1.title"
whilst none of the selectFoo1/selectFoo2 actions is ever called. appendToResponse is called, though.
That is consistent with setPageRefreshOnBacktrackEnabled(true).
Post by Ondřej Čada
What am I missing, and, more important, how to fix the problem? I don't care whether
(a) back keeps showing the "OK Foo1.title" contents (
(b) back goes to "Foo1 Foo2" AND selection works all right.
I've googled out a trick based on contextID comparation, but that one fails with automatic refresh (which it considers to be same as "back") :(
Check what is happening to the contextID when this is going on.
I've added logs above and below super.dispatchRequest. Also, I am logging from app and session appendToResponse, and from component's preAppendToResponse and postAppendToResponse. The logs look like this:

public WOResponse dispatchRequest(WORequest rr) { // in Application
println "-- WILL dispatch ${rr.context.contextID}"
WOResponse re=super.dispatchRequest(rr)
println "-- DID dispatch ${rr.context.contextID}"
re
}
public void appendToResponse(WOResponse response, WOContext context) { // in both Application and Session
def cid=context.request.requestHandlerPathArray.lastObject // this is what...
def n=cid.indexOf('.') // ... I have found ...
if (n>=0) cid=cid.substring(0,n) // ... at the Web as a solution of the problem
println "//// app-pre ${context.contextID}: $cid" // session prefixes 'sess'
super.appendToResponse(response,context)
println "//// app-post ${context.contextID}: $cid"
}
protected void preAppendToResponse(WOResponse response, WOContext context) { // in Component
def cid=context.request.requestHandlerPathArray.lastObject
def n=cid.indexOf('.')
if (n>=0) cid=cid.substring(0,n)
println "//// comp-pre ${context.contextID}: $cid LAST $_lastKnownCID known ${_knownCIDs.containsObject(cid)}, CM ${sess.foo.title}"
}
protected void postAppendToResponse(WOResponse response, WOContext context) {
_knownCIDs.addObject(_lastKnownCID=context.contextID)
println "//// comp-post ${context.contextID}: $_lastKnownCID, CM ${sess.footitle}"
}


=== first access of the page ... ===
-- WILL dispatch null
//// app-pre 0: null
//// sess-pre 0: null
//// comp-pre 0: null LAST null known false, CM null
//// comp-post 0: 0, CM null
//// sess-post 1: null
//// app-post 1: null
-- DID dispatch null
-- WILL dispatch null
-- DID dispatch null
=== ... shows foo selection | foo1 selection clicked ... ===
-- WILL dispatch null
//// app-pre 2: 0
//// sess-pre 2: 0
//// comp-pre 2: 0 LAST 0 known true, CM aaa // <= 'aaa' is the first foo.title
//// comp-post 2: 2, CM aaa
//// sess-post 2: 0
//// app-post 2: 0
-- DID dispatch null
-- WILL dispatch null
-- DID dispatch null
=== ... shows correct OK:Foo1 | 'back' browser button tapped (nothing in log at all) ... ===
=== ... shows foo selection | foo2 selection clicked ... ===
-- WILL dispatch null
//// app-pre 3: 0
//// sess-pre 3: 0
//// comp-pre 3: 0 LAST 2 known true, CM aaa
//// comp-post 3: 3, CM aaa
//// sess-post 3: 0
//// app-post 3: 0
-- DID dispatch null
-- WILL dispatch null
-- DID dispatch null
=== ... shows still OK:Foo1 ===

Thanks and all the best,
---
Ondra Čada
OCSoftware: ***@ocs.cz http://www.ocs.cz
private ***@ocs.cz http://www.ocs.cz/oc
Ondřej Čada
2012-04-27 02:07:52 UTC
Permalink
A propos ...
Post by Ondřej Čada
=== ... shows correct OK:Foo1 | 'back' browser button tapped (nothing in log at all) ... ===
=== ... shows foo selection | foo2 selection clicked ... ===
-- WILL dispatch null
//// app-pre 3: 0
//// sess-pre 3: 0
//// comp-pre 3: 0 LAST 2 known true, CM aaa
//// comp-post 3: 3, CM aaa
//// sess-post 3: 0
//// app-post 3: 0
-- DID dispatch null
-- WILL dispatch null
-- DID dispatch null
=== ... shows still OK:Foo1 ===
... here's what happens if, instead of the 'back' button, I use the 'select foo' link (whose action just nulls session.foo):

=== ... correct OK:Foo1 shown | 'select foo' link clicked ... ===
-- WILL dispatch null
//// app-pre 5: 4
//// sess-pre 5: 4
//// comp-pre 5: 4 LAST null known false, CM null
//// comp-post 5: 5, CM null
//// sess-post 5: 4
//// app-post 5: 4
-- DID dispatch null
-- WILL dispatch null
-- DID dispatch null
=== ... shows foo selection | foo2 selection clicked ... ===
-- WILL dispatch null
//// app-pre 6: 5
//// sess-pre 6: 5
//// comp-pre 6: 5 LAST 5 known true, CM bbb // proper foo2.title
//// comp-post 6: 6, CM bbb
//// sess-post 6: 5
//// app-post 6: 5
-- DID dispatch null
-- WILL dispatch null
-- DID dispatch null

If in this state I again use the back button, nothing in log and foo selection shown again. If I select "foo1" (whose title is 'aaa'), I see again the wrong previous one:

-- WILL dispatch null
//// app-pre 7: 5
//// sess-pre 7: 5
//// comp-pre 7: 5 LAST 6 known true, CM bbb
//// comp-post 7: 7, CM bbb
//// sess-post 7: 5
//// app-post 7: 5
-- DID dispatch null
-- WILL dispatch null
-- DID dispatch null

can be repeated consistently any number of times.

Thanks and all the best,
---
Ondra Čada
OCSoftware: ***@ocs.cz http://www.ocs.cz
private ***@ocs.cz http://www.ocs.cz/oc
Chuck Hill
2012-04-27 02:23:17 UTC
Permalink
Which browser are you using? It seems like maybe the browser is caching instead of respecting the headers. It is probably worth using a proxy for your browser (Charles is one) and see if it is actually sending a request. If not, then it is buggy or something is wrong with those headers. If it IS sending a request, then there is a problem in WO or perhaps your web server. Hmmm, that reminds me of something. Are you using mod_expires in Apache? It can mess with the headers. I use this as a configuration:

<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault A60
ExpiresByType application/javascript A3600
ExpiresByType text/css A3600
ExpiresByType text/html A1

The last one prevents browser caching for longer than a second.


Chuck
Post by Ondřej Čada
A propos ...
Post by Ondřej Čada
=== ... shows correct OK:Foo1 | 'back' browser button tapped (nothing in log at all) ... ===
=== ... shows foo selection | foo2 selection clicked ... ===
-- WILL dispatch null
//// app-pre 3: 0
//// sess-pre 3: 0
//// comp-pre 3: 0 LAST 2 known true, CM aaa
//// comp-post 3: 3, CM aaa
//// sess-post 3: 0
//// app-post 3: 0
-- DID dispatch null
-- WILL dispatch null
-- DID dispatch null
=== ... shows still OK:Foo1 ===
=== ... correct OK:Foo1 shown | 'select foo' link clicked ... ===
-- WILL dispatch null
//// app-pre 5: 4
//// sess-pre 5: 4
//// comp-pre 5: 4 LAST null known false, CM null
//// comp-post 5: 5, CM null
//// sess-post 5: 4
//// app-post 5: 4
-- DID dispatch null
-- WILL dispatch null
-- DID dispatch null
=== ... shows foo selection | foo2 selection clicked ... ===
-- WILL dispatch null
//// app-pre 6: 5
//// sess-pre 6: 5
//// comp-pre 6: 5 LAST 5 known true, CM bbb // proper foo2.title
//// comp-post 6: 6, CM bbb
//// sess-post 6: 5
//// app-post 6: 5
-- DID dispatch null
-- WILL dispatch null
-- DID dispatch null
-- WILL dispatch null
//// app-pre 7: 5
//// sess-pre 7: 5
//// comp-pre 7: 5 LAST 6 known true, CM bbb
//// comp-post 7: 7, CM bbb
//// sess-post 7: 5
//// app-post 7: 5
-- DID dispatch null
-- WILL dispatch null
-- DID dispatch null
can be repeated consistently any number of times.
Thanks and all the best,
---
Ondra Čada
--
Chuck Hill Senior Consultant / VP Development

Practical WebObjects - for developers who want to increase their overall knowledge of WebObjects or who are trying to solve specific problems.
http://www.global-village.net/gvc/practical_webobjects
Ondřej Čada
2012-04-27 02:41:33 UTC
Permalink
Chuck,
Post by Chuck Hill
Which browser are you using?
Safari / Mac OS X. The client reported problems from iPad.
Post by Chuck Hill
It seems like maybe the browser is caching instead of respecting the headers.
Hmmmm..... seems it is so! I've just downloaded FF, and the behaviour there is indeed considerably different from Safari, and seems from it, it works (more or less) all right. Namely, backtrack does trigger dispatch/appendToResponse there all right

(Somewhat inconsistently with what you suggested /or at least with what I understood/, the action then _gets_ called all right, too. That's not important though.)

Which is bad, since my client rather needs that the app does work with iPad/Safari, too. Darn...
Post by Chuck Hill
It is probably worth using a proxy for your browser (Charles is one) and see if it is actually sending a request. If not, then it is buggy or something is wrong with those headers. If it IS sending a request, then there is a problem in WO or perhaps your web server. Hmmm, that reminds me of something. Are you using mod_expires in Apache? It can mess with the headers.
The headers look like this:

====
HTTP/1.1 200 Apple WebObjects
cache-control: private
cache-control: no-cache
cache-control: no-store
cache-control: must-revalidate
cache-control: max-age=0
expires: Fri, 27-Apr-2012 02:32:48 GMT
content-type: text/html; charset=UTF-8
pragma: no-cache
x-webobjects-loadaverage: 4
date: Fri, 27-Apr-2012 02:32:48 GMT
set-cookie: wosid=sQtMjsY7xerCBetSFGubaM; version="1"; path=/cgi-bin/WebObjects/CEBOIS.woa
set-cookie: woinst=-1; version="1"; path=/cgi-bin/WebObjects/CEBOIS.woa
content-length: 4140
====

Thanks and all the best,
---
Ondra Čada
OCSoftware: ***@ocs.cz http://www.ocs.cz
private ***@ocs.cz http://www.ocs.cz/oc
Chuck Hill
2012-04-27 03:44:27 UTC
Permalink
Post by Ondřej Čada
Chuck,
Post by Chuck Hill
Which browser are you using?
Safari / Mac OS X. The client reported problems from iPad.
Ah, yes. My aging memory is slowly starting to cough up things. :-)
Post by Ondřej Čada
Safari always caches HTML content. Regardless of the headers, it uses the local cache instead of going back to the server. This is a very serious problem with dynamic web apps (like for example, this one).
Following the instructions here:http://developer.apple.com/internet/safari/faq.html#anchor5
does nothing. See attached screen shot of inspector in Safari showing the headers returned to Safari. Clicking back on this page uses the local cache. Clearly, it should not do that.
Radar 5983915. Still open. Though I did get a little curt with Apple Engineering when they asked for a reproduction case.

Clearly, Safari is totally broken. I have no solution for this other than "don't back track".



Chuck
Post by Ondřej Čada
Post by Chuck Hill
It seems like maybe the browser is caching instead of respecting the headers.
Hmmmm..... seems it is so! I've just downloaded FF, and the behaviour there is indeed considerably different from Safari, and seems from it, it works (more or less) all right. Namely, backtrack does trigger dispatch/appendToResponse there all right
(Somewhat inconsistently with what you suggested /or at least with what I understood/, the action then _gets_ called all right, too. That's not important though.)
Which is bad, since my client rather needs that the app does work with iPad/Safari, too. Darn...
Post by Chuck Hill
It is probably worth using a proxy for your browser (Charles is one) and see if it is actually sending a request. If not, then it is buggy or something is wrong with those headers. If it IS sending a request, then there is a problem in WO or perhaps your web server. Hmmm, that reminds me of something. Are you using mod_expires in Apache? It can mess with the headers.
====
HTTP/1.1 200 Apple WebObjects
cache-control: private
cache-control: no-cache
cache-control: no-store
cache-control: must-revalidate
cache-control: max-age=0
expires: Fri, 27-Apr-2012 02:32:48 GMT
content-type: text/html; charset=UTF-8
pragma: no-cache
x-webobjects-loadaverage: 4
date: Fri, 27-Apr-2012 02:32:48 GMT
set-cookie: wosid=sQtMjsY7xerCBetSFGubaM; version="1"; path=/cgi-bin/WebObjects/CEBOIS.woa
set-cookie: woinst=-1; version="1"; path=/cgi-bin/WebObjects/CEBOIS.woa
content-length: 4140
====
Thanks and all the best,
---
Ondra Čada
--
Chuck Hill Senior Consultant / VP Development

Practical WebObjects - for developers who want to increase their overall knowledge of WebObjects or who are trying to solve specific problems.
http://www.global-village.net/gvc/practical_webobjects
Chuck Hill
2012-05-03 00:47:21 UTC
Permalink
Hi Ondra,

While looking for something else, I see that I actually _did_ work around this. I no longer recall why this works, but it does. I have this in my "page frame" that wraps all of my content pages:

<iframe style="height:0px;width:0px;visibility:hidden" src="about:blank">
This frame prevents back/forward cache bug in Safari do not remove!
</iframe>
</webobject name = "Body" >

A related page is here: http://stackoverflow.com/questions/24046/the-safari-back-button-problem

Chuck
Post by Chuck Hill
Post by Ondřej Čada
Chuck,
Post by Chuck Hill
Which browser are you using?
Safari / Mac OS X. The client reported problems from iPad.
Ah, yes. My aging memory is slowly starting to cough up things. :-)
Post by Ondřej Čada
Safari always caches HTML content. Regardless of the headers, it uses the local cache instead of going back to the server. This is a very serious problem with dynamic web apps (like for example, this one).
Following the instructions here:http://developer.apple.com/internet/safari/faq.html#anchor5
does nothing. See attached screen shot of inspector in Safari showing the headers returned to Safari. Clicking back on this page uses the local cache. Clearly, it should not do that.
Radar 5983915. Still open. Though I did get a little curt with Apple Engineering when they asked for a reproduction case.
Clearly, Safari is totally broken. I have no solution for this other than "don't back track".
Chuck
Post by Ondřej Čada
Post by Chuck Hill
It seems like maybe the browser is caching instead of respecting the headers.
Hmmmm..... seems it is so! I've just downloaded FF, and the behaviour there is indeed considerably different from Safari, and seems from it, it works (more or less) all right. Namely, backtrack does trigger dispatch/appendToResponse there all right
(Somewhat inconsistently with what you suggested /or at least with what I understood/, the action then _gets_ called all right, too. That's not important though.)
Which is bad, since my client rather needs that the app does work with iPad/Safari, too. Darn...
Post by Chuck Hill
It is probably worth using a proxy for your browser (Charles is one) and see if it is actually sending a request. If not, then it is buggy or something is wrong with those headers. If it IS sending a request, then there is a problem in WO or perhaps your web server. Hmmm, that reminds me of something. Are you using mod_expires in Apache? It can mess with the headers.
====
HTTP/1.1 200 Apple WebObjects
cache-control: private
cache-control: no-cache
cache-control: no-store
cache-control: must-revalidate
cache-control: max-age=0
expires: Fri, 27-Apr-2012 02:32:48 GMT
content-type: text/html; charset=UTF-8
pragma: no-cache
x-webobjects-loadaverage: 4
date: Fri, 27-Apr-2012 02:32:48 GMT
set-cookie: wosid=sQtMjsY7xerCBetSFGubaM; version="1"; path=/cgi-bin/WebObjects/CEBOIS.woa
set-cookie: woinst=-1; version="1"; path=/cgi-bin/WebObjects/CEBOIS.woa
content-length: 4140
====
Thanks and all the best,
---
Ondra Čada
--
Chuck Hill Senior Consultant / VP Development
Practical WebObjects - for developers who want to increase their overall knowledge of WebObjects or who are trying to solve specific problems.
http://www.global-village.net/gvc/practical_webobjects
--
Chuck Hill Senior Consultant / VP Development

Practical WebObjects - for developers who want to increase their overall knowledge of WebObjects or who are trying to solve specific problems.
http://www.global-village.net/gvc/practical_webobjects
Loading...