aspose file tools
The moose likes Other Application Frameworks and the fly likes Passing session-like data in Spring w/o sessions Big Moose Saloon
  Search | Java FAQ | Recent Topics
Register / Login
JavaRanch » Java Forums » Application Frameworks » Other Application Frameworks
Reply Bookmark "Passing session-like data in Spring w/o sessions" Watch "Passing session-like data in Spring w/o sessions" New topic
Author

Passing session-like data in Spring w/o sessions

Rusty Enisin
Ranch Hand

Joined: May 26, 2005
Posts: 107
I am using Axis, Spring and AspectJ to implement this. There are a few extra requirements: security, auditing, privileged access control.

1. Security is handled by the Axis wss4j plugin. This gets the user from the database and authenticates them. I would like to store the user's data somewhere where the next two steps will have access to it. And make it thread safe.

2. Auditing logs access and actions in the system. We need user data (userId) retrieved during step 1.

3. Each class/method has access privileges set on it. User roles need to be checked before the operation is allowed to continue. Roles are retrieved from the user data from step 1.

This is what the model looks like. For each request two things happen:
1. Axis -> Axis wss4j hander -> Spring (logic) -> dao getUser()
2. Axis -> Spring -> dao... (use user all over the place)

The hard part is since the system backs out all the way back to Axis, there is a kind of disconnect, I think.

The big question is where do I store the user object to pass it from the first lookup to the second? And once I get it into the second, how do I make it available to all beans and yet keep it thread safe?

Spring does not have a session type object that I can do something like session.setAttribute(user). I can put a user bean in the applicationContext, but wouldn't that make the bean not thread safe?

How do I do this? Any ideas?


The squeaky wheel gets the grease. Well, that or replaced...
Chris Mathews
Ranch Hand

Joined: Jul 18, 2001
Posts: 2712
The easiest solution that jumps out to me here is to use a ThreadLocal. However, you need to be extremely careful when implementing this, especially since you are storing user information. The ThreadLocal must absolutely, regardless of exceptions, be cleaned at the end of each request to prevent the possibility of users from "leaking" across requests... this could be done using a Servlet Filter or other mechanism.
Rusty Enisin
Ranch Hand

Joined: May 26, 2005
Posts: 107
Is there nothing within Spring that allows for this? For such a large framework, I am surprised that there is nothing like a request object wherein I can store a common object.

Here are the ideas I have found so far:

1. ThreadLocal - This would work. Like you said, there is the extra task of cleanup. This could be handled with a filter very easily and it would be clean. It also should be thread safe considering each http request is put into a new thread. But, before I go off start messing with threads, I would like to explore more to see if there is any build in feature that I do not know about yet.

2. Use the servlet API's request object. Axis is built on Servlets. The wss4j plugin and the servlet endpoints in spring both have access to the servlet context. Using this I can bridge the gap between the two processes. But there is still no elegant way to make that user data available to the rest of spring and keep it thread safe.

What I am looking for is something in spring that looks like this:
<bean id="myThreadBean" singleton="true" threadsafe="true" class="com.company.User"/>

It would be nice to be able to say, true, I want a singleton, but only for this thread.
Chris Mathews
Ranch Hand

Joined: Jul 18, 2001
Posts: 2712
Originally posted by Rusty Enisin:
It would be nice to be able to say, true, I want a singleton, but only for this thread.

That is exactly the purpose of ThreadLocals. Using a ThreadLocal is not the same as writing threading code... you don't touch the Thread class, you don't implement Runnable, and you aren't actually causing the creation of more threads in the application server. You are just tacking on contextual information for the current request onto the execution thread... very standard use, you just have to be careful that the ThreadLocal is being properly cleaned at the end of each request.
[ April 01, 2006: Message edited by: Chris Mathews ]
Ben Ethridge
Ranch Hand

Joined: Jul 28, 2003
Posts: 108
Hi.

I'm trying to learn more about ThreadLocal, as I have a need for the "per-thread singleton" pattern, and so far, the only solution appears to be based on ThreadLocal. I hesitate to use it though, coz googling around on it, I read so many scary caveats about it. However, it certainly seems to fit the bill, so...

To further ensure that the ThreadLocal is "cleaned", couldn't you also set it to null or some such, at (or near) the logical beginning of the servlet (or web service) run?

By "logical beginning", I mean at some logical pinchpoint through which you know the app is going to pass? (i.e. not the init())

Ben
Ben Ethridge
Ranch Hand

Joined: Jul 28, 2003
Posts: 108
Speaking of googling this, if you google "per-thread singleton", the #1 google result is an article by Brian Goetz, titled "Threading lightly, Part 3: Sometimes it's best not to share":

http://www-128.ibm.com/developerworks/library/j-threads3.html

In it, he does a pretty good job of explaining high-level, what a per-thread singleton is and when/why you'd want to use such, but when I copied in his code:

--------------------------------------------
public class ConnectionDispenser {
private static class ThreadLocalConnection extends ThreadLocal {
public Object initialValue() {
return DriverManager.getConnection(ConfigurationSingleton.getDbUrl());
}
}

private ThreadLocalConnection conn = new ThreadLocalConnection();

public static Connection getConnection() {
return (Connection) conn.get();
}
}
----------------------------------------------

... it wouldn't compile. Never mind about the ConfigurationSingleton compile error. You can just null that out. The REAL compile error is in the conn.get(). Java complains (rightly so, I believe) that you cannot make a static reference to a non-static field.

I could, of course, "fix it up", but, since so many writers are saying to only use ThreadLocal if you really understand its subtleties, I would first need a clear explanation of when/why to use static here and when/why not to (i.e. the static inner classes and static methods).

Having passed the SCJP1.4, I'm somewhat familiar with static's, , but not how to apply them to something as apparently exotic as ThreadLocal. Unfortunately, Sun doesn't give a very good explanation in the api docs either:

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ThreadLocal.html

Of course, if I'm missing something simple about the broken code, please let me know.

Ben
Ben Ethridge
Ranch Hand

Joined: Jul 28, 2003
Posts: 108
Hi, everyone.

I think I have part of the answer, maybe the whole answer. A google search on "static inner class ThreadLocal" returns a blog thread by Crazy Bob (who ain't so crazy sometimes ), that kind of explains why the inner class needs to be static for ThreadLocal use:

http://crazybob.org/2006/02/threadlocal-memory-leak.html

...basically it's "insurance" against memory leaks caused by strong references to the outer class, if I'm understanding this correctly.

That would mean that Mr. Goetz's code needs to be changed to this, in order to compile correctly:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class Test {
private static class ThreadLocalConnection extends ThreadLocal {
public Object initialValue() {
Connection initConn = null;
try {
initConn = DriverManager.getConnection("someURL");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return initConn;
}
}

private static ThreadLocalConnection conn = new ThreadLocalConnection();

public static Connection getConnection() {
return (Connection) conn.get();
}
}

Using the above as a pattern, I created other such "Dispensers" for Spring objects (but not Connections), and they appear to run correctly. I say "appear", because I would still like some confirmation that I'm understanding this correctly from a second source (other that Crazy Bob). I would sure be nice if Sun or someone in authority would state why these need to be static, as I'm still having a bit of trouble visualizing it in relation to ThreadLocal.

In any case, as a side-benefit, using the above, I can do all my Spring stuff programattically, i.e. I'm not having to do anything in the Spring bean xml config files, but am still getting most of the benefit of the Spring classes.

Ben
Ben Ethridge
Ranch Hand

Joined: Jul 28, 2003
Posts: 108
Thinking about this some more, why wouldn't most of the above code need to be sychronized?

Ben
rich farrell
Greenhorn

Joined: May 05, 2006
Posts: 4
I found this thread interesting, and I'm trying to understand the meaning of it all. I understand the concept of thread local, and I understand how servlet filters might be used here. Would one of these be used for instance to pass a transaction instance if you started a transaction that would span several dao objects?
Also, does thread local stuff have to be synchronized?
kri shan
Ranch Hand

Joined: Apr 08, 2004
Posts: 1248
Hi Rusty einsin, Spring supports security thru acegi. check-out this open source project http://www.acegisecurity.org/
Ben Ethridge
Ranch Hand

Joined: Jul 28, 2003
Posts: 108
There is another forum discussion going on about this subject, that may help, at:

http://forum.springframework.org/showthread.php?t=24569

I pointed that thread to this one earlier, so now I'm pointing this one to that as well. Some of the Spring team have started to weigh in on the discussion now.

Ben
 
 
subject: Passing session-like data in Spring w/o sessions
 
Threads others viewed
Stateful or stateless session bean?
Architecture issue...common database access interface
EJB Model
java application accessing the ejb
My SCEA Part 1Study Notes
MyEclipse, The Clear Choice