More problems with CRUDify and SessionVars

8 views
Skip to first unread message

Jeppe Nejsum Madsen

unread,
Aug 10, 2009, 11:37:57 AM8/10/09
to lif...@googlegroups.com
Hi,

I'm using CRUDify, but all domain objects belong to an account, so I
need to add the current user's account id to the queries made by
CRUDIfy. This works fine for the list Loc:

override def findForListParams: List[QueryParam[Vehicle]] =
List(OrderBy(primaryKeyField, Ascending), By(account, User.currentUser.open_!.account.is))

But for the edit/delete Locs, this fails:

override def findForParam(in: String): Box[Vehicle] = {
Log.info("User %s, id=%s".format(User.currentUser, User.currentUserId))
find(List(in,By(account, User.currentUser.open_!.account.is)))
}

Both currentUser & currentUserId is empty at this point in the request
cycle, as can be seen from this log output:

INFO - User Empty, id=Empty
java.lang.NullPointerException: Trying to open an empty Box
at net.liftweb.util.EmptyBox.open_$bang(Box.scala:370)
at net.liftweb.util.EmptyBox.open_$bang(Box.scala:366)
at dk.model.Vehicle$$$M$f617a4a2.findForParam(Vehicle.scala:276)
at dk.model.Vehicle$$$A$f617a4a2.findForParam(<generated>)
at dk.model.Vehicle$.findForParam(Vehicle.scala:259)
at net.liftweb.mapper.CRUDify$$anon$6$$anonfun$4.gd4$1(CRUDify.scala:174)
at net.liftweb.mapper.CRUDify$$anon$6$$anonfun$4.isDefinedAt(CRUDify.scala:170)
at net.liftweb.mapper.CRUDify$$anon$6$$anonfun$4.isDefinedAt(CRUDify.scala:170)
at net.liftweb.util.NamedPF.isDefinedAt(NamedPartialFunction.scala:29)
at net.liftweb.sitemap.Loc$$anonfun$rewritePF$1$$anon$1.isDefinedAt(Loc.scala:77)
at net.liftweb.sitemap.Loc$$anonfun$rewritePF$1$$anon$1.isDefinedAt(Loc.scala:70)
at net.liftweb.util.NamedPF$$anonfun$find$1.apply(NamedPartialFunction.scala:51)
at net.liftweb.util.NamedPF$$anonfun$find$1.apply(NamedPartialFunction.scala:51)
at scala.List.find(List.scala:1048)
at net.liftweb.util.NamedPF$.find(NamedPartialFunction.scala:51)
at net.liftweb.util.NamedPF$.applyBox(NamedPartialFunction.scala:91)
at net.liftweb.http.Req$.processRewrite$1(Req.scala:114)
at net.liftweb.http.Req$.apply(Req.scala:123)
at net.liftweb.http.provider.HTTPProvider$class.service(HTTPProvider.scala:51)
at net.liftweb.http.LiftFilter.service(LiftServlet.scala:481)
at net.liftweb.http.provider.servlet.ServletFilterProvider$class.protected$service(ServletFilterProvider.scala:41)
at net.liftweb.http.LiftFilter.protected$service(LiftServlet.scala:481)
at net.liftweb.http.provider.servlet.ServletFilterProvider$$anonfun$doFilter$1.apply(ServletFilterProvider.scala:41)
at net.liftweb.http.provider.servlet.ServletFilterProvider$$anonfun$doFilter$1.apply(ServletFilterProvider.scala:36)
at net.liftweb.http.RequestVarHandler$$anonfun$apply$5$$anonfun$apply$6$$anonfun$apply$7$$anonfun$apply$8.apply(Vars.scala:212)
at net.liftweb.util.ThreadGlobal.doWith(ThreadGlobal.scala:65)
at net.liftweb.http.RequestVarHandler$$anonfun$apply$5$$anonfun$apply$6$$anonfun$apply$7.apply(Vars.scala:211)
at net.liftweb.util.ThreadGlobal.doWith(ThreadGlobal.scala:65)
at net.liftweb.http.RequestVarHandler$$anonfun$apply$5$$anonfun$apply$6.apply(Vars.scala:210)
at net.liftweb.util.ThreadGlobal.doWith(ThreadGlobal.scala:65)
at net.liftweb.http.RequestVarHandler$$anonfun$apply$5.apply(Vars.scala:209)
at net.liftweb.util.ThreadGlobal.doWith(ThreadGlobal.scala:65)
at net.liftweb.http.RequestVarHandler$.apply(Vars.scala:208)

I think I'm seeing something similar to the problem mentioned here
http://groups.google.com/group/liftweb/browse_thread/thread/0190091bcdb6d18a/90a33ace15273d3d?lnk=raot

except now also the User.currentUserId SesssionVar seems to be
uninitialized.

So, is this not supported? Is there a workaround?

Just back from two weeks of vacation, I might have missed something
obvious :-)

/Jeppe

David Pollak

unread,
Aug 10, 2009, 11:46:35 AM8/10/09
to lif...@googlegroups.com
(1) Don't use open_! unless you have a very, very, very good reason to do so.  It defeats the purpose of Box.
(2) If you have a particular question/example of what you want to do (a complete, runnable example), I can work out a pattern for you.
--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp

Jeppe Nejsum Madsen

unread,
Aug 10, 2009, 12:07:08 PM8/10/09
to lif...@googlegroups.com
David Pollak <feeder.of...@gmail.com> writes:

> (1) Don't use open_! unless you have a very, very, very good reason to do
> so. It defeats the purpose of Box.

I'm aware of this. But in this situation, most Locs are protected, ie the
user is always logged in, so the only alternatives I see are:

1) wrap the code in map or something similar which will then return
Empty if no user is found. But this is dangerous, giving the user the
impression that no data is found when in fact this is a coding error.

2) Redirect to a nice error page if this code is called with no user
active. This is of course the nice solution, but we have more pressing
needs atm :-)

But maybe I've missed something obvious and there are better ways to
handle this?

> (2) If you have a particular question/example of what you want to do (a
> complete, runnable example), I can work out a pattern for you.

The question comes down to: Why is User.currentUserId Empty when
findForParam is called? The user is signed in, since
findForListParams works fine.

If I remember the previous thread correctly, there is some tension
between request rewriting (as is done in CRUDify when edit/delete
actions are called ) and the session/request var initialization. Wonder
if I'm seeing more of the same here?

I might be able to put together an example, but that will have to wait a
few days (lots of stuff to catch up with after vacation :-)

/Jeppe

David Pollak

unread,
Aug 12, 2009, 2:49:51 PM8/12/09
to lif...@googlegroups.com
On Mon, Aug 10, 2009 at 9:07 AM, Jeppe Nejsum Madsen <je...@ingolfs.dk> wrote:

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

> (1) Don't use open_! unless you have a very, very, very good reason to do
> so.  It defeats the purpose of Box.

I'm aware of this. But in this situation, most Locs are protected, ie the
user is always logged in, so the only alternatives I see are:

1) wrap the code in map or something similar which will then return
Empty if no user is found. But this is dangerous, giving the user the
impression that no data is found when in fact this is a coding error.

User.currentUserId.map(... business logic here) openOr defaultValue
 


2) Redirect to a nice error page if this code is called with no user
active. This is of course the nice solution, but we have more pressing
needs atm :-)

But maybe I've missed something obvious and there are better ways to
handle this?

See the above code.


> (2) If you have a particular question/example of what you want to do (a
> complete, runnable example), I can work out a pattern for you.

The question comes down to: Why is User.currentUserId Empty when
findForParam is called?

Because this method is called during the re-writing phase.

I've updated Lift to make the session available during the re-writing phase if there is a session (a new session will not be created) to deal with this situation.
 
The user is signed in, since
findForListParams works fine.

If I remember the previous thread correctly, there is some tension
between request rewriting (as is done in CRUDify when edit/delete
actions are called ) and the session/request var initialization. Wonder
if I'm seeing more of the same here?

I might be able to put together an example, but that will have to wait a
few days (lots of stuff to catch up with after vacation :-)

/Jeppe


Jeppe Nejsum Madsen

unread,
Aug 19, 2009, 8:20:03 AM8/19/09
to lif...@googlegroups.com
Seems I missed this response....more comments below

On Wed, Aug 12, 2009 at 8:49 PM, David
Pollak<feeder.of...@gmail.com> wrote:
>
>
> On Mon, Aug 10, 2009 at 9:07 AM, Jeppe Nejsum Madsen <je...@ingolfs.dk>
> wrote:
>>
>> David Pollak <feeder.of...@gmail.com> writes:
>>
>> > (1) Don't use open_! unless you have a very, very, very good reason to
>> > do
>> > so.  It defeats the purpose of Box.
>>
>> I'm aware of this. But in this situation, most Locs are protected, ie the
>> user is always logged in, so the only alternatives I see are:
>>
>> 1) wrap the code in map or something similar which will then return
>> Empty if no user is found. But this is dangerous, giving the user the
>> impression that no data is found when in fact this is a coding error.
>
> User.currentUserId.map(... business logic here) openOr defaultValue

But the problem arise when there is no good default to apply. I.e.
suppose the business logic was "list my items" where "my" depends on
currentUser. If, for all intents and purposes, this list is only
available to signed in users, it doesn't really make sense to show no
list or some random user's list.

[...]

>> The question comes down to: Why is User.currentUserId Empty when
>> findForParam is called?
>
> Because this method is called during the re-writing phase.
>
> I've updated Lift to make the session available during the re-writing phase
> if there is a session (a new session will not be created) to deal with this
> situation.

As noted above, I missed this post earlier and went ahead to create an
example showing the problem. When I didn't succeed to show the error,
I scratched my head a few times and went back to my app to see if it
failed. Lo and behold, it worked!

Thanks for the fix, sorry for the late reply :-)

/Jeppe

David Pollak

unread,
Aug 19, 2009, 12:28:30 PM8/19/09
to lif...@googlegroups.com
On Wed, Aug 19, 2009 at 5:20 AM, Jeppe Nejsum Madsen <je...@ingolfs.dk> wrote:

Seems I missed this response....more comments below

On Wed, Aug 12, 2009 at 8:49 PM, David
Pollak<feeder.of...@gmail.com> wrote:
>
>
> On Mon, Aug 10, 2009 at 9:07 AM, Jeppe Nejsum Madsen <je...@ingolfs.dk>
> wrote:
>>
>> David Pollak <feeder.of...@gmail.com> writes:
>>
>> > (1) Don't use open_! unless you have a very, very, very good reason to
>> > do
>> > so.  It defeats the purpose of Box.
>>
>> I'm aware of this. But in this situation, most Locs are protected, ie the
>> user is always logged in, so the only alternatives I see are:
>>
>> 1) wrap the code in map or something similar which will then return
>> Empty if no user is found. But this is dangerous, giving the user the
>> impression that no data is found when in fact this is a coding error.
>
> User.currentUserId.map(... business logic here) openOr defaultValue

But the problem arise when there is no good default to apply. I.e.
suppose the business logic was "list my items" where "my" depends on
currentUser. If, for all intents and purposes, this list is only
available to signed in users, it doesn't really make sense to show no
list  or some random user's list.

In general, it's "good practice" to comment the use of "open_!" as to why you are using it.  For example "Box tested at a level above this method" or "no alternative, so an exception should be thrown if the box is empty"
 


[...]

>> The question comes down to: Why is User.currentUserId Empty when
>> findForParam is called?
>
> Because this method is called during the re-writing phase.
>
> I've updated Lift to make the session available during the re-writing phase
> if there is a session (a new session will not be created) to deal with this
> situation.

As noted above, I missed this post earlier and went ahead to create an
example showing the problem. When I didn't succeed to show the error,
I scratched my head a few times and went back to my app to see if it
failed. Lo and behold, it worked!

Thanks for the fix, sorry for the late reply :-)

No worries.
 


/Jeppe


Reply all
Reply to author
Forward
0 new messages