I'm using a custom interceptor which creates a new db connection, and sets this connection onto the current action before executing the action. After that, the interceptor closes the connection.
I'm looking for a convenient way to share this db connection with other classes / static methods (such as Models) that are used by the action. E.g so I can call static method like User.get( id )
or User.getEmail( id )
without having to pass the db connection to each method separately.
I could set the db connection onto the ActionContext
from the interceptor, by doing:
ServletActionContext.getActionContext().put("db", db );
And then I could access this db connection from a static method, such as:
public class User implements Model
{
public static String getEmail(int id)
{
Connection db =
(Connection) ServletActionContext.getActionContext().get("db");
//...
}
}
My question is, would a new ActionContext
be generated for every given request, so I can be sure that a new db connection will be used each time? E.g if I have 500 people visiting mysite.com/fooAction
, could I be sure that each of those 500 requests is generating a unique ActionContext, and each call to User.getEmail()
would access only the db connection which is unique to the given request?
Thanks.
My question is, would a new ActionContext be generated for every given
request, so I can be sure that a new db connection will be used each
time?
Since ActionContext uses ThreadLocal it is thread safe. Struts 2 creates an ActionContext for each request, and each request has its own thread. So yes, if you create a new connection and store it in the ActionContext every thread will have its own connection. But I don't recommend you to store the connection in the ActionContext because this couple you to Struts 2 which is not a good thing, also your services shouldn't be calling web specific classes because it also couple them.
From Struts 2 Javadoc:
The ActionContext is the context in which an Action is executed. Each
context is basically a container of objects an action needs for
execution like the session, parameters, locale, etc.
The ActionContext is thread local which means that values stored in
the ActionContext are unique per thread. See the
ActionContext.ActionContextThreadLocal class for more information. The
benefit of this is you don't need to worry about a user specific
action context, you just get it:
ActionContext context = ActionContext.getContext(); Finally, because
of the thread local usage you don't need to worry about making your
actions thread safe.
ActionContext excerpt:
public class ActionContext implements Serializable {
static ThreadLocal<ActionContext> actionContext = new ThreadLocal<ActionContext>();
....
}
To answer the question :
My question is, would a new ActionContext be generated for every given
request, so I can be sure that a new db connection will be used each
time?
Is yes. Reference is the java-doc. It similar to the one provided by Alfredo Osorio only it refers to 2.3.x version.
Can you say what struts2 version is being used?
I was not able to find any version that uses
ServletActionContext.getActionContext()
but instead the signature is
ServletActionContext.getActionContext(javax.servlet.http.HttpServletRequest)
To answer the comment regarding thread-local being static and still the ActionContext instance being unique per request its because the doing a
ActionContext.getContext()
internally invokes a get on the thread local instance.
actionContext.get()
You may find the following post helpful in this regard.
However to delve deeper, the method
ServletActionContext.getActionContext(javax.servlet.http.HttpServletRequest)
takes a different route than using the thread-local.
public static ActionContext getActionContext(HttpServletRequest req) {
ValueStack vs = getValueStack(req);
if (vs != null) {
return new ActionContext(vs.getContext());
} else {
return null;
}
}
public static ValueStack getValueStack(HttpServletRequest req) {
return (ValueStack) req.getAttribute(STRUTS_VALUESTACK_KEY);
}
getActionContext
getValueStack
Below are some additional references (source code).
ValueStack
OgnlValueStack
ActionContext
The following posts may also be helpful.
will-a-new-actioncontext-and-valuestack-be-created-for-every-new-action-object
struts2-actioncontext-and-valuestack
Update 2 :
Wanted to add as mentioned here (Link 1 above) that in case of ActionChaining being involved, the action is invoked with its own interceptor stack and result.
The thread in which its executed, however is the same.
The value-stack and parameters are copied over. See - ActionChainResult#execute(ActionInvocation).
Once the chain-invocation is complete, the state of the action-context is reset. (See DefaultActionProxy#execute() ).
Partial Information : Although the action-invocation is set in DefaultActionInvocation#init(ActionProxy) I was not able to determine if or where it is reset.
Sources :
DefaultActionInvocation
DefaultActionProxy
DefaultActionProxyFactory
ActionChainResult
FilterDispatcher(Deprecated)