SessionAware.[ Side note -- Interestingly enough, there may have been talk of deprecating SessionAware in WebWork's early days according to an old WebWork wiki. Does anyone have any more information about this? ]
By implementing
SessionAware, you provide a method that allows a Struts 2 interceptor to inject the session dependency into the appropriate action.Basically, your code looks something like this:
A Struts interceptor intercepts this action and injects the session into the action. That's fine, but most of the time I just want one or two things from the session and I really do not need the entire session object.
/////////////////////////////////////////////////////////
// SomeAction.java
public class SomeAction extends ActionSupport
implements SessionAware {
private Map<Object, Object> session;
private Object someObjectFromSession;
@Override
public String execute() {
someObjectFromSession = session.get("someKey");
// ... do something ...
return SUCCESS;
}
@SuppressWarnings("unchecked");
public void setSession(Map session) {
this.session = session;
}
// ... other methods ...
}
Another way to read objects from the session is to create your own
<SomeObject>Aware interfaces and then create interceptors to retrieve your necessary session objects. For instance, if you logged in a user and then wanted to retrieve this user from the session, you could implement something like this:I prefer the second way because it injects just the object you need into the action rather than the entire session map. However, I had actions that required more than one value from the session and I did not want to implement a corresponding interface and interceptor for each value. I wanted one interceptor to perform all the legwork for me. There already is a great solution that is freely available that I use with my own stuff, but I decided to create my own solution just for the experience and to become more familiar with the Java Reflection API. I created an annotation and then used an interceptor to inject the dependency if the annotation was in place. For instance, the preceding example would be implemented like this:
/////////////////////////////////////////////////////////
// SomeAction.java
public class SomeAction extends ActionSupport implements UserAware {
private User user;
@Override
public String execute() {
// ... do something ...
return SUCCESS;
}
public void setUser(User user) {
this.session = session;
}
// ... other methods ...
}
/////////////////////////////////////////////////////////
// UserInterceptor.java
public class UserInterceptor extends AbstractInterceptor {
public UserInterceptor() {
super();
}
@SuppressWarnings("unchecked")
public String intercept(ActionInvocation invocation)
throws Exception {
Map<Object,Object> session =
invocation.getInvocationContext().getSession();
User user = (User)session.get("user");
// ... handle case if no user on session ...
Object action = invocation.getAction();
if (action instanceof UserAware) {
((UserAware)action).setUser(user);
}
return invocation.invoke();
}
}
Now, the interceptor uses reflection to check if any of the action's setter methods have the
/////////////////////////////////////////////////////////
// SessionValue.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SessionValue {
public String id();
}
/////////////////////////////////////////////////////////
// SomeAction.java
public class SomeAction extends ActionSupport {
private User user;
@Override
public String execute() {
// ... do something ...
return SUCCESS;
}
@SessionValue(id = "user")
public void setUser(User user) {
this.session = session;
}
// ... other methods ...
}
/////////////////////////////////////////////////////////
// SessionValueLookupInterceptor.java
public class SessionValueLookupInterceptor extends AbstractInterceptor {
public SessionValueLookupInterceptor () {
super();
}
@SuppressWarnings("unchecked")
public String intercept(ActionInvocation invocation)
throws Exception {
Map<Object, Object> session =
invocation.getInvocationContext().getSession();
Object action = invocation.getAction();
for (Method m : action.getClass().getMethods()) {
if (m.isAnnotationPresent(SessionValue.class)) {
if (m.getName().startsWith("set")) {
SessionValue ann = m.getAnnotation(SessionValue.class);
String id = ann.id();
Object obj = session.get(id);
m.invoke(action, obj);
}
}
}
return invocation.invoke();
}
}
SessionValue annotation. If the method does have the annotation, the interceptor tries to envoke the setter method with the object on the session who has an ID of the value specified in the annotation. In other words, in the preceding example the interceptor retrieves the object from the session whose ID is "user" and envokes the action's setUser method.The nice thing about the preceding example is that that interceptor is the only interceptor you need to implement to retreive any object from the session. Simply put the
SessionValue annotation above the appropriate setter method, add the interceptor to your interceptor stack and you are good to go.Note that the preceding was a basic example and some additional sanity checks may be necessary for your own application (e.g.
null object condition, better exception handling in interceptor, etc.), but I hope that's enough to get you going. Feel free to use/change/whatever the preceding code for your own application development. In my next post, I will post an example of the annotation in action.If you are new to annotations and reflection, the following link provides a some information and a quick example:
As stated previously, there already is a great solution out there so if you are looking for code that's ready for prime time, use that instead, but feel free to download the previous example if you're looking for an introduction to see annotations and reflection in action.

4 comments:
nice post, this is what i'm looking for. Thank you
You can still follow below code
class where session value is to set:
----------------------------
private Map session;
@Override
public String execute() throws Exception {
getSession().put("username",getUsername());
return SUCCESS;
}
public void setSession(Map session) {
this.session = session;
}
public Map getSession() {
return session;
}
-----------------------------
Class where session value from first class is to be retrieved:
private Map session;
private Object someObjectFromSession;
someObjectFromSession = session.get("username");
public void setSession(Map session)
{
this.session = session;
}
public Map getSession()
{
return session;
}
----------------------
dont forgot to import :
import com.opensymphony.xwork2.ActionSupport;
import java.util.*;
import org.apache.struts2.interceptor.SessionAware;
Post a Comment