Using cookies with Struts 2 and Struts
Asked Answered
H

4

11

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

Haugh answered 28/7, 2010 at 6:57 Comment(4)
Or am i going against the grain here - should i really be using sessions instead? Are sessions the more 'blessed' way of doing things in struts2?Haugh
I'm going to check this out: omkarp.blogspot.com/2007/08/…Haugh
It looks to me that using the 'map' approach isn't very good for reading cookies - because you have to specify the cookies you want (or all) in the interceptor-ref, but it still tries to inject them into setters anyway, crashing if it cannot find any setters!Haugh
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.Haugh
H
10

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.

Haugh answered 29/7, 2010 at 3:4 Comment(2)
Does that mean you need to implement Response and request interfaces on every action that need to use cookies ? then if you need to call this class from another class, you need to pass the first class's response, request objects to this one am I right?Sylphid
would you please have a look at this question #17780156Sylphid
W
5

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>
Wun answered 28/7, 2010 at 11:40 Comment(6)
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 ;)Haugh
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'Haugh
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.Wun
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.Haugh
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: omkarp.blogspot.com/2007/11/… It outlines creating a custom cookie interceptor that allows you to add cookies to the response after processing in the action.Wun
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.Haugh
C
2

While I'm aware that the question is now more than 3 years old, today I needed to set a cookie with Struts2, landed here, and managed to set cookies in a Struts2-y way (using 2.3.16). Hope this will help some others.

In order to set cookies with Struts2, you need to follow these steps:

  1. Have your Action implement org.apache.struts2.interceptor.CookieProvider. (You might want to see its javadoc)
  2. Implement the Set<Cookie> getCookies(); method, returning all the cookies you want to set.
  3. Make your Action use the cookieProvider interceptor the same way as @Pat mentioned in his answer.
<action name="MyAction" class="your.fancy.app.MyAction">
    <interceptor-ref name="defaultStack"/>
    <interceptor-ref name="cookieProvider"/>
    <result>/index.jsp</result>
</action>

If you set a domain for a cookie, when you test this setup make sure you're requesting a URL under that domain. In my case, I didn't realize I was accessing my test machine directly instead of going through the domain, and the cookie wasn't being set.

Caftan answered 11/2, 2014 at 10:33 Comment(0)
T
0

Following article has more details on how to use cookie aware interface http://www.journaldev.com/2203/how-to-get-servlet-session-request-response-context-attributes-in-struts-2-action

Thylacine answered 1/11, 2014 at 19:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.