I'm working (mostly) with @ViewScoped @Named Faces beans (javax.faces.view.ViewScoped
and javax.inject.Named
) and would like to know if from the ServletRequest (or HttpServletRequest) I can differentiate between two different instantiations of the same bean within a javax.servlet.Filter
For example, a user opens the same page in two different tabs, but both of these have the same SessionID via the call httpRequest.getSession().getId()
. Currently this is not helpful to me.
Alternatively I have access to the Thread ID, but this changes with each ajax call, and I need to keep around something unique for just the instance of the backing bean across all calls.. until the bean is destroyed.
So, something like this (this doesn't work, but hopefully illustrates my need)
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
try
{
HttpServletRequest httpRequest = (HttpServletRequest) request;
// not real code, but this is what I'm looking for;
// get a unique identifier for just this instance of the bean that stays the same across all ajax requests
String beanId = request.getCurrentBackingBean.getInstanceId();
...
As @BalusC mentioned in a comment, a servlet filter may not be the most optimal place to solve this, but I'm working with existing code that may not allow refactoring.
His other comments have led me to this solution:
In the Filter: using the HttpServletRequest
, get the parameter "javax.faces.ViewState". This contains a unique id for the view of my (ViewScoped) backing bean that lives across Ajax requests. It will create a new unique id for each new instantiation of the backing bean.
Note that it does not seem to be available in the first call to the filter, I assume because the @PostConstruct has not yet been called on the new backing bean. My initial attempts to solve this was to pull it out of the FacesContext (in the @PostConstruct) with the calls:
String viewState = FacesContext.getCurrentInstance().getApplication().getStateManager().getViewState(FacesContext.getCurrentInstance());
ThreadContext.put("viewState", viewState);
and although this appears to get the viewState, it seems to break up the lifecycle somehow, and my page does not render. I wonder if it is not possible to 'grab' the viewState until after the page is rendered?
For now, the working code in the Filter
now looks like this (truncated):
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
try
{
HttpServletRequest httpRequest = (HttpServletRequest) request;
String viewState = httpRequest.getParameter("javax.faces.ViewState");
...
ThreadContext.put("viewState", viewState);
...