ServletContextAttributeListener.attributeReplaced() method doesn't work

I have a code which must print my atomic counter every time when I change it in a servlet. But my code didn't work. I cannot figure out what's the problem. I need to print a new value of counter in listener. Is there any suggestion how can I print it?

    @WebServlet (description = "StartServlet", urlPatterns = {"/*"})
    public class StartController extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
                ((AtomicInteger) getServletContext().
                        getAttribute("ctr")).
                        incrementAndGet();
    }
}

@WebListener
public class ContextAttributeListenerImpl implements ServletContextAttributeListener {

    @Override
    public void attributeReplaced(ServletContextAttributeEvent event) {
        AtomicInteger c = (AtomicInteger) event.
                getServletContext().
                getAttribute("ctr");

        System.out.println(c); // all magic must be here
    }

    @Override
    public void attributeRemoved(ServletContextAttributeEvent event) {/*NOP*/}

    @Override
    public void attributeAdded(ServletContextAttributeEvent event) {/*NOP*/}
}

@WebListener
public class ContextCreationListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent event) {

        AtomicInteger counter = new AtomicInteger(0);
        event.getServletContext().setAttribute("ctr", counter);
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {/*NOP*/}
}
Jon Skeet
people
quotationmark

The value of the attribute isn't changing - it's the same reference throughout the context's lifetime. When you increment the counter, that isn't changing the value of the attribute... it's just changing the data within the object that the attribute value refers to.

Now you could store an Integer in the servlet context instead of an AtomicInteger, and just use synchronization to maintain the atomicity... (calling setAttribute appropriately after incrementing) would that work for you?

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
        throws ServletException, IOException {
    ServletContext context = getServletContext();
    synchronized (context) { // Or choose something else...
        Integer count = (Integer) context.getAttribute("ctr");
        context.setAttribute("ctr", count + 1);
    }
}

people

See more on this question at Stackoverflow