Quoting Nifty Music <[EMAIL PROTECTED]>:
> Howdy all!
>
> I was considering employing a "Master Action Class" from which I could
> inherit smaller action classes in order to make effective use of shared code.
> However, I want to ensure that the code remains thread-safe. Here's an
> example of what I was considering:
>
Unfortunately, this is a pretty classic example of non-threadsafe Action code.
Remember that there is only one Action instance in the entire web application,
shared by all requests that happen to select this action. The problem comes
when two (or more) requests for the same action happen at the same time.
> public abstract class MainAction extends TilesAction {
>
> protected DynaValidatorForm form = null;
> protected ActionErrors errors = null;
> protected ActionMessages messages = null;
Because these variables are declared outside of a method, they are *instance*
variables and therefore shared across requests. That's not what you want.
> protected SimpleDateFormat df=new
> SimpleDateFormat("MM/dd/yyyy",Locale.US);
Although a SimpleDateFormat looks like something you ought to be able to share
successfully, it turns out this class is not threadsafe either.
> public abstract ActionForward execute(ActionMapping mapping, ActionForm
> baseForm, HttpServletRequest request, HttpServletResponse response);
>
> protected boolean validLogon(HttpSession session) {
> //check session to ensure that it's not invalidated
> }
>
> protected void startSubTransaction(HttpSession session) {
> session.setAttribute(Constants.SUB_TRANSACTION_IN_PROGRESS,
> Constants.TRUE);
>
> }
>
> protected void endSubTransaction(HttpSession session) {
> session.setAttribute(Constants.SUB_TRANSACTION_IN_PROGRESS,
> Constants.FALSE);
> }
> }
>
> public class SubAction extends MainAction {
>
> private static Logger logger = Logger.getLogger(SubAction.class);
>
> public ActionForward execute(
> ActionMapping mapping,
> ActionForm baseForm,
> HttpServletRequest request,
> HttpServletResponse response) {
>
> form = (DynaValidatorForm) baseForm;
What happens when two requests execute this statement at (essentially) the same
time? The second assignment wipes out the first one, and you start seeing
references to the wrong form bean.
The answer is to only declare variables INSIDE your methods, and then explicitly
pass them as parameters to the methods in your subclass.
> errors = new ActionErrors();
>
> if (!validLogon(request.getSession())) {
> return (mapping.findForward("logon"));
>
> }
>
> //Check for errors
> if (!errors.isEmpty()) {
> saveErrors(request, errors);
> return (mapping.findForward("error"));
> }
>
> saveToken(request);
> startSubTransaction(request.getSession());
> return (mapping.findForward("success"));
> }
> }
>
> What with the form, errors & messages variables being defined at class level
> in the parent class, could I run into some issues with instance variables
> being overwritten with different requests?
Absolutely.
Should I move them into the
> individual execute() methods of the subclasses of MainAction?
>
Or declare them in the base class's execute() method and pass them as
parameters.
> Thanks,
>
> Brent
>
Craig
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]