6

i have written the next code:

public void delete(MyType instance) {
        List<MyType> myList = this.getAll();

        Cookie[] cookies = request.getCookies();
        List<Cookie> cookieList = new ArrayList<Cookie>();
        cookieList = Arrays.asList(cookies);
        for(Cookie cookie:cookieList) {
            if(Long.valueOf(cookie.getValue()) == instance.getId()) {
                cookieList.remove(cookie);
            }
        }
        myList.remove(instance);
        cookies = (Cookie[]) cookieList.toArray();
}

the issue is next: when i delete the cookie from the cookielist, how i can put the updated cookielist (without deleted cookie) back to the client? request or response don't have any *.setCookies(); methods. or cookies will update automatically? best regards.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
John Smith
  • 831
  • 5
  • 19
  • 37

1 Answers1

17

You need to set the very same cookie with a null value and a max age of 0 (and the same path, if you have set a custom one) back on the response by HttpServletResponse#addCookie().

cookie.setValue(null);
cookie.setMaxAge(0);
cookie.setPath(theSamePathAsYouUsedBeforeIfAny);
response.addCookie(cookie);

Unrelated to the concrete problem, you do not need massage the array to a list and back at all. The enhanced for loop works on arrays as good. Also, using == to compare Long values would only work for values between -128 and 127. You need equals() instead. So all in all, the method could look like this:

public void delete(MyType instance) {
    Cookie[] cookies = request.getCookies();

    if (cookies != null) {
        for (Cookie cookie : cookies) {
            if (Long.valueOf(cookie.getValue()).equals(instance.getId())) {
                cookie.setValue(null);
                cookie.setMaxAge(0);
                cookie.setPath(theSamePathAsYouUsedBeforeIfAny);
                response.addCookie(cookie);
            }
        }
    }
}

By the way, it's scary to see request and response being instance variables of some class. Are you sure that the particular class is threadsafe? To understand servlets and threadsafety, you may find this answer helpful: How do servlets work? Instantiation, sessions, shared variables and multithreading.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    @ BalusC so i don't need to call request.getCookies() method and do it via WebUtils.getCookie method? – John Smith Jun 19 '12 at 14:27
  • I have no idea what `WebUtils.getCookie` method is. Perhaps it's from a 3rd party framework I am not familiar with but which you didn't tell anything about in your question. I just assumed the standard Java EE stack as your question didn't give any indication of a 3rd party framework. – BalusC Jun 19 '12 at 14:28
  • 1
    @ BalusC, i didn't knew that feature about Long values. i'll fix it. thnx. – John Smith Jun 19 '12 at 14:30
  • Non-primitive, non-`Class>` and non-`enum` objects should **always** be compared with `equals()`. The `==` only compares object references. The `Long` (and `Integer`, `Byte`, `Short`, etc) classes cache references with a value between -128 and 127 for better `valueOf()` performance (see also the javadoc and read up the "flyweight pattern"). – BalusC Jun 19 '12 at 14:31
  • i think that's what i wanted and it's the only answer for the moment, so i'll mark it as correct. thnx a lot! :) – John Smith Jun 19 '12 at 14:40
  • @BalusC @JohnSmith If instead of using [`Long.valueOf()`](http://docs.oracle.com/javase/8/docs/api/java/lang/Long.html#valueOf-java.lang.String-), you used [`Long.parsLong()`](http://docs.oracle.com/javase/8/docs/api/java/lang/Long.html#parseLong-java.lang.String-), which returns a primitive, then you could safely do the comparison with `==`. – Asaph May 23 '15 at 14:45
  • given that the domain is also part of the cookie's identity (http://stackoverflow.com/a/891037/274677), shouldn't `Cookie#setDomain` also be used to ensure it overwrites previously set cookies? – Marcus Junius Brutus Nov 30 '16 at 21:08