INTERNAL_SERVER_ERROR when altering session

7 views
Skip to first unread message

Justin Hayes

unread,
Jul 23, 2009, 12:19:50 AM7/23/09
to Compojure
I have a simple web app with a login form that submits to a handler
that authenticates the username/password and then attempts to store
the username in the session. When it gets to the (alter session
assoc :name (params :name)) expression it fails with:

HTTP ERROR 500
Problem accessing /login/. Reason:
INTERNAL_SERVER_ERROR
Caused by:
java.lang.NullPointerException
at clojure.core$alter__4494.doInvoke(core.clj:1436)
at clojure.lang.RestFn.invoke(RestFn.java:462)
at communitiesgrow$login_controller__15$fn__17$fn__19.invoke
(communitiesgrow.clj:55)
at clojure.lang.AFn.call(AFn.java:31)
at clojure.lang.LockingTransaction.runInTransaction
(LockingTransaction.java:202)
at communitiesgrow$login_controller__15$fn__17.invoke
(communitiesgrow.clj:54)
at clojure.lang.AFn.call(AFn.java:31)
at clojure.lang.LockingTransaction.run(LockingTransaction.java:236)
at clojure.lang.LockingTransaction.runInTransaction
(LockingTransaction.java:204)
at communitiesgrow$login_controller__15.invoke(communitiesgrow.clj:
47)
...

Here is the route it uses:
(POST "/login/"
(login-controller session params))

And here is the controller:
(defn login-controller [session params]
(dosync
(if
(and
(= "changeme" (params :password))
(.matches (params :name) "[\\w\\s\\-]+"))
(dosync
(alter session assoc :name (params :name)) ;; FAILS HERE
(redirect-to "/"))
(redirect-to "/login/"))))

It's like the session ref isn't there or isn't being set up properly.
Has anyone else seen something like this? Or, even better, does anyone
know what's going on?

Thanks.

Shantanu Kumar

unread,
Jul 23, 2009, 6:30:26 AM7/23/09
to comp...@googlegroups.com
You may like to call (.setAttribute session :name (:name params))


Regards,
Shantanu

Justin Hayes

unread,
Jul 23, 2009, 9:18:06 AM7/23/09
to Compojure
I tried that and am still getting the NullPointerException. I don't
think that the session is being created properly. I've tried using
several different functions with the session ref and they all give
null ptr exceptions.

Also, doesn't (.setAttribute session ...) change the semantics by not
using STM like (alter session ...) does? Probably not a huge deal in
this case but I just want to make sure I understand it correctly.

Thanks.

On Jul 23, 6:30 am, Shantanu Kumar <kumar.shant...@gmail.com> wrote:
> You may like to call (.setAttribute session :name (:name params))
> It is working for me --http://bitbucket.org/kumarshantanu/blogjure/
>
> Regards,
> Shantanu

Shantanu Kumar

unread,
Jul 23, 2009, 9:33:06 AM7/23/09
to comp...@googlegroups.com
It is likely that the session object is not the correct one. You may like to use the get-http-session function from code at the URL below to extract the HttpSession object from Compojure's request object. (Compojure request is NOT HttpServletRequest object -- it is what you pass on from the route.)


> Also, doesn't (.setAttribute session ...) change the semantics by not
> using STM like (alter session ...) does? Probably not a huge deal in
> this case but I just want to make sure I understand it correctly.

I would expect the session object to be thread safe anyway - it is provided by the app server. :-)

Regards,
Shantanu

Luke Renn

unread,
Jul 23, 2009, 9:45:46 AM7/23/09
to Compojure
On Jul 23, 9:18 am, Justin Hayes <justin.a.ha...@gmail.com> wrote:
> Also, doesn't (.setAttribute session ...) change the semantics by not
> using STM like (alter session ...) does? Probably not a huge deal in
> this case but I just want to make sure I understand it correctly.

I'm sorry that I don't have time for a detailed explanation right now,
but you should be using with-session (if you aren't) and session-
assoc. Take a look at:

http://preview.compojure.org/docs/sessions

The preview site seems to be missing it's css, but the info is there.

Luke

Luke Renn

unread,
Jul 23, 2009, 10:38:53 AM7/23/09
to Compojure
On Jul 23, 9:33 am, Shantanu Kumar <kumar.shant...@gmail.com> wrote:
> It is likely that the session object is not the correct one. You may like to
> use the get-http-session function from code at the URL below to extract the
> HttpSession object from Compojure's request object. (Compojure request is
> NOT HttpServletRequest object -- it is what you pass on from

This is not the correct way to use sessions with Compojure. Again,
sorry for not having the time right now for a more detailed
explanation.

Luke

Luke Renn

unread,
Jul 23, 2009, 11:42:58 PM7/23/09
to Compojure
On Jul 23, 9:18 am, Justin Hayes <justin.a.ha...@gmail.com> wrote:
> I tried that and am still getting the NullPointerException. I don't
> think that the session is being created properly. I've tried using
> several different functions with the session ref and they all give
> null ptr exceptions.

Give this a try:

http://gist.github.com/153821

So the key is to make sure you use with-session, and to call session-
assoc. Routes do different things depending on what they return
(http://preview.compojure.org/docs/route-macros). Since the login-
controller returns a vector "Each element in the vector is used to
update the response." So first the session-assoc updates the response
with it's new session map, then the redirect does (where the session
is now updated).

Luke

Luke Renn

unread,
Jul 24, 2009, 12:32:47 AM7/24/09
to Compojure
On Jul 23, 9:33 am, Shantanu Kumar <kumar.shant...@gmail.com> wrote:
> It is likely that the session object is not the correct one. You may like to
> use the get-http-session function from code at the URL below to extract the
> HttpSession object from Compojure's request object. (Compojure request is
> NOT HttpServletRequest object -- it is what you pass on from the route.)http://bitbucket.org/kumarshantanu/blogjure/src/tip/src/blogjure/mvc/...
>

Using the linked code you lose two of Compojure's biggest advantages:
easily testable code, and server abstraction. You're now forced to be
running your server (which now must be a Servlet container) whenever
you call any of your methods.

Using the gist I posted above you can call anything in your app from
the repl without even starting a webserver.

user> (home-controller {:username "lrenn"})
"<html><body><h2>Home<p>Hello lrenn.</p></h2></body></
html>"
user> (home-controller {})
[302 {:headers {"Location" "/
login"}}]
user> (login-view {:message "Some flash message."})
"<html><body><h2>Login</h2><h4>Some flash message.</h4><form action=\"/
login\" \
method=\"POST\"><input id=\"username\" name=\"username\" type=\"text
\" /><input\
id=\"password\" name=\"password\" type=\"password\" value=\"\" /
><input type=\\
"submit\" value=\"Login\" /></form></body></html>"

Testing if home-controller redirects to the login page if the user
isn't logged in is just a:

(deftest login-redirects
(is (= (home-controller {})
[302 {:headers {"Location" "/login"}}])))

Which could also be run at the repl without the server running.

Luke

Justin Hayes

unread,
Jul 24, 2009, 6:42:43 AM7/24/09
to Compojure
Thanks for the thorough response(s). They have definitely helped me in
the process of getting started with compojure.

Shantanu Kumar

unread,
Jul 24, 2009, 8:22:01 AM7/24/09
to Compojure
Many thanks for explaining that - I wasn't aware of http://preview.compojure.org/docs
so hacked together from what I found.

Regards,
Shantanu

Tom Hickey

unread,
Aug 6, 2009, 9:07:41 AM8/6/09
to Compojure
Luke,

Thanks for the gist! I hadn't used compojure for a long while and this
was the perfect example for getting my session-related code ported.

Cheers,
Tom Hickey

On Jul 23, 11:42 pm, Luke Renn <luke.r...@gmail.com> wrote:
Reply all
Reply to author
Forward
0 new messages