Search code examples
jsfscopecdicustom-scope

JSF custom scope - missing javascript


I would like to configure custom scope in JSF application. We are using JSF 2.0 with Primefaces 5.3.17 on Websphere 8.0/8.5. For now we have RequestScoped Core- and SessionScoped Model-Beans with Named annotations. Model is passed to Core via Inject. Now we need to provide a way to parallel work with models on many browser tabs. Our idea is to use filters to inject generated tab id into response and then, later on, extract it from post requests and pass it in to Extension to load/create required bean from map with beans per view with is stored in session. I suppose that filters work fine - without scope change the generated tab Id is injected in action attribute in forms etc. and there is no error.

But the problem is that when i set the new custom scope for some model bean to prove if it works. I got an exception that "jquery is not defined". For me Java part looks fine - required bean is created in context and then the same bean is used in core. But it turned out that every request which is responsible for loading js get empty response. I don't see any stacktrace and I have totally no idea why it happens, how and where can I find cause of that behavior.

Some code samples:

Context:

public class TabScopeContext implements Context, Serializable {

    /**
     * SerialId.
     */
    private static final long serialVersionUID = -558257182139134232L;

    public TabScopeContext() {}

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public <T> T get(Contextual<T> contextual) {
        final Bean<T> bean = (Bean<T>) contextual;
        Map<String, Object> beans = getBeansForCurrentTab();
        if (beans.containsKey(bean.getName())) {
            return (T) beans.get(bean.getName());
        } else {
            return null;
        }
    }

    private Map<String, Object> getBeansForCurrentTab() {
        FacesContext context = FacesContext.getCurrentInstance();
        HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
        Map<Integer, Map<String, Object>> tabScope;

        if (isTabScopeAlreadyInSession(session)) {
            tabScope = getTabScope(session);
        } else {
            tabScope = initScopeInSession(session);
        }

        Integer viewId = TabScopeViewIdPersister.getInstance().getViewId();

        if (isViewAlreadyInScope(viewId, tabScope)) {
            return tabScope.get(viewId);
        } else {
            return initBeansForView(tabScope, viewId);
        }

    }

    private Map<String, Object> initBeansForView(Map<Integer, Map<String, Object>> tabScope, Integer viewId) {
        Map<String, Object> beans = new HashMap<String, Object>();
        tabScope.put(viewId, beans);

        return beans;
    }

    private boolean isViewAlreadyInScope(Integer viewId, Map<Integer, Map<String, Object>> tabScope) {
        return tabScope.containsKey(viewId);
    }

    private Map<Integer, Map<String, Object>> initScopeInSession(HttpSession session) {
        Map<Integer, Map<String, Object>> beansPerView = new HashMap<Integer, Map<String, Object>>();
        session.setAttribute(TabScope.NAME, beansPerView);

        return beansPerView;
    }

    private boolean isTabScopeAlreadyInSession(HttpSession session) {
        return getTabScope(session) != null;
    }

    @SuppressWarnings("unchecked")
    private Map<Integer, Map<String, Object>> getTabScope(HttpSession session) {
        return (Map<Integer, Map<String, Object>>) session.getAttribute(TabScope.NAME);
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public <T> T get(Contextual<T> contextual, CreationalContext<T> creationalContext) {
        final Bean<T> bean = (Bean<T>) contextual;

        Map<String, Object> scopeBeansMap = getBeansForCurrentTab();
        if (scopeBeansMap.containsKey(bean.getName())) {
            return (T) scopeBeansMap.get(bean.getName());
        } else {
            T t = bean.create(creationalContext);
            scopeBeansMap.put(bean.getName(), t);
            return t;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Class<? extends Annotation> getScope() {
        return TabScope.class;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isActive() {
        return true;
    }

}

Extension:

public class TabScopeContextExtension implements Extension {

public void registerContext(@Observes AfterBeanDiscovery event) {
    event.addContext(new TabScopeContext());
}

}

Scope:

@NormalScope(passivating=true)
@Target({TYPE, FIELD, METHOD })
@Retention(value = RUNTIME)
@Documented
@Inherited
public @interface TabScope {

    public static final String NAME = "TAB_SCOPE";
}

Anyone have some idea how this problem can be connected with scope change and how to fix it? Thanks in advance for your help.


Solution

  • It turned out that was a problem with browser cache. After clearing the cache it seems to working.