multithreadingjsfphaselistener

How to thread-safely share an attribute between the beforePhase() and the afterPhase() methods of a PhaseListener?


I need to share an attribute between the beforePhase() and the afterPhase() methods of my PhaseListener, for a same JSF request.

Is the following snippet thread-safe?

public class MyPhaseListener implements PhaseListener {

  private MyObject o = null;

  @Override
  public void beforePhase(PhaseEvent event) {
    if (condition) {
      o = new MyObject();
    }
  }

  @Override
  public void afterPhase(PhaseEvent event) {
    if (o != null) {
      o.process();
      o = null;
    }
  }

  @Override
  public PhaseId getPhaseId() {
    return PhaseId.RESTORE_VIEW;
  }

}

If not, what are other solutions?


Solution

  • This is definitely not threadsafe. There's only one phase listener instance applicationwide which is shared across multiple requests. Basically, a phase listener is like an @ApplicationScoped managed bean.

    Just set it as a context attribute.

    public class MyPhaseListener implements PhaseListener {
    
      @Override
      public void beforePhase(PhaseEvent event) {
        if (condition) {
          event.getFacesContext().setAttribute("o", new MyObject());
        }
      }
    
      @Override
      public void afterPhase(PhaseEvent event) {
        MyObject o = (MyObject) event.getFacesContext().getAttribute("o");
        if (o != null) {
          o.process();
        }
      }
    
      @Override
      public PhaseId getPhaseId() {
        return PhaseId.RESTORE_VIEW;
      }
    
    }