Let’s start from looking what is a Scope.Strategy
by looking at the docs. It says
Pluggable scoping strategy. Enables users to provide custom
implementations of request, session, and wizard scopes. Implement and
pass to
Container.setScopeStrategy(com.opensymphony.xwork2.inject.Scope.Strategy)
Ok, assume I want to implement session scope. Then I need to know the place where I could implement it. The framework has it’s extension points where where you could plug your extensions or simply extend the default
implementation and provide your own custom implementations. This is easy done via looking at the BeanSelectionProvider
. Then analyzing the stacktraces I decided the best point would be to extend the DefaultActionProxyFactory
. Extending it requires to extend the DefaultActionProxy
also.
public class MyActionProxyFactory extends DefaultActionProxyFactory {
public MyActionProxyFactory() {
super();
}
@Override
public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) {
MyActionProxy proxy = new MyActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
container.inject(proxy);
container.setScopeStrategy(new MyScopeStrategy());
proxy.prepare();
return proxy;
}
}
public class MyActionProxy extends DefaultActionProxy {
protected MyActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) {
super(inv, namespace, actionName, methodName, executeResult, cleanupContext);
}
@Override
protected void prepare() {
super.prepare();
}
}
public class MyScopeStrategy implements Scope.Strategy {
@Override
public <T> T findInRequest(Class<T> type, String name, Callable<? extends T> factory) throws Exception {
return null;
}
@Override
public <T> T findInSession(Class<T> type, String name, Callable<? extends T> factory) throws Exception {
ActionContext context = ActionContext.getContext();
SessionMap<String, T> sessionMap = (SessionMap<String, T>) context.getSession();
if (sessionMap == null) {
sessionMap = new SessionMap<String, T>(ServletActionContext.getRequest());
context.setSession((Map<String, Object>) sessionMap);
}
T obj = sessionMap.get(name);
if (obj == null) {
obj = factory.call();
sessionMap.put(name, obj);
}
return obj;
}
@Override
public <T> T findInWizard(Class<T> type, String name, Callable<? extends T> factory) throws Exception {
return null;
}
}
In the configuration file struts.xml
you should set the property
<constant name="struts.actionProxyFactory" value="jspbean.struts.factory.MyActionProxyFactory"/>
That’s all you need to inject a bean Session
with the session scope. Similar implementations could be done for other scopes. Notice, that other scopes like singlton (used by default), thread, and default seems don’t require such pluggable extension. And the last word is about @Scoped
annotation. It’s not used if you provide the beans via xml configuration. But if you supply the ContainerBuilder
with the bean in any other way it’s able to find annotation on it and set the corresponding scope.