views:

210

answers:

2

I've got the following (shortened) struts2 action:

public class MyAction extends BaseAction implements CookiesAware {

  public String execute() {

    if (cookiesMap.containsKey("BLAH"))
      blah=Integer.parseInt(cookiesMap.get("BLAH"));

      return "success";
  }

  // For handling cookies
  Map<String, String> cookiesMap;
  @Override
  public void setCookiesMap(Map<String, String> cookiesMap) {
    this.cookiesMap = cookiesMap;
  }
}

I get a null pointer exception when i do 'cookiesMap.containsKey' - it seems to me that setCookiesMap isn't being called. I've implemented the CookiesAware interface so i would have thought that it should be getting called - have i missed something here?

Thanks

+2  A: 

You need to also implement the Cookie Interceptor for the action definition in your struts.xml:

<action name="MyAction" class="your.fancy.app.MyAction">
    <interceptor-ref name="defaultStack"/>       
    <interceptor-ref name="cookie">
        <param name="cookiesName">BLAH</param>
    </interceptor-ref>
    <result>/index.jsp</result>
</action>
Pat
Of course! More XML configuration! Silly me: I forgot for a minute there that i was working with Java, i should have guessed i'd need some xml ;)
Chris
Ok now i've added the cookies configuration, it won't wire up my properties to input elements any more! I get many errors like the below in my console: 13016 [http-7080-2] WARN org.apache.struts2.util.TextProviderHelper - The first TextProvider in the ValueStack (actions.jobs.Search) could not locate the message resource with key 'division'13016 [http-7080-2] WARN org.apache.struts2.util.TextProviderHelper - The default value expression 'division' evaluated to '0'
Chris
Haha, always with the XML. If you've defined as in my example, it means what's happened is that your default interceptor stack isn't being invoked anymore. See my updated code (in about 30 seconds) to see how to fix this.
Pat
Thanks a lot for the help. Ok i've put the 'defaultStack' line in and you're right, it fixes the input wiring. But the cookies seem to be a placebo - they compile, when running i use them with no logged warnings, but they simply do nothing.
Chris
Hmmm, interesting...I haven't used cookies in my Struts2 apps, but it looks like the default Cookie Interceptor is only for getting cookies into your action - it doesn't allow you to set them... I googled a bit and found this post which looks promising: http://omkarp.blogspot.com/2007/11/working-with-cookies-in-struts-2-part-3.html It outlines creating a custom cookie interceptor that allows you to add cookies to the response after processing in the action.
Pat
Yeah i found that blog too. Thanks a lot for your help, in the end i've decided that struts2's support for cookies is too dinky, and i'm simply going to use the ServletRequest/Response to get/set them respectively. I'm using it now and it works beautifully.
Chris
+1  A: 

It appears that struts only supports reading cookies, you have to go to the servlet response to actually set a cookie.

In the end, i've opted to bypass the struts2 cookie support entirely and go directly to the servlet request/response objects for both reading and writing:

public class MyAction extends ActionSupport implements ServletResponseAware, ServletRequestAware {

  public int division;

  public String execute() {

    // Load from cookie
    for(Cookie c : servletRequest.getCookies()) {
      if (c.getName().equals("cookieDivision"))
        division=Integer.parseInt(c.getValue());
    }

    // Save to cookie
    Cookie div = new Cookie("cookieDivision", String.format("%d",division));
    div.setMaxAge(60*60*24*365); // Make the cookie last a year
    servletResponse.addCookie(div);

    return "success";
  }

  // For access to the raw servlet request / response, eg for cookies
  protected HttpServletResponse servletResponse;
  @Override
  public void setServletResponse(HttpServletResponse servletResponse) {
    this.servletResponse = servletResponse;
  }

  protected HttpServletRequest servletRequest;
  @Override
  public void setServletRequest(HttpServletRequest servletRequest) {
    this.servletRequest = servletRequest;
  }
}

And there's no configuration required for this method in either struts.xml or web.xml, which is a bonus. So i'm happy with this solution, even if it does paint struts2 in a poor light.

Chris