Problem with rewriting and SessionVar

45 views
Skip to first unread message

Jeppe Nejsum Madsen

unread,
Nov 13, 2009, 8:21:03 AM11/13/09
to lif...@googlegroups.com
Hi,

I seem to have a problem with SessionVars which I try to initialize in
a LocRewrite.

This is an entry point url to the app. It receives some parameters from
the url, picks out the parameters and puts them in SessionVars and
rewrites the request.

I have problems setting the SessionVar when I hit the url in a clean
browser (ie with no session)

This is the code:
private object curAccountId extends SessionVar[Box[Long]](Empty)

private object curAccount extends RequestVar[Box[Account]] ({
println("read:"+curAccountId);
val found = currentAccountId.flatMap(id => getSingleton.find(id));
println("Found: "+found);
found}) with CleanRequestVarOnSessionTransition

def currentAccountId: Box[Long] = curAccountId.is
def currentAccount: Box[Account] = curAccount.is
def currentAccount_=(account: Box[Account]) {
println("set account: "+account);
curAccount.remove
curAccountId.remove
curAccountId.set({val s = account.map{a => a.id.is}; println("set: "+s);s});
curAccount.set(account);
println("read2:"+curAccountId.is)
}

In the LocRewrite I call Account.setCurrentAccount = someAccount

When the URL is hit in a clean browser, this is logged:

set account: Full(dk.fleetzone.model.Account={name=Demo Account,id=1})
set: Full(1)
read2:Empty

If I hit the login page first (and nothing else, but I believe it triggers the
creation of a http session), and the exact same url, this is logged:

set account: Full(dk.fleetzone.model.Account={name=Demo Account,id=1})
set: Full(1)
read2:Full(1)

Any clues??

/Jeppe


David Pollak

unread,
Nov 13, 2009, 9:01:53 AM11/13/09
to lif...@googlegroups.com

Yes.  The rewrite phase takes place very early in the HTTP request/response cycle.  It takes place before the statelessDispatch call.  The statelessDispatch call is very important for REST style APIs as it does *not* cause the creation of a session, thus for lots of API calls, we don't have a session created for each call.

The rewrite phase has to come before the statelessDispatch phase because the request has to be properly rewritten before being pattern matched against the partial functions that define the statelessDispatch

Based on some of your prior needs, I've made the session available during the rewrite phase, but it's only if the session actually exists (basically, the request is checked for a session, but the request is not told "create one if it doesn't already exists".

So, the first request from a browser does not have a session and thus does not have session vars.  Is there a way you can use RequestVars here?
 

/Jeppe









--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics

Jeppe Nejsum Madsen

unread,
Nov 13, 2009, 9:46:09 AM11/13/09
to lif...@googlegroups.com
David Pollak <feeder.of...@gmail.com> writes:

[...]

> Yes. The rewrite phase takes place very early in the HTTP request/response
> cycle. It takes place before the statelessDispatch call. The
> statelessDispatch call is very important for REST style APIs as it does
> *not* cause the creation of a session, thus for lots of API calls, we don't
> have a session created for each call.
>
> The rewrite phase has to come before the statelessDispatch phase because the
> request has to be properly rewritten before being pattern matched against
> the partial functions that define the statelessDispatch
>
> Based on some of your prior needs, I've made the session available during
> the rewrite phase, but it's only if the session actually exists (basically,
> the request is checked for a session, but the request is not told "create
> one if it doesn't already exists".

I sort of guessed it had to do with this. I find rewriting really useful
to write apps that need to extract info from the URL in a type-safe way
before continuing the processing.

I seem to run into a number of issues with this approach (some which
you've fixed, thanks!), so was wondering if perhaps I'm misusing
rewriting and there are better ways to approach this?

A few thoughts:

- Is it possible to create a session manually in the rewrite phase? If
no, maybe a LiftRule PF that could be used to force session creation
for certain requests?

- Would it be possible to detect (at least in Dev mode) some of these
misuses (i.e. using a SessionVar with no session) and emit a warning?

> So, the first request from a browser does not have a session and thus does
> not have session vars. Is there a way you can use RequestVars here?

I guess I can hack something together for this case, but I need to think
a little more to make sure it fits cleanly with the rest.

If I just redirect back to the same page, will this trigger the session
creation or does the redirect happen before the session is created?

It's a multipage workflow, so SessionVars seem like the easy way out
:-)

/Jeppe

David Pollak

unread,
Nov 13, 2009, 7:13:24 PM11/13/09
to lif...@googlegroups.com
On Fri, Nov 13, 2009 at 6:46 AM, Jeppe Nejsum Madsen <je...@ingolfs.dk> wrote:

David Pollak <feeder.of...@gmail.com> writes:

[...]

> Yes.  The rewrite phase takes place very early in the HTTP request/response
> cycle.  It takes place before the statelessDispatch call.  The
> statelessDispatch call is very important for REST style APIs as it does
> *not* cause the creation of a session, thus for lots of API calls, we don't
> have a session created for each call.
>
> The rewrite phase has to come before the statelessDispatch phase because the
> request has to be properly rewritten before being pattern matched against
> the partial functions that define the statelessDispatch
>
> Based on some of your prior needs, I've made the session available during
> the rewrite phase, but it's only if the session actually exists (basically,
> the request is checked for a session, but the request is not told "create
> one if it doesn't already exists".

I sort of guessed it had to do with this. I find rewriting really useful
to write apps that need to extract info from the URL in a type-safe way
before continuing the processing.

I seem to run into a number of issues with this approach (some which
you've fixed, thanks!), so was wondering if perhaps I'm misusing
rewriting and there are better ways to approach this?

A few thoughts:

- Is it possible to create a session manually in the rewrite phase?

Yes.  Please open a ticket
 
If
 no, maybe a LiftRule PF that could be used to force session creation
 for certain requests?

No, because we don't know what the request is during the rewrite phase.
 

- Would it be possible to detect (at least in Dev mode) some of these
 misuses (i.e. using a SessionVar with no session) and emit a warning?

Yes.  Please open a ticket.
 

> So, the first request from a browser does not have a session and thus does
> not have session vars.  Is there a way you can use RequestVars here?

I guess I can hack something together for this case, but I need to think
a little more to make sure it fits cleanly with the rest.

Generally, the rewrite phase should not have side effects.  Yeah, storing something in a RequestVar is one thing, but changing session state is another.  I would strongly suggest looking at your code and seeing if you can set the SessionVar in the business logic portion of your code.
 

If I just redirect back to the same page, will this trigger the session
creation or does the redirect happen before the session is created?

You could manually force the session to be created and then redirect.
 

It's a multipage workflow, so SessionVars seem like the easy way out
:-)

Wizard is coming. :-)
 

/Jeppe



Reply all
Reply to author
Forward
0 new messages