Question

Ajax call performed in order to remove item from shopping cart - removeOrder() method is called

UI removeOrder() call(JSF&Primefaces):

<p:commandButton value="clean" actionListener="#{showProducts.removeOrder}"
   process="@form" update="@form,:ccId:cCart:ccSizeId,:ccId:cCart:ccTotId" immediate="true">
<f:attribute name="remove" value="#{cart.name}"/>
</p:commandButton>

Backend removeOrder() call(managed bean)

public void removeOrder(ActionEvent e) {
        String productName = (String) e.getComponent().getAttributes().get("remove");
        Product p = getProductByName(productName);
        inCart.remove(p);
        persistCookies();
        emptyCartNotifier();
        totalRendered();
    }

Here cookies is persisted,output of this method as is expected,Cookie array contains cookies with empty values,that's OK:

private void persistCookies() {
    HttpServletResponse httpServletResponse = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();

    String ids = "";

    for (Product prod : inCart) {
        // TODO change logic to support real count,for now 1 is available only
        ids += prod.getId() + ";" + prod.getCount() + "_";
    }

    Cookie cookie = new Cookie(SC_COOKIE, ids);
    Cookie cookie2 = new Cookie(SC_SIZE, String.valueOf(inCart.size()));
    Cookie cookie3 = new Cookie(SC_TOTAL_PRICE, String.valueOf(subTotal));
    cookie3.setPath("/");
    cookie3.setMaxAge(TWO_WEEKS);
    httpServletResponse.addCookie(cookie3);
    cookie.setPath("/");
    cookie.setMaxAge(TWO_WEEKS);
    cookie2.setPath("/");
    cookie2.setMaxAge(TWO_WEEKS);

    httpServletResponse.addCookie(cookie);
    httpServletResponse.addCookie(cookie2);

}

Here problem occurred, the method emptyCartNotifier() see non-empty "previous" Cookies array

private String emptyCartNotifier() {

    HttpServletRequest httpServletRequest = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
    Cookie[] cookies = httpServletRequest.getCookies();
    boolean isCookiePresent = false;
    if (cookies != null) {
        for (Cookie c : cookies) {
            if (SC_COOKIE.equals(c.getName()) && (!c.getValue().isEmpty())) {
                isCookiePresent = true;
            }
        }
    }
    if (inCart.isEmpty() && (!isCookiePresent)) {
        emptyCartNotifier = "you cart is empty";
        isFormRendered = false;
    } else {
        emptyCartNotifier = "";
        isFormRendered = true;
    }
    return emptyCartNotifier;
}

After any HTTP request performed, that Cookie array is really cleaned up.

As I see , clash is:
after AJAX call cleans cookie, that HttpServletRequest contains non-empty cookie until new HTTP request performed(user submit button or go by link).

Is there solution or good practice for immediate cookie management,when web-app combines AJAX and non-AJAX calls?

Thank you.

Was it helpful?

Solution

Wait, what? In emptyCartNotifier, You are calling getCookies on the HttpRequest object, which is supposed to contain the cookies that were in the HTTP request that triggered your method, so of course you don't see changes until the next request.

OTHER TIPS

Your cookie problem is one thing, but I think there is a much easier way to get things done.

In your page, just replace the pages you mention with this:

<p:commandButton value="clean" action="#{showProducts.removeOrder(cart)}"
   process="@form" update="@form,:ccId:cCart:ccSizeId,:ccId:cCart:ccTotId" immediate="true" />

Backing bean (e.g. session scoped):

private double subtotal; // don't forget getter and setter

public void removeOrder(Product product) {
        inCart.remove(product);
        // calculate subtotal
}

I guess you show the subtotal and maybe list all products after calling removeOrder. Just recalculate subtotal after removing the product, and make sure the shopping cart is refreshed (update attribute).

This code is simple enough and easy to understand, and yet does everything you need. No need to "manually" manage cookies.

You could try setting your cookies setHttpOnly(true), but the question is why would you need "ajax-scoped" cookie persistence at all?

Why not use local variables in your view/request/session scoped beans? They're actually designed for that sort of tasks. If you want additional cookie persistence you do it in corresponding setters or action methods.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top