You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ta...@apache.org on 2021/03/16 09:39:41 UTC
[myfaces] branch master updated: refactored flows
This is an automated email from the ASF dual-hosted git repository.
tandraschko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces.git
The following commit(s) were added to refs/heads/master by this push:
new 6f5599a refactored flows
6f5599a is described below
commit 6f5599a219ae1f19d6a6ba7a8a9dc566b0bff1a4
Author: Thomas Andraschko <ta...@apache.org>
AuthorDate: Tue Mar 16 10:39:32 2021 +0100
refactored flows
---
.../viewstate/StateCacheServerSide.java | 2 +-
.../apache/myfaces/cdi/JsfArtifactProducer.java | 373 +++++++++++----------
.../cdi/clientwindow/ClientWindowScopeContext.java | 17 +-
.../ClientWindowScopeContextualStorageHolder.java | 10 +
.../myfaces/cdi/model/FacesDataModelManager.java | 2 +-
.../cdi/util/AbstractContextualStorageHolder.java | 37 +-
.../java/org/apache/myfaces/cdi/util/CDIUtils.java | 6 +
.../apache/myfaces/cdi/view/ViewScopeCDIMap.java | 4 +-
.../apache/myfaces/cdi/view/ViewScopeContext.java | 19 +-
.../cdi/view/ViewScopeContextualStorageHolder.java | 10 +
.../cdi/wrapper/FacesBehaviorCDIWrapper.java | 3 +-
.../cdi/wrapper/FacesClientBehaviorCDIWrapper.java | 3 +-
.../cdi/wrapper/FacesConverterCDIWrapper.java | 2 +-
.../cdi/wrapper/FacesValidatorCDIWrapper.java | 2 +-
.../myfaces/el/DefaultELResolverBuilder.java | 3 +-
.../org/apache/myfaces/el/ELResolverBuilder.java | 2 +-
.../flow/cdi/DefaultCDIFacesFlowProvider.java | 81 +----
.../flow/cdi/FacesFlowClientWindowCollection.java | 70 ----
.../myfaces/flow/cdi/FlowBuilderExtension.java | 47 ---
.../myfaces/flow/cdi/FlowBuilderFactoryBean.java | 46 ---
.../myfaces/flow/cdi/FlowScopeBeanHolder.java | 334 ------------------
.../apache/myfaces/flow/cdi/FlowScopeContext.java | 167 +++------
.../flow/cdi/FlowScopeContextualStorageHolder.java | 215 ++++++++++++
.../myfaces/flow/cdi/FlowScopeExtension.java | 6 +-
.../org/apache/myfaces/flow/cdi/FlowScopeMap.java | 20 +-
.../flow/impl/DefaultFacesFlowProvider.java | 6 -
.../myfaces/push/WebsocketComponentRenderer.java | 6 +-
.../myfaces/push/cdi/PushContextCDIExtension.java | 4 -
.../myfaces/push/cdi/PushContextFactoryBean.java | 44 ---
.../apache/myfaces/push/cdi/PushContextImpl.java | 4 +-
.../org/apache/myfaces/spi/FacesFlowProvider.java | 2 -
.../org/apache/myfaces/view/ViewScopeProxyMap.java | 2 +-
.../myfaces/webapp/AbstractFacesInitializer.java | 13 -
.../myfaces/webapp/MyFacesHttpSessionListener.java | 21 +-
.../jakarta.enterprise.inject.spi.Extension | 1 -
35 files changed, 572 insertions(+), 1012 deletions(-)
diff --git a/impl/src/main/java/org/apache/myfaces/application/viewstate/StateCacheServerSide.java b/impl/src/main/java/org/apache/myfaces/application/viewstate/StateCacheServerSide.java
index df6f771..93fa65b 100644
--- a/impl/src/main/java/org/apache/myfaces/application/viewstate/StateCacheServerSide.java
+++ b/impl/src/main/java/org/apache/myfaces/application/viewstate/StateCacheServerSide.java
@@ -72,7 +72,7 @@ class StateCacheServerSide extends StateCache<Object, Object>
private final int numberOfSequentialViewsInSession;
private final boolean serializeStateInSession;
private final boolean compressStateInSession;
-
+
private final SessionViewStorageFactory sessionViewStorageFactory;
private final CsrfSessionTokenFactory csrfSessionTokenFactory;
private final StateTokenProcessor stateTokenProcessor;
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/JsfArtifactProducer.java b/impl/src/main/java/org/apache/myfaces/cdi/JsfArtifactProducer.java
index 50f3ee6..5f25cfa 100644
--- a/impl/src/main/java/org/apache/myfaces/cdi/JsfArtifactProducer.java
+++ b/impl/src/main/java/org/apache/myfaces/cdi/JsfArtifactProducer.java
@@ -21,6 +21,7 @@ package org.apache.myfaces.cdi;
import java.util.Map;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
+import jakarta.enterprise.inject.spi.InjectionPoint;
import jakarta.faces.annotation.ApplicationMap;
import jakarta.faces.annotation.HeaderMap;
import jakarta.faces.annotation.HeaderValuesMap;
@@ -37,188 +38,210 @@ import jakarta.faces.component.UIViewRoot;
import jakarta.faces.context.ExternalContext;
import jakarta.faces.context.FacesContext;
import jakarta.faces.context.Flash;
+import jakarta.faces.flow.builder.FlowBuilder;
+import jakarta.faces.flow.builder.FlowBuilderParameter;
import jakarta.faces.lifecycle.ClientWindow;
+import jakarta.faces.push.Push;
+import jakarta.faces.push.PushContext;
import jakarta.inject.Named;
import org.apache.myfaces.cdi.view.ViewTransientScoped;
+import org.apache.myfaces.flow.builder.FlowBuilderImpl;
+import org.apache.myfaces.push.cdi.PushContextImpl;
@ApplicationScoped
public class JsfArtifactProducer
{
- @Produces
- @Named("application")
- @ApplicationScoped
- public Application getApplication()
- {
- return FacesContext.getCurrentInstance().getApplication();
- }
-
- @Produces
- @Named("applicationScope")
- @ApplicationMap
- @ApplicationScoped
- public Map<String, Object> getApplicationMap()
- {
- return FacesContext.getCurrentInstance().getExternalContext().getApplicationMap();
- }
-
- @Produces
- @Named("initParam")
- @InitParameterMap
- @ApplicationScoped
- public Map<String, String> getInitParameterMap()
- {
- return FacesContext.getCurrentInstance().getExternalContext().getInitParameterMap();
- }
+ @Produces
+ @Named("application")
+ @ApplicationScoped
+ public Application getApplication()
+ {
+ return FacesContext.getCurrentInstance().getApplication();
+ }
+
+ @Produces
+ @Named("applicationScope")
+ @ApplicationMap
+ @ApplicationScoped
+ public Map<String, Object> getApplicationMap()
+ {
+ return FacesContext.getCurrentInstance().getExternalContext().getApplicationMap();
+ }
+
+ @Produces
+ @Named("initParam")
+ @InitParameterMap
+ @ApplicationScoped
+ public Map<String, String> getInitParameterMap()
+ {
+ return FacesContext.getCurrentInstance().getExternalContext().getInitParameterMap();
+ }
+
+ @Produces
+ @Named("resource")
+ @ApplicationScoped
+ public ResourceHandler getResourceHandler()
+ {
+ return FacesContext.getCurrentInstance().getApplication().getResourceHandler();
+ }
+
+ @Produces
+ @Named("facesContext")
+ @FacesScoped
+ public FacesContext getFacesContext()
+ {
+ return FacesContext.getCurrentInstance();
+ }
+
+ @Produces
+ @Named("externalContext")
+ @FacesScoped
+ public ExternalContext getExternalContext()
+ {
+ return FacesContext.getCurrentInstance().getExternalContext();
+ }
+
+ @Produces
+ @Named("flash")
+ @FacesScoped
+ public Flash getFlash()
+ {
+ return FacesContext.getCurrentInstance().getExternalContext().getFlash();
+ }
+
+ @Produces
+ @Named("header")
+ @HeaderMap
+ @FacesScoped
+ public Map<String, String> getHeaderMap()
+ {
+ return FacesContext.getCurrentInstance().getExternalContext().getRequestHeaderMap();
+ }
+
+ @Produces
+ @Named("headerValues")
+ @HeaderValuesMap
+ @FacesScoped
+ public Map<String, String[]> getHeaderValuesMap()
+ {
+ return FacesContext.getCurrentInstance().getExternalContext().getRequestHeaderValuesMap();
+ }
+
+ @Produces
+ @Named("requestScope")
+ @RequestMap
+ @FacesScoped
+ public Map<String, Object> getRequestMap()
+ {
+ return FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
+ }
+
+ @Produces
+ @Named("cookie")
+ @RequestCookieMap
+ @FacesScoped
+ public Map<String, Object> getRequestCookieMap()
+ {
+ return FacesContext.getCurrentInstance().getExternalContext().getRequestCookieMap();
+ }
+
+ @Produces
+ @Named("param")
+ @RequestParameterMap
+ @FacesScoped
+ public Map<String, String> getRequestParameterMap()
+ {
+ return FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
+ }
+
+ @Produces
+ @Named("paramValues")
+ @RequestParameterValuesMap
+ @FacesScoped
+ public Map<String, String[]> getRequestParameterValuesMap()
+ {
+ return FacesContext.getCurrentInstance().getExternalContext().getRequestParameterValuesMap();
+ }
+
+ @Produces
+ @Named("sessionScope")
+ @SessionMap
+ @FacesScoped
+ public Map<String, Object> getSessionMap()
+ {
+ return FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
+ }
+
+ @Produces
+ @Named("view")
+ @FacesScoped
+ public UIViewRoot getViewRoot()
+ {
+ return FacesContext.getCurrentInstance().getViewRoot();
+ }
+
+ @Produces
+ @Named("session")
+ @FacesScoped
+ public Object getSession()
+ {
+ return FacesContext.getCurrentInstance().getExternalContext().getSession(false);
+ }
+
- @Produces
- @Named("resource")
- @ApplicationScoped
- public ResourceHandler getResourceHandler()
- {
- return FacesContext.getCurrentInstance().getApplication().getResourceHandler();
- }
+ /*
+ The spec actually forces us the use producers for "cc" and "component but it leads to a bad performance.
+ Also @Inject UIComponent doesn't make sense and wouldn't work correctly if we don't create a own "ComponentScoped"
+ or something.
+ We will still use ELResolvers for this - see ImplicitObjectResolver#makeResolverForFacesCDI().
+
+ @Produces
+ @Named("component")
+ @Dependent
+ public UIComponent getComponent()
+ {
+ return UIComponent.getCurrentComponent(FacesContext.getCurrentInstance());
+ }
+
+ @Produces
+ @Named("cc")
+ @Dependent
+ public UIComponent getCompositeComponent()
+ {
+ return UIComponent.getCurrentCompositeComponent(FacesContext.getCurrentInstance());
+ }
+ */
+
+ @Produces
+ @Named("viewScope")
+ @ViewMap
+ @ViewTransientScoped
+ public Map<String, Object> getViewMap()
+ {
+ return FacesContext.getCurrentInstance().getViewRoot().getViewMap();
+ }
+
+ @Produces
+ @Named("clientWindow")
+ @FacesScoped
+ public ClientWindow getClientWindow()
+ {
+ return FacesContext.getCurrentInstance().getExternalContext().getClientWindow();
+ }
+
+ @Produces
+ @FlowBuilderParameter
+ public FlowBuilder getFlowBuilderInstance()
+ {
+ return new FlowBuilderImpl();
+ }
- @Produces
- @Named("facesContext")
- @FacesScoped
- public FacesContext getFacesContext()
- {
- return FacesContext.getCurrentInstance();
- }
-
- @Produces
- @Named("externalContext")
- @FacesScoped
- public ExternalContext getExternalContext()
- {
- return FacesContext.getCurrentInstance().getExternalContext();
- }
-
- @Produces
- @Named("flash")
- @FacesScoped
- public Flash getFlash()
- {
- return FacesContext.getCurrentInstance().getExternalContext().getFlash();
- }
-
- @Produces
- @Named("header")
- @HeaderMap
- @FacesScoped
- public Map<String, String> getHeaderMap()
- {
- return FacesContext.getCurrentInstance().getExternalContext().getRequestHeaderMap();
- }
-
- @Produces
- @Named("headerValues")
- @HeaderValuesMap
- @FacesScoped
- public Map<String, String[]> getHeaderValuesMap()
- {
- return FacesContext.getCurrentInstance().getExternalContext().getRequestHeaderValuesMap();
- }
-
- @Produces
- @Named("requestScope")
- @RequestMap
- @FacesScoped
- public Map<String, Object> getRequestMap()
- {
- return FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
- }
-
- @Produces
- @Named("cookie")
- @RequestCookieMap
- @FacesScoped
- public Map<String, Object> getRequestCookieMap()
- {
- return FacesContext.getCurrentInstance().getExternalContext().getRequestCookieMap();
- }
-
- @Produces
- @Named("param")
- @RequestParameterMap
- @FacesScoped
- public Map<String, String> getRequestParameterMap()
- {
- return FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
- }
-
- @Produces
- @Named("paramValues")
- @RequestParameterValuesMap
- @FacesScoped
- public Map<String, String[]> getRequestParameterValuesMap()
- {
- return FacesContext.getCurrentInstance().getExternalContext().getRequestParameterValuesMap();
- }
-
- @Produces
- @Named("sessionScope")
- @SessionMap
- @FacesScoped
- public Map<String, Object> getSessionMap()
- {
- return FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
- }
-
- @Produces
- @Named("view")
- @FacesScoped
- public UIViewRoot getViewRoot()
- {
- return FacesContext.getCurrentInstance().getViewRoot();
- }
-
- @Produces
- @Named("session")
- @FacesScoped
- public Object getSession()
- {
- return FacesContext.getCurrentInstance().getExternalContext().getSession(false);
- }
-
-
- /*
- The spec actually forces us the use producers for "cc" and "component but it leads to a bad performance.
- Also @Inject UIComponent doesn't make sense and wouldn't work correctly if we don't create a own "ComponentScoped"
- or something.
- We will still use ELResolvers for this - see ImplicitObjectResolver#makeResolverForFacesCDI().
-
- @Produces
- @Named("component")
- @Dependent
- public UIComponent getComponent()
- {
- return UIComponent.getCurrentComponent(FacesContext.getCurrentInstance());
- }
-
- @Produces
- @Named("cc")
- @Dependent
- public UIComponent getCompositeComponent()
- {
- return UIComponent.getCurrentCompositeComponent(FacesContext.getCurrentInstance());
- }
- */
-
- @Produces
- @Named("viewScope")
- @ViewMap
- @ViewTransientScoped
- public Map<String, Object> getViewMap()
- {
- return FacesContext.getCurrentInstance().getViewRoot().getViewMap();
- }
-
- @Produces
- @Named("clientWindow")
- @FacesScoped
- public ClientWindow getClientWindow()
- {
- return FacesContext.getCurrentInstance().getExternalContext().getClientWindow();
- }
+ @Produces
+ @Push
+ public PushContext getPushContext(InjectionPoint ip)
+ {
+ Push push = ip.getAnnotated().getAnnotation(Push.class);
+ String channel = push.channel().isEmpty() ? ip.getMember().getName() : push.channel();
+ return new PushContextImpl(channel);
+ }
}
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/clientwindow/ClientWindowScopeContext.java b/impl/src/main/java/org/apache/myfaces/cdi/clientwindow/ClientWindowScopeContext.java
index 8bb9d15..8ad992c 100644
--- a/impl/src/main/java/org/apache/myfaces/cdi/clientwindow/ClientWindowScopeContext.java
+++ b/impl/src/main/java/org/apache/myfaces/cdi/clientwindow/ClientWindowScopeContext.java
@@ -30,7 +30,6 @@ import jakarta.faces.context.FacesContext;
import jakarta.faces.lifecycle.ClientWindowScoped;
import org.apache.myfaces.cdi.util.ContextualInstanceInfo;
import org.apache.myfaces.cdi.util.ContextualStorage;
-import org.apache.myfaces.cdi.util.AbstractContextualStorageHolder;
/**
* Minimal implementation of ClientWindowScope.
@@ -76,7 +75,7 @@ public class ClientWindowScopeContext implements Context
if (facesContext != null)
{
- ContextualStorage storage = getContextManager(facesContext).getContextualStorage(
+ ContextualStorage storage = getStorageHolder(facesContext).getContextualStorage(
getCurrentClientWindowId(facesContext), false);
if (storage != null)
{
@@ -103,7 +102,7 @@ public class ClientWindowScopeContext implements Context
checkActive(facesContext);
- ContextualStorage storage = getContextManager(facesContext).getContextualStorage(
+ ContextualStorage storage = getStorageHolder(facesContext).getContextualStorage(
getCurrentClientWindowId(facesContext), true);
Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
@@ -132,9 +131,9 @@ public class ClientWindowScopeContext implements Context
}
}
- protected ClientWindowScopeContextualStorageHolder getContextManager(FacesContext context)
+ protected ClientWindowScopeContextualStorageHolder getStorageHolder(FacesContext context)
{
- return AbstractContextualStorageHolder.getInstance(context, ClientWindowScopeContextualStorageHolder.class);
+ return ClientWindowScopeContextualStorageHolder.getInstance(context, true);
}
protected String getCurrentClientWindowId(FacesContext context)
@@ -145,8 +144,8 @@ public class ClientWindowScopeContext implements Context
public static void destroyAll(FacesContext facesContext)
{
- ClientWindowScopeContextualStorageHolder manager = AbstractContextualStorageHolder.getInstance(facesContext,
- ClientWindowScopeContextualStorageHolder.class);
+ ClientWindowScopeContextualStorageHolder manager =
+ ClientWindowScopeContextualStorageHolder.getInstance(facesContext);
if (manager != null)
{
manager.destroyAll(facesContext);
@@ -155,8 +154,8 @@ public class ClientWindowScopeContext implements Context
public static void destroyAll(FacesContext context, String clientWindowId)
{
- ClientWindowScopeContextualStorageHolder manager = AbstractContextualStorageHolder.getInstance(context,
- ClientWindowScopeContextualStorageHolder.class);
+ ClientWindowScopeContextualStorageHolder manager = ClientWindowScopeContextualStorageHolder
+ .getInstance(context);
if (manager != null)
{
manager.destroyAll(context, clientWindowId);
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/clientwindow/ClientWindowScopeContextualStorageHolder.java b/impl/src/main/java/org/apache/myfaces/cdi/clientwindow/ClientWindowScopeContextualStorageHolder.java
index a12a323..ce4b812 100644
--- a/impl/src/main/java/org/apache/myfaces/cdi/clientwindow/ClientWindowScopeContextualStorageHolder.java
+++ b/impl/src/main/java/org/apache/myfaces/cdi/clientwindow/ClientWindowScopeContextualStorageHolder.java
@@ -56,4 +56,14 @@ public class ClientWindowScopeContextualStorageHolder
{
return new ContextualStorage(beanManager, true);
}
+
+ protected static ClientWindowScopeContextualStorageHolder getInstance(FacesContext facesContext)
+ {
+ return getInstance(facesContext, false);
+ }
+
+ protected static ClientWindowScopeContextualStorageHolder getInstance(FacesContext facesContext, boolean create)
+ {
+ return getInstance(facesContext, ClientWindowScopeContextualStorageHolder.class, create);
+ }
}
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/model/FacesDataModelManager.java b/impl/src/main/java/org/apache/myfaces/cdi/model/FacesDataModelManager.java
index d6e88d6..9b9bae3 100644
--- a/impl/src/main/java/org/apache/myfaces/cdi/model/FacesDataModelManager.java
+++ b/impl/src/main/java/org/apache/myfaces/cdi/model/FacesDataModelManager.java
@@ -163,7 +163,7 @@ public class FacesDataModelManager
public static DataModel createDataModel(FacesContext facesContext, Class<?> forClass, Object value)
{
- BeanManager beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext());
+ BeanManager beanManager = CDIUtils.getBeanManager(facesContext);
FacesDataModelManager facesDataModelManager = CDIUtils.get(beanManager, FacesDataModelManager.class);
return facesDataModelManager.tryToCreateDataModel(facesContext, forClass, value);
}
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/util/AbstractContextualStorageHolder.java b/impl/src/main/java/org/apache/myfaces/cdi/util/AbstractContextualStorageHolder.java
index 88a6155..172303a 100644
--- a/impl/src/main/java/org/apache/myfaces/cdi/util/AbstractContextualStorageHolder.java
+++ b/impl/src/main/java/org/apache/myfaces/cdi/util/AbstractContextualStorageHolder.java
@@ -202,11 +202,15 @@ public abstract class AbstractContextualStorageHolder<T extends ContextualStorag
for (Map.Entry<Object, ContextualInstanceInfo<?>> entry : contextMap.entrySet())
{
- Contextual bean = contextualStorage.getBean(entry.getKey());
+ boolean skip = isSkipDestroy(entry);
+ if (!skip)
+ {
+ Contextual bean = contextualStorage.getBean(entry.getKey());
- ContextualInstanceInfo<?> contextualInstanceInfo = entry.getValue();
- bean.destroy(contextualInstanceInfo.getContextualInstance(),
- contextualInstanceInfo.getCreationalContext());
+ ContextualInstanceInfo<?> contextualInstanceInfo = entry.getValue();
+ bean.destroy(contextualInstanceInfo.getContextualInstance(),
+ contextualInstanceInfo.getCreationalContext());
+ }
}
contextMap.clear();
@@ -221,6 +225,11 @@ public abstract class AbstractContextualStorageHolder<T extends ContextualStorag
}
}
}
+
+ protected boolean isSkipDestroy(Map.Entry<Object, ContextualInstanceInfo<?>> entry)
+ {
+ return false;
+ }
public void destroyAll(FacesContext context, String slotId)
{
@@ -233,9 +242,15 @@ public abstract class AbstractContextualStorageHolder<T extends ContextualStorag
destroyAll(contextualStorage, context);
}
- public static <T extends AbstractContextualStorageHolder> T getInstance(FacesContext facesContext,
+ protected static <T extends AbstractContextualStorageHolder> T getInstance(FacesContext facesContext,
Class<T> contextManagerClass)
{
+ return getInstance(facesContext, contextManagerClass, false);
+ }
+
+ protected static <T extends AbstractContextualStorageHolder> T getInstance(FacesContext facesContext,
+ Class<T> contextManagerClass, boolean create)
+ {
if (facesContext == null
|| facesContext.getExternalContext() == null
|| facesContext.getExternalContext().getSession(false) == null)
@@ -243,7 +258,7 @@ public abstract class AbstractContextualStorageHolder<T extends ContextualStorag
return null;
}
- BeanManager beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext());
+ BeanManager beanManager = CDIUtils.getBeanManager(facesContext);
if (beanManager == null)
{
return null;
@@ -257,7 +272,14 @@ public abstract class AbstractContextualStorageHolder<T extends ContextualStorag
T cached = (T) facesContext.getExternalContext().getSessionMap().get(contextManagerClass.getClass().getName());
if (cached == null)
{
- cached = CDIUtils.getOptional(beanManager, contextManagerClass);
+ if (create)
+ {
+ cached = CDIUtils.get(beanManager, contextManagerClass);
+ }
+ else
+ {
+ cached = CDIUtils.getOptional(beanManager, contextManagerClass);
+ }
if (cached != null)
{
facesContext.getExternalContext().getSessionMap().put(contextManagerClass.getClass().getName(),
@@ -267,4 +289,5 @@ public abstract class AbstractContextualStorageHolder<T extends ContextualStorag
return cached;
}
+
}
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/util/CDIUtils.java b/impl/src/main/java/org/apache/myfaces/cdi/util/CDIUtils.java
index 9c559c8..a3b3e3c 100644
--- a/impl/src/main/java/org/apache/myfaces/cdi/util/CDIUtils.java
+++ b/impl/src/main/java/org/apache/myfaces/cdi/util/CDIUtils.java
@@ -30,6 +30,7 @@ import jakarta.enterprise.context.spi.CreationalContext;
import jakarta.enterprise.inject.spi.Bean;
import jakarta.enterprise.inject.spi.BeanManager;
import jakarta.faces.context.ExternalContext;
+import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import org.apache.myfaces.webapp.AbstractFacesInitializer;
@@ -38,6 +39,11 @@ import org.apache.myfaces.webapp.AbstractFacesInitializer;
*/
public class CDIUtils
{
+ public static BeanManager getBeanManager(FacesContext facesContext)
+ {
+ return getBeanManager(facesContext.getExternalContext());
+ }
+
public static BeanManager getBeanManager(ExternalContext externalContext)
{
return (BeanManager) externalContext.getApplicationMap().get(
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeCDIMap.java b/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeCDIMap.java
index e3874f1..50ee7d8 100644
--- a/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeCDIMap.java
+++ b/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeCDIMap.java
@@ -40,7 +40,7 @@ public class ViewScopeCDIMap implements Map<String, Object>
public ViewScopeCDIMap(FacesContext facesContext)
{
- BeanManager beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext());
+ BeanManager beanManager = CDIUtils.getBeanManager(facesContext);
ViewScopeContextualStorageHolder bean = CDIUtils.get(beanManager, ViewScopeContextualStorageHolder.class);
viewScopeId = bean.generateUniqueViewScopeId();
}
@@ -59,7 +59,7 @@ public class ViewScopeCDIMap implements Map<String, Object>
if (storage == null)
{
FacesContext facesContext = FacesContext.getCurrentInstance();
- BeanManager beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext());
+ BeanManager beanManager = CDIUtils.getBeanManager(facesContext);
ViewScopeContextualStorageHolder bean = CDIUtils.get(beanManager, ViewScopeContextualStorageHolder.class);
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeContext.java b/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeContext.java
index e5826eb..c2ddfa0 100644
--- a/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeContext.java
+++ b/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeContext.java
@@ -32,7 +32,6 @@ import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import org.apache.myfaces.cdi.util.ContextualInstanceInfo;
-import org.apache.myfaces.cdi.util.AbstractContextualStorageHolder;
import org.apache.myfaces.view.ViewScopeProxyMap;
/**
@@ -57,15 +56,9 @@ public class ViewScopeContext implements Context
this.passivatingScope = beanManager.isPassivatingScope(getScope());
}
- protected ViewScopeContextualStorageHolder getContextManager(FacesContext facesContext)
+ protected ViewScopeContextualStorageHolder getStorageHolder(FacesContext facesContext)
{
- return AbstractContextualStorageHolder.getInstance(facesContext, ViewScopeContextualStorageHolder.class);
- }
-
- protected static ViewScopeContextualStorageHolder getViewScopeBeanHolder(FacesContext facesContext)
- {
- return (ViewScopeContextualStorageHolder) facesContext.getExternalContext().getSessionMap()
- .get(ViewScopeContextualStorageHolder.class.getName());
+ return ViewScopeContextualStorageHolder.getInstance(facesContext, true);
}
public String getCurrentViewScopeId(boolean create)
@@ -96,7 +89,7 @@ public class ViewScopeContext implements Context
}
if (viewScopeId != null)
{
- return getContextManager(facesContext).getContextualStorage(viewScopeId, createIfNotExist);
+ return getStorageHolder(facesContext).getContextualStorage(viewScopeId, createIfNotExist);
}
return null;
}
@@ -194,8 +187,7 @@ public class ViewScopeContext implements Context
public static void destroyAll(FacesContext facesContext)
{
- ViewScopeContextualStorageHolder manager = AbstractContextualStorageHolder.getInstance(facesContext,
- ViewScopeContextualStorageHolder.class);
+ ViewScopeContextualStorageHolder manager = ViewScopeContextualStorageHolder.getInstance(facesContext);
if (manager != null)
{
manager.destroyAll(facesContext);
@@ -204,8 +196,7 @@ public class ViewScopeContext implements Context
public static void destroyAll(FacesContext facesContext, String viewScopeId)
{
- ViewScopeContextualStorageHolder manager = AbstractContextualStorageHolder.getInstance(facesContext,
- ViewScopeContextualStorageHolder.class);
+ ViewScopeContextualStorageHolder manager = ViewScopeContextualStorageHolder.getInstance(facesContext);
if (manager != null)
{
manager.destroyAll(facesContext, viewScopeId);
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeContextualStorageHolder.java b/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeContextualStorageHolder.java
index abe80b9..a50cc63 100644
--- a/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeContextualStorageHolder.java
+++ b/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeContextualStorageHolder.java
@@ -21,6 +21,7 @@ package org.apache.myfaces.cdi.view;
import java.io.Serializable;
import java.util.Random;
import jakarta.enterprise.context.SessionScoped;
+import jakarta.faces.context.FacesContext;
import org.apache.myfaces.cdi.util.AbstractContextualStorageHolder;
/**
@@ -56,4 +57,13 @@ public class ViewScopeContextualStorageHolder
return new ViewScopeContextualStorage(beanManager);
}
+ protected static ViewScopeContextualStorageHolder getInstance(FacesContext facesContext)
+ {
+ return getInstance(facesContext, false);
+ }
+
+ protected static ViewScopeContextualStorageHolder getInstance(FacesContext facesContext, boolean create)
+ {
+ return getInstance(facesContext, ViewScopeContextualStorageHolder.class, create);
+ }
}
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesBehaviorCDIWrapper.java b/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesBehaviorCDIWrapper.java
index 1b944ef..e07f8c7 100644
--- a/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesBehaviorCDIWrapper.java
+++ b/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesBehaviorCDIWrapper.java
@@ -54,8 +54,7 @@ public class FacesBehaviorCDIWrapper implements PartialStateHolder, Behavior, Fa
{
if (delegate == null)
{
- delegate = (Behavior) CDIUtils.get(CDIUtils.getBeanManager(
- FacesContext.getCurrentInstance().getExternalContext()),
+ delegate = (Behavior) CDIUtils.get(CDIUtils.getBeanManager(FacesContext.getCurrentInstance()),
Behavior.class, true, new FacesBehaviorAnnotationLiteral(behaviorId));
}
return delegate;
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesClientBehaviorCDIWrapper.java b/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesClientBehaviorCDIWrapper.java
index 7957199..113145b 100644
--- a/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesClientBehaviorCDIWrapper.java
+++ b/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesClientBehaviorCDIWrapper.java
@@ -76,8 +76,7 @@ public class FacesClientBehaviorCDIWrapper implements PartialStateHolder, Client
{
if (delegate == null)
{
- delegate = (ClientBehavior) CDIUtils.get(CDIUtils.getBeanManager(
- FacesContext.getCurrentInstance().getExternalContext()),
+ delegate = (ClientBehavior) CDIUtils.get(CDIUtils.getBeanManager(FacesContext.getCurrentInstance()),
ClientBehavior.class, true, new FacesBehaviorAnnotationLiteral(behaviorId));
}
return delegate;
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesConverterCDIWrapper.java b/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesConverterCDIWrapper.java
index 50c8fa5..86294f2 100644
--- a/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesConverterCDIWrapper.java
+++ b/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesConverterCDIWrapper.java
@@ -73,7 +73,7 @@ public class FacesConverterCDIWrapper implements PartialStateHolder, Converter,
{
if (delegate == null)
{
- BeanManager bm = CDIUtils.getBeanManager(FacesContext.getCurrentInstance().getExternalContext());
+ BeanManager bm = CDIUtils.getBeanManager(FacesContext.getCurrentInstance());
if (converterId != null)
{
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesValidatorCDIWrapper.java b/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesValidatorCDIWrapper.java
index 28114fc..b5c80a7 100644
--- a/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesValidatorCDIWrapper.java
+++ b/impl/src/main/java/org/apache/myfaces/cdi/wrapper/FacesValidatorCDIWrapper.java
@@ -63,7 +63,7 @@ public class FacesValidatorCDIWrapper implements PartialStateHolder, Validator,
{
if (delegate == null)
{
- BeanManager bm = CDIUtils.getBeanManager(FacesContext.getCurrentInstance().getExternalContext());
+ BeanManager bm = CDIUtils.getBeanManager(FacesContext.getCurrentInstance());
FacesValidatorAnnotationLiteral literal = new FacesValidatorAnnotationLiteral(validatorId);
delegate = (Validator) CDIUtils.get(bm, VALIDATOR_TYPE, true, literal);
diff --git a/impl/src/main/java/org/apache/myfaces/el/DefaultELResolverBuilder.java b/impl/src/main/java/org/apache/myfaces/el/DefaultELResolverBuilder.java
index 12cd9d8..5617937 100644
--- a/impl/src/main/java/org/apache/myfaces/el/DefaultELResolverBuilder.java
+++ b/impl/src/main/java/org/apache/myfaces/el/DefaultELResolverBuilder.java
@@ -182,8 +182,7 @@ public class DefaultELResolverBuilder extends ELResolverBuilder
protected ELResolver getCDIELResolver()
{
- BeanManager beanManager = CDIUtils.getBeanManager(
- FacesContext.getCurrentInstance().getExternalContext());
+ BeanManager beanManager = CDIUtils.getBeanManager(FacesContext.getCurrentInstance());
return beanManager.getELResolver();
}
}
diff --git a/impl/src/main/java/org/apache/myfaces/el/ELResolverBuilder.java b/impl/src/main/java/org/apache/myfaces/el/ELResolverBuilder.java
index e4c4bad..368e2c0 100644
--- a/impl/src/main/java/org/apache/myfaces/el/ELResolverBuilder.java
+++ b/impl/src/main/java/org/apache/myfaces/el/ELResolverBuilder.java
@@ -142,7 +142,7 @@ public class ELResolverBuilder
return false;
}
- BeanManager beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext());
+ BeanManager beanManager = CDIUtils.getBeanManager(facesContext);
if (beanManager != null)
{
FacesConfigBeanHolder holder = CDIUtils.get(beanManager, FacesConfigBeanHolder.class);
diff --git a/impl/src/main/java/org/apache/myfaces/flow/cdi/DefaultCDIFacesFlowProvider.java b/impl/src/main/java/org/apache/myfaces/flow/cdi/DefaultCDIFacesFlowProvider.java
index 0a1748f..598333a 100644
--- a/impl/src/main/java/org/apache/myfaces/flow/cdi/DefaultCDIFacesFlowProvider.java
+++ b/impl/src/main/java/org/apache/myfaces/flow/cdi/DefaultCDIFacesFlowProvider.java
@@ -44,43 +44,9 @@ public class DefaultCDIFacesFlowProvider extends FacesFlowProvider
{
private final static String CURRENT_FLOW_SCOPE_MAP = "oam.flow.SCOPE_MAP";
private final static char SEPARATOR_CHAR = '.';
-
- private BeanManager _beanManager;
- private boolean _initialized;
+
private List<Flow> flows;
-
- private boolean isFlowScopeBeanHolderCreated(FacesContext facesContext)
- {
- if (facesContext.getExternalContext().getSession(false) == null)
- {
- return false;
- }
-
- return facesContext.getExternalContext().getSessionMap()
- .containsKey(FlowScopeBeanHolder.CREATED);
- }
-
- @Override
- public void onSessionDestroyed()
- {
- // In CDI case, the best way to deal with this is use a method
- // with @PreDestroy annotation on a session scope bean
- // ( ViewScopeBeanHolder.destroyBeans() ). There is no need
- // to do anything else in this location, but it is advised
- // in CDI the beans are destroyed at the end of the request,
- // not when invalidateSession() is called.
- FacesContext facesContext = FacesContext.getCurrentInstance();
- if (facesContext != null && isFlowScopeBeanHolderCreated(facesContext))
- {
- FlowScopeBeanHolder flowScopeBeanHolder = CDIUtils.get(
- _beanManager, FlowScopeBeanHolder.class, false);
- if (flowScopeBeanHolder != null)
- {
- flowScopeBeanHolder.destroyBeans();
- }
- }
- }
-
+
@Override
public Iterator<Flow> getAnnotatedFlows(FacesContext facesContext)
{
@@ -88,7 +54,7 @@ public class DefaultCDIFacesFlowProvider extends FacesFlowProvider
{
flows = new ArrayList<>();
- BeanManager beanManager = getBeanManager(facesContext);
+ BeanManager beanManager = CDIUtils.getBeanManager(facesContext);
if (beanManager == null)
{
Logger.getLogger(DefaultCDIFacesFlowProvider.class.getName()).log(Level.INFO,
@@ -111,12 +77,8 @@ public class DefaultCDIFacesFlowProvider extends FacesFlowProvider
@Override
public void doAfterEnterFlow(FacesContext context, Flow flow)
{
- BeanManager beanManager = getBeanManager(context);
- if (beanManager != null)
- {
- FlowScopeBeanHolder beanHolder = CDIUtils.get(beanManager, FlowScopeBeanHolder.class);
- beanHolder.createCurrentFlowScope(context);
- }
+ FlowScopeContextualStorageHolder storageHolder = FlowScopeContextualStorageHolder.getInstance(context, true);
+ storageHolder.createCurrentFlowScope(context);
String mapKey = getFlowKey(flow);
context.getAttributes().remove(mapKey);
@@ -125,12 +87,8 @@ public class DefaultCDIFacesFlowProvider extends FacesFlowProvider
@Override
public void doBeforeExitFlow(FacesContext context, Flow flow)
{
- BeanManager beanManager = getBeanManager(context);
- if (beanManager != null)
- {
- FlowScopeBeanHolder beanHolder = CDIUtils.get(beanManager, FlowScopeBeanHolder.class);
- beanHolder.destroyCurrentFlowScope(context);
- }
+ FlowScopeContextualStorageHolder storageHolder = FlowScopeContextualStorageHolder.getInstance(context, true);
+ storageHolder.destroyCurrentFlowScope(context);
String mapKey = getFlowKey(flow);
context.getAttributes().remove(mapKey);
@@ -144,7 +102,9 @@ public class DefaultCDIFacesFlowProvider extends FacesFlowProvider
{
String mapKey = getFlowKey(flow);
return (Map<Object, Object>) facesContext.getAttributes().computeIfAbsent(mapKey,
- k -> new FlowScopeMap(getBeanManager(facesContext), FlowUtils.getFlowMapKey(facesContext, flow)));
+ k -> new FlowScopeMap(
+ CDIUtils.getBeanManager(facesContext),
+ FlowUtils.getFlowMapKey(facesContext, flow)));
}
return null;
@@ -158,27 +118,12 @@ public class DefaultCDIFacesFlowProvider extends FacesFlowProvider
Flow flow = facesContext.getApplication().getFlowHandler().getCurrentFlow(facesContext);
if (flow != null)
{
- BeanManager beanManager = getBeanManager(facesContext);
- if (beanManager != null)
- {
- FlowScopeBeanHolder beanHolder = CDIUtils.get(beanManager, FlowScopeBeanHolder.class);
-
- //Refresh client window for flow scope
- beanHolder.refreshClientWindow(facesContext);
- }
+ FlowScopeContextualStorageHolder storageHolder = FlowScopeContextualStorageHolder
+ .getInstance(facesContext, true);
+ storageHolder.refreshClientWindow(facesContext);
}
}
}
-
- public BeanManager getBeanManager(FacesContext facesContext)
- {
- if (_beanManager == null && !_initialized)
- {
- _beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext());
- _initialized = true;
- }
- return _beanManager;
- }
protected String getFlowKey(Flow flow)
{
diff --git a/impl/src/main/java/org/apache/myfaces/flow/cdi/FacesFlowClientWindowCollection.java b/impl/src/main/java/org/apache/myfaces/flow/cdi/FacesFlowClientWindowCollection.java
deleted file mode 100644
index 6b495aa..0000000
--- a/impl/src/main/java/org/apache/myfaces/flow/cdi/FacesFlowClientWindowCollection.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.myfaces.flow.cdi;
-
-import java.io.Serializable;
-import org.apache.myfaces.util.lang.LRULinkedHashMap;
-
-/**
- * This class is a wrapper used to deal with concurrency issues when accessing the inner LRUMap.
- */
-class FacesFlowClientWindowCollection implements Serializable
-{
- private static final long serialVersionUID = 1L;
-
- private LRULinkedHashMap<String, String> map;
- private FlowScopeBeanHolder holder;
-
- public FacesFlowClientWindowCollection()
- {
- }
-
- public FacesFlowClientWindowCollection(int capacity)
- {
- this.map = new LRULinkedHashMap<>(capacity, (eldest) ->
- {
- holder.clearFlowMap(eldest.getKey());
- });
- }
-
- public synchronized void put(String key, String value)
- {
- map.put(key, value);
- }
-
- public synchronized String get(String key)
- {
- return map.get(key);
- }
-
- public synchronized void remove(String key)
- {
- map.remove(key);
- }
-
- public synchronized boolean isEmpty()
- {
- return map.isEmpty();
- }
-
- public void setFlowScopeBeanHolder(FlowScopeBeanHolder holder)
- {
- this.holder = holder;
- }
-}
diff --git a/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowBuilderExtension.java b/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowBuilderExtension.java
deleted file mode 100644
index 2527c36..0000000
--- a/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowBuilderExtension.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.myfaces.flow.cdi;
-
-import jakarta.enterprise.event.Observes;
-import jakarta.enterprise.inject.spi.AnnotatedType;
-import jakarta.enterprise.inject.spi.BeanManager;
-import jakarta.enterprise.inject.spi.BeforeBeanDiscovery;
-import jakarta.enterprise.inject.spi.Extension;
-
-/**
- * This extension is responsible of scan flow definitions through CDI. For example:
- *
- * <code>
- * @Produces @FlowDefinition
- * public Flow defineFlow(@FlowBuilderParameter FlowBuilder flowBuilder) {...}
- * </code>
- *
- * @author Leonardo Uribe
- */
-public class FlowBuilderExtension implements Extension
-{
- void beforeBeanDiscovery(@Observes final BeforeBeanDiscovery event, BeanManager beanManager)
- {
- // Register FlowBuilderFactoryBean as a bean with CDI annotations, so the system
- // can take it into account, and use it later when necessary.
- AnnotatedType<FlowBuilderFactoryBean> flowDiscoveryHelper =
- beanManager.createAnnotatedType(FlowBuilderFactoryBean.class);
- event.addAnnotatedType(flowDiscoveryHelper, flowDiscoveryHelper.getJavaClass().getName());
- }
-}
diff --git a/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowBuilderFactoryBean.java b/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowBuilderFactoryBean.java
deleted file mode 100644
index cf29891..0000000
--- a/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowBuilderFactoryBean.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.myfaces.flow.cdi;
-
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.enterprise.inject.Produces;
-import jakarta.faces.flow.builder.FlowBuilder;
-import jakarta.faces.flow.builder.FlowBuilderParameter;
-
-import org.apache.myfaces.flow.builder.FlowBuilderImpl;
-
-/**
- * This bean is used later by CDI to process flow definitions
- *
- * @author Leonardo Uribe
- */
-@ApplicationScoped
-public class FlowBuilderFactoryBean
-{
- public FlowBuilderFactoryBean()
- {
- }
-
- @Produces
- @FlowBuilderParameter
- public FlowBuilder createFlowBuilderInstance()
- {
- return new FlowBuilderImpl();
- }
-}
diff --git a/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeBeanHolder.java b/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeBeanHolder.java
deleted file mode 100644
index d2f62b4..0000000
--- a/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeBeanHolder.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.myfaces.flow.cdi;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import jakarta.annotation.PostConstruct;
-import jakarta.annotation.PreDestroy;
-import jakarta.enterprise.context.SessionScoped;
-import jakarta.enterprise.inject.spi.BeanManager;
-import jakarta.faces.context.ExceptionHandler;
-import jakarta.faces.context.ExternalContext;
-import jakarta.faces.context.FacesContext;
-import jakarta.faces.flow.Flow;
-import jakarta.faces.flow.FlowHandler;
-import jakarta.faces.lifecycle.ClientWindow;
-import jakarta.inject.Inject;
-import jakarta.servlet.ServletContext;
-import org.apache.myfaces.cdi.util.ContextualInstanceInfo;
-import org.apache.myfaces.cdi.util.ContextualStorage;
-import org.apache.myfaces.cdi.JsfApplicationArtifactHolder;
-import org.apache.myfaces.cdi.util.CDIUtils;
-import org.apache.myfaces.context.servlet.StartupFacesContextImpl;
-import org.apache.myfaces.context.servlet.StartupServletExternalContextImpl;
-import org.apache.myfaces.flow.FlowUtils;
-import org.apache.myfaces.config.MyfacesConfig;
-import org.apache.myfaces.context.ExceptionHandlerImpl;
-
-
-/**
- *
- * This holder will store the flow scope active ids and it's beans for the current
- * HTTP Session. We use standard SessionScoped bean to not need
- * to treat async-supported and similar headache.
- *
- * @author lu4242
- */
-@SessionScoped
-public class FlowScopeBeanHolder implements Serializable
-{
- /**
- * key: client window id + flow id
- * value: the {@link ContextualStorage} which holds all the
- * {@link jakarta.enterprise.inject.spi.Bean}s.
- */
- private Map<String, ContextualStorage> storageMap;
-
- private Map<String, List<String>> activeFlowMapKeys;
-
- private FacesFlowClientWindowCollection windowCollection;
-
- public static final String CURRENT_FLOW_SCOPE_MAP = "oam.CURRENT_FLOW_SCOPE_MAP";
-
- public static final String CREATED = FlowScopeBeanHolder.class.getName() + ".CREATED";
-
- @Inject
- JsfApplicationArtifactHolder applicationContextBean;
-
- public FlowScopeBeanHolder()
- {
- }
-
- @PostConstruct
- public void init()
- {
- storageMap = new ConcurrentHashMap<>();
- activeFlowMapKeys = new ConcurrentHashMap<>();
- windowCollection = null;
-
- FacesContext facesContext = FacesContext.getCurrentInstance();
- this.refreshClientWindow(facesContext);
- facesContext.getExternalContext().getSessionMap().put(CREATED, true);
-
- Object context = facesContext.getExternalContext().getContext();
- if (context instanceof ServletContext)
- {
- BeanManager beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext());
- JsfApplicationArtifactHolder appBean = CDIUtils.get(beanManager, JsfApplicationArtifactHolder.class);
- if (appBean.getServletContext() != null)
- {
- appBean.setServletContext((ServletContext) context);
- }
- }
- }
-
- /**
- * This method will return the ContextualStorage or create a new one
- * if no one is yet assigned to the current flowClientWindowId.
- *
- * @param beanManager we need the CDI {@link BeanManager} for serialisation.
- * @param flowClientWindowId the flowClientWindowId for the current flow.
- * @param create create if not existent
- *
- * @return the ContextualStorage or null
- */
- public ContextualStorage getContextualStorage(BeanManager beanManager, String flowClientWindowId, boolean create)
- {
- ContextualStorage storage = storageMap.get(flowClientWindowId);
- if (storage == null && create)
- {
- storage = new ContextualStorage(beanManager, true);
- storageMap.put(flowClientWindowId, storage);
- }
- return storage;
- }
-
- public Map<String, ContextualStorage> getStorageMap()
- {
- return storageMap;
- }
-
- public Map<Object, Object> getFlowScopeMap(BeanManager beanManager, String flowClientWindowId, boolean create)
- {
- ContextualStorage contextualStorage = getContextualStorage(beanManager, flowClientWindowId, create);
- if (contextualStorage == null)
- {
- return null;
- }
-
- ContextualInstanceInfo info = contextualStorage.getStorage().get(CURRENT_FLOW_SCOPE_MAP);
- if (info == null && create)
- {
- info = new ContextualInstanceInfo<>();
- contextualStorage.getStorage().put(CURRENT_FLOW_SCOPE_MAP, info);
- }
- if (info == null)
- {
- return null;
- }
-
- Map<Object, Object> map = (Map<Object, Object>) info.getContextualInstance();
- if (map == null && create)
- {
- map = new HashMap<>();
- info.setContextualInstance(map);
- }
- return map;
- }
-
- /**
- *
- * This method will replace the storageMap and with
- * a new empty one.
- * This method can be used to properly destroy the BeanHolder beans
- * without having to sync heavily. Any
- * {@link jakarta.enterprise.inject.spi.Bean#destroy(Object, jakarta.enterprise.context.spi.CreationalContext)}
- * should be performed on the returned old storage map.
- * @return the old storageMap.
- */
- public Map<String, ContextualStorage> forceNewStorage()
- {
- Map<String, ContextualStorage> oldStorageMap = storageMap;
- storageMap = new ConcurrentHashMap<>();
- return oldStorageMap;
- }
-
- /**
- * This method properly destroys all current @WindowScoped beans
- * of the active session and also prepares the storage for new beans.
- * It will automatically get called when the session context closes
- * but can also get invoked manually, e.g. if a user likes to get rid
- * of all it's @WindowScoped beans.
- */
- //@PreDestroy
- public void destroyBeans()
- {
- // we replace the old BeanHolder beans with a new storage Map
- // an afterwards destroy the old Beans without having to care about any syncs.
- Map<String, ContextualStorage> oldContextStorages = forceNewStorage();
-
- for (ContextualStorage contextualStorage : oldContextStorages.values())
- {
- FlowScopeContext.destroyAllActive(contextualStorage);
- }
- }
-
- /**
- * See description on ViewScopeBeanHolder for details about how this works
- */
- @PreDestroy
- public void destroyBeansOnPreDestroy()
- {
- Map<String, ContextualStorage> oldContextStorages = forceNewStorage();
- if (!oldContextStorages.isEmpty())
- {
- FacesContext facesContext = FacesContext.getCurrentInstance();
- ServletContext servletContext = null;
- if (facesContext == null)
- {
- try
- {
- servletContext = applicationContextBean.getServletContext();
- }
- catch (Throwable e)
- {
- Logger.getLogger(FlowScopeBeanHolder.class.getName()).log(Level.WARNING,
- "Cannot locate servletContext to create FacesContext on @PreDestroy flow scope beans. "
- + "The beans will be destroyed without active FacesContext instance.");
- servletContext = null;
- }
- }
- if (facesContext == null && servletContext != null)
- {
- try
- {
- ExternalContext externalContext = new StartupServletExternalContextImpl(servletContext, false);
- ExceptionHandler exceptionHandler = new ExceptionHandlerImpl();
- facesContext = new StartupFacesContextImpl(externalContext, externalContext, exceptionHandler,
- false);
- for (ContextualStorage contextualStorage : oldContextStorages.values())
- {
- FlowScopeContext.destroyAllActive(contextualStorage);
- }
- }
- finally
- {
- facesContext.release();
- }
- }
- else
- {
- for (ContextualStorage contextualStorage : oldContextStorages.values())
- {
- FlowScopeContext.destroyAllActive(contextualStorage);
- }
- }
- }
- }
-
- public void refreshClientWindow(FacesContext facesContext)
- {
- if (windowCollection == null)
- {
- Integer numberOfFacesFlowClientWindowIdsInSession =
- MyfacesConfig.getCurrentInstance(facesContext).getNumberOfFacesFlowClientWindowIdsInSession();
- windowCollection = new FacesFlowClientWindowCollection(numberOfFacesFlowClientWindowIdsInSession);
- }
- ClientWindow cw = facesContext.getExternalContext().getClientWindow();
- if (cw != null && cw.getId() != null)
- {
- windowCollection.setFlowScopeBeanHolder(this);
- windowCollection.put(cw.getId(), "");
- }
- }
-
- public void clearFlowMap(String clientWindowId)
- {
- List<String> activeFlowKeys = activeFlowMapKeys.remove(clientWindowId);
- if (activeFlowKeys != null && !activeFlowKeys.isEmpty())
- {
- for (String flowMapKey : activeFlowKeys)
- {
- ContextualStorage contextualStorage = storageMap.remove(flowMapKey);
- if (contextualStorage != null)
- {
- FlowScopeContext.destroyAllActive(contextualStorage);
- }
- }
- }
- }
-
- public List<String> getActiveFlowMapKeys(FacesContext facesContext)
- {
- ClientWindow cw = facesContext.getExternalContext().getClientWindow();
- String baseKey = cw.getId();
- List<String> activeFlowKeys = activeFlowMapKeys.get(baseKey);
- if (activeFlowKeys == null)
- {
- return Collections.emptyList();
- }
-
- return activeFlowKeys;
- }
-
- public void createCurrentFlowScope(FacesContext facesContext)
- {
- ClientWindow cw = facesContext.getExternalContext().getClientWindow();
- String baseKey = cw.getId();
-
- FlowHandler flowHandler = facesContext.getApplication().getFlowHandler();
- Flow flow = flowHandler.getCurrentFlow(facesContext);
- String flowMapKey = FlowUtils.getFlowMapKey(facesContext, flow);
-
- List<String> activeFlowKeys = activeFlowMapKeys.computeIfAbsent(baseKey, k -> new ArrayList<>());
- activeFlowKeys.add(0, flowMapKey);
- activeFlowMapKeys.put(baseKey, activeFlowKeys);
- refreshClientWindow(facesContext);
- }
-
- public void destroyCurrentFlowScope(FacesContext facesContext)
- {
- ClientWindow cw = facesContext.getExternalContext().getClientWindow();
- String baseKey = cw.getId();
-
- FlowHandler flowHandler = facesContext.getApplication().getFlowHandler();
- Flow flow = flowHandler.getCurrentFlow(facesContext);
- String flowMapKey = FlowUtils.getFlowMapKey(facesContext, flow);
-
- ContextualStorage contextualStorage = storageMap.remove(flowMapKey);
- if (contextualStorage != null)
- {
- FlowScopeContext.destroyAllActive(contextualStorage);
- }
-
- List<String> activeFlowKeys = activeFlowMapKeys.get(baseKey);
- if (activeFlowKeys != null && !activeFlowKeys.isEmpty())
- {
- activeFlowKeys.remove(flowMapKey);
- }
- }
-}
diff --git a/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeContext.java b/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeContext.java
index be5f533..7c40bad 100644
--- a/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeContext.java
+++ b/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeContext.java
@@ -33,7 +33,6 @@ import jakarta.faces.context.FacesContext;
import jakarta.faces.flow.Flow;
import jakarta.faces.flow.FlowHandler;
import jakarta.faces.flow.FlowScoped;
-import org.apache.myfaces.cdi.util.CDIUtils;
import org.apache.myfaces.cdi.util.ContextualInstanceInfo;
import org.apache.myfaces.cdi.util.ContextualStorage;
import org.apache.myfaces.flow.FlowReference;
@@ -67,24 +66,9 @@ public class FlowScopeContext implements Context
this.passivatingScope = beanManager.isPassivatingScope(getScope());
}
- protected FlowScopeBeanHolder getFlowScopeBeanHolder()
+ protected FlowScopeContextualStorageHolder getStorageHolder(FacesContext facesContext)
{
- return getFlowScopeBeanHolder(FacesContext.getCurrentInstance());
- }
-
- protected FlowScopeBeanHolder getFlowScopeBeanHolder(FacesContext facesContext)
- {
- FlowScopeBeanHolder beanHolder = (FlowScopeBeanHolder) facesContext.getExternalContext().getApplicationMap()
- .get(FlowScopeBeanHolder.class.getName());
- if (beanHolder == null)
- {
- beanHolder = CDIUtils.get(beanManager, FlowScopeBeanHolder.class);
- facesContext.getExternalContext().getApplicationMap().put(
- FlowScopeBeanHolder.class.getName(),
- beanHolder);
- }
-
- return beanHolder;
+ return FlowScopeContextualStorageHolder.getInstance(facesContext, true);
}
public String getCurrentClientWindowFlowId(FacesContext facesContext)
@@ -99,22 +83,6 @@ public class FlowScopeContext implements Context
return flowMapKey;
}
- /**
- * An implementation has to return the underlying storage which
- * contains the items held in the Context.
- * @param createIfNotExist whether a ContextualStorage shall get created if it doesn't yet exist.
- * @return the underlying storage
- */
- protected ContextualStorage getContextualStorage(boolean createIfNotExist, String clientWindowFlowId)
- {
- if (clientWindowFlowId == null)
- {
- throw new ContextNotActiveException(this.getClass().getName() + ": no current active flow");
- }
-
- return getFlowScopeBeanHolder().getContextualStorage(beanManager, clientWindowFlowId, createIfNotExist);
- }
-
@Override
public Class<? extends Annotation> getScope()
{
@@ -138,9 +106,15 @@ public class FlowScopeContext implements Context
return flow != null;
}
- /**
- * @return whether the served scope is a passivating scope
- */
+ protected void checkActive(FacesContext facesContext)
+ {
+ if (!isActive(facesContext))
+ {
+ throw new ContextNotActiveException("CDI context with scope annotation @"
+ + getScope().getName() + " is not active with respect to the current thread");
+ }
+ }
+
public boolean isPassivatingScope()
{
return passivatingScope;
@@ -159,7 +133,7 @@ public class FlowScopeContext implements Context
String flowMapKey = FlowUtils.getFlowMapKey(facesContext, reference);
if (flowMapKey != null)
{
- ContextualStorage storage = getContextualStorage(false, flowMapKey);
+ ContextualStorage storage = getContextualStorage(facesContext, false, flowMapKey);
if (storage != null)
{
Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
@@ -178,13 +152,12 @@ public class FlowScopeContext implements Context
}
}
- List<String> activeFlowMapKeys = getFlowScopeBeanHolder().getActiveFlowMapKeys(facesContext);
+ List<String> activeFlowMapKeys = getStorageHolder(facesContext).getActiveFlowMapKeys(facesContext);
for (String flowMapKey : activeFlowMapKeys)
{
- ContextualStorage storage = getContextualStorage(false, flowMapKey);
+ ContextualStorage storage = getContextualStorage(facesContext, false, flowMapKey);
if (storage == null)
{
- //return null;
continue;
}
@@ -213,30 +186,28 @@ public class FlowScopeContext implements Context
" doesn't implement " + PassivationCapable.class.getName());
}
- FlowReference reference = flowBeanReferences.get(((Bean)bean).getBeanClass());
+ FlowReference reference = flowBeanReferences.get(((Bean) bean).getBeanClass());
if (reference != null)
{
String flowMapKey = FlowUtils.getFlowMapKey(facesContext, reference);
- if (flowMapKey != null)
- {
- ContextualStorage storage = getContextualStorage(false, flowMapKey);
- if (storage != null)
- {
- Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
- ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(storage.getBeanKey(bean));
-
- if (contextualInstanceInfo != null)
- {
- return (T) contextualInstanceInfo.getContextualInstance();
- }
- }
- }
- else
+ if (flowMapKey == null)
{
throw new IllegalStateException("Flow " + reference.getId()+
" cannot be found when resolving bean " + bean.toString());
}
-
+
+ ContextualStorage storage = getContextualStorage(facesContext, false, flowMapKey);
+ if (storage != null)
+ {
+ Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
+ ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(storage.getBeanKey(bean));
+
+ if (contextualInstanceInfo != null)
+ {
+ return (T) contextualInstanceInfo.getContextualInstance();
+ }
+ }
+
FlowHandler flowHandler = facesContext.getApplication().getFlowHandler();
// Since it is possible to have only the flow id without documentId, the best
// is first get the flow using flowHandler.getFlow and then check if the flow is
@@ -253,11 +224,10 @@ public class FlowScopeContext implements Context
throw new IllegalStateException(bean.toString() + "cannot be created if flow "
+ reference.getId() + " is not active");
}
-
- ContextualStorage storage = getContextualStorage(true, flowMapKey);
+
+ storage = getContextualStorage(facesContext, true, flowMapKey); // now create it
Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(storage.getBeanKey(bean));
-
if (contextualInstanceInfo != null)
{
@SuppressWarnings("unchecked")
@@ -271,14 +241,13 @@ public class FlowScopeContext implements Context
return storage.createContextualInstance(bean, creationalContext);
}
- List<String> activeFlowMapKeys = getFlowScopeBeanHolder().getActiveFlowMapKeys(facesContext);
+ List<String> activeFlowMapKeys = getStorageHolder(facesContext).getActiveFlowMapKeys(facesContext);
for (String flowMapKey : activeFlowMapKeys)
{
- ContextualStorage storage = getContextualStorage(false, flowMapKey);
+ ContextualStorage storage = getContextualStorage(facesContext, false, flowMapKey);
Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(storage.getBeanKey(bean));
-
if (contextualInstanceInfo != null)
{
@SuppressWarnings("unchecked")
@@ -288,13 +257,12 @@ public class FlowScopeContext implements Context
return instance;
}
}
-
}
- ContextualStorage storage = getContextualStorage(true, getCurrentClientWindowFlowId(facesContext));
+ ContextualStorage storage = getContextualStorage(facesContext, true,
+ getCurrentClientWindowFlowId(facesContext));
Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(storage.getBeanKey(bean));
-
if (contextualInstanceInfo != null)
{
@SuppressWarnings("unchecked")
@@ -304,72 +272,27 @@ public class FlowScopeContext implements Context
return instance;
}
}
-
+
return storage.createContextualInstance(bean, creationalContext);
}
- /**
- * Destroy the Contextual Instance of the given Bean.
- * @param bean dictates which bean shall get cleaned up
- * @return <code>true</code> if the bean was destroyed, <code>false</code> if there was no such bean.
- */
- public boolean destroy(Contextual bean)
+ protected ContextualStorage getContextualStorage(FacesContext context, boolean createIfNotExist,
+ String clientWindowFlowId)
{
- FacesContext facesContext = FacesContext.getCurrentInstance();
- List<String> activeFlowMapKeys = getFlowScopeBeanHolder().getActiveFlowMapKeys(facesContext);
- for (String flowMapKey : activeFlowMapKeys)
+ if (clientWindowFlowId == null)
{
- ContextualStorage storage = getContextualStorage(false, flowMapKey);
- if (storage == null)
- {
- continue;
- }
- ContextualInstanceInfo<?> contextualInstanceInfo = storage.getStorage().get(storage.getBeanKey(bean));
-
- if (contextualInstanceInfo == null)
- {
- continue;
- }
-
- bean.destroy(contextualInstanceInfo.getContextualInstance(), contextualInstanceInfo.getCreationalContext());
- return true;
+ throw new ContextNotActiveException(this.getClass().getName() + ": no current active flow");
}
- return false;
- }
-
- /**
- * Destroys all the Contextual Instances in the specified ContextualStorage.
- * This is a static method to allow various holder objects to cleanup
- * properly in @PreDestroy.
- */
- public static void destroyAllActive(ContextualStorage storage)
- {
- Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
- for (Map.Entry<Object, ContextualInstanceInfo<?>> entry : contextMap.entrySet())
- {
- if (!FlowScopeBeanHolder.CURRENT_FLOW_SCOPE_MAP.equals(entry.getKey()))
- {
- Contextual bean = storage.getBean(entry.getKey());
- ContextualInstanceInfo<?> contextualInstanceInfo = entry.getValue();
- bean.destroy(contextualInstanceInfo.getContextualInstance(),
- contextualInstanceInfo.getCreationalContext());
- }
- }
+ return getStorageHolder(context).getContextualStorage(clientWindowFlowId, createIfNotExist);
}
- /**
- * Make sure that the Context is really active.
- * @throws ContextNotActiveException if there is no active
- * Context for the current Thread.
- */
- protected void checkActive(FacesContext facesContext)
+ public static void destroyAll(FacesContext facesContext)
{
- if (!isActive(facesContext))
+ FlowScopeContextualStorageHolder manager = FlowScopeContextualStorageHolder.getInstance(facesContext);
+ if (manager != null)
{
- throw new ContextNotActiveException("CDI context with scope annotation @"
- + getScope().getName() + " is not active with respect to the current thread");
+ manager.destroyAll(facesContext);
}
}
-
}
diff --git a/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeContextualStorageHolder.java b/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeContextualStorageHolder.java
new file mode 100644
index 0000000..d2aae03
--- /dev/null
+++ b/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeContextualStorageHolder.java
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.flow.cdi;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import jakarta.annotation.PostConstruct;
+import jakarta.enterprise.context.SessionScoped;
+import jakarta.enterprise.inject.spi.BeanManager;
+import jakarta.faces.context.FacesContext;
+import jakarta.faces.flow.Flow;
+import jakarta.faces.flow.FlowHandler;
+import jakarta.faces.lifecycle.ClientWindow;
+import org.apache.myfaces.cdi.util.ContextualInstanceInfo;
+import org.apache.myfaces.cdi.util.ContextualStorage;
+import org.apache.myfaces.cdi.util.AbstractContextualStorageHolder;
+import org.apache.myfaces.flow.FlowUtils;
+import org.apache.myfaces.config.MyfacesConfig;
+import org.apache.myfaces.util.lang.LRULinkedHashMap;
+
+/**
+ * This holder will store the flow scope active ids and it's beans for the current
+ * HTTP Session. We use standard SessionScoped bean to not need
+ * to treat async-supported and similar headache.
+ *
+ * @author lu4242
+ */
+@SessionScoped
+public class FlowScopeContextualStorageHolder
+ extends AbstractContextualStorageHolder<ContextualStorage>
+ implements Serializable
+{
+ /**
+ * key: client window id + flow id
+ * value: the {@link ContextualStorage} which holds all the
+ * {@link jakarta.enterprise.inject.spi.Bean}s.
+ */
+
+ // clientwindow <> List<Flow>
+ private Map<String, List<String>> activeFlowMapKeys;
+
+ private LRULinkedHashMap<String, String> clientWindowExpirationStack;
+
+ public static final String CURRENT_FLOW_SCOPE_MAP = "oam.CURRENT_FLOW_SCOPE_MAP";
+
+ public FlowScopeContextualStorageHolder()
+ {
+ }
+
+ @PostConstruct
+ @Override
+ public void init()
+ {
+ super.init();
+
+ activeFlowMapKeys = new ConcurrentHashMap<>();
+
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+
+ Integer numberOfFacesFlowClientWindowIdsInSession =
+ MyfacesConfig.getCurrentInstance(facesContext).getNumberOfFacesFlowClientWindowIdsInSession();
+ clientWindowExpirationStack = new LRULinkedHashMap<>(numberOfFacesFlowClientWindowIdsInSession, (eldest) ->
+ {
+ clearFlowMap(FacesContext.getCurrentInstance(), eldest.getKey());
+ });
+
+ refreshClientWindow(facesContext);
+ }
+
+ public Map<Object, Object> getFlowScopeMap(BeanManager beanManager, String flowClientWindowId, boolean create)
+ {
+ ContextualStorage contextualStorage = getContextualStorage(flowClientWindowId, create);
+ if (contextualStorage == null)
+ {
+ return null;
+ }
+
+ ContextualInstanceInfo info = contextualStorage.getStorage().get(CURRENT_FLOW_SCOPE_MAP);
+ if (info == null && create)
+ {
+ info = new ContextualInstanceInfo<>();
+ contextualStorage.getStorage().put(CURRENT_FLOW_SCOPE_MAP, info);
+ }
+ if (info == null)
+ {
+ return null;
+ }
+
+ Map<Object, Object> map = (Map<Object, Object>) info.getContextualInstance();
+ if (map == null && create)
+ {
+ map = new HashMap<>();
+ info.setContextualInstance(map);
+ }
+ return map;
+ }
+
+ public void refreshClientWindow(FacesContext facesContext)
+ {
+ ClientWindow cw = facesContext.getExternalContext().getClientWindow();
+ if (cw != null && cw.getId() != null)
+ {
+ clientWindowExpirationStack.put(cw.getId(), "");
+ }
+ }
+
+ public void clearFlowMap(FacesContext facesContext, String clientWindowId)
+ {
+ List<String> activeFlowKeys = activeFlowMapKeys.remove(clientWindowId);
+ if (activeFlowKeys != null && !activeFlowKeys.isEmpty())
+ {
+ for (String flowMapKey : activeFlowKeys)
+ {
+ ContextualStorage contextualStorage = storageMap.remove(flowMapKey);
+ if (contextualStorage != null)
+ {
+ destroyAll(contextualStorage, facesContext);
+ }
+ }
+ }
+ }
+
+ public List<String> getActiveFlowMapKeys(FacesContext facesContext)
+ {
+ ClientWindow cw = facesContext.getExternalContext().getClientWindow();
+ String baseKey = cw.getId();
+ List<String> activeFlowKeys = activeFlowMapKeys.get(baseKey);
+ if (activeFlowKeys == null)
+ {
+ return Collections.emptyList();
+ }
+
+ return activeFlowKeys;
+ }
+
+ public void createCurrentFlowScope(FacesContext facesContext)
+ {
+ ClientWindow cw = facesContext.getExternalContext().getClientWindow();
+ String baseKey = cw.getId();
+
+ FlowHandler flowHandler = facesContext.getApplication().getFlowHandler();
+ Flow flow = flowHandler.getCurrentFlow(facesContext);
+ String flowMapKey = FlowUtils.getFlowMapKey(facesContext, flow);
+
+ List<String> activeFlowKeys = activeFlowMapKeys.computeIfAbsent(baseKey, k -> new ArrayList<>());
+ activeFlowKeys.add(0, flowMapKey);
+ activeFlowMapKeys.put(baseKey, activeFlowKeys);
+ refreshClientWindow(facesContext);
+ }
+
+ public void destroyCurrentFlowScope(FacesContext facesContext)
+ {
+ ClientWindow cw = facesContext.getExternalContext().getClientWindow();
+ String baseKey = cw.getId();
+
+ FlowHandler flowHandler = facesContext.getApplication().getFlowHandler();
+ Flow flow = flowHandler.getCurrentFlow(facesContext);
+ String flowMapKey = FlowUtils.getFlowMapKey(facesContext, flow);
+
+ ContextualStorage contextualStorage = storageMap.remove(flowMapKey);
+ if (contextualStorage != null)
+ {
+ destroyAll(contextualStorage, facesContext);
+ }
+
+ List<String> activeFlowKeys = activeFlowMapKeys.get(baseKey);
+ if (activeFlowKeys != null && !activeFlowKeys.isEmpty())
+ {
+ activeFlowKeys.remove(flowMapKey);
+ }
+ }
+
+ @Override
+ protected boolean isSkipDestroy(Map.Entry<Object, ContextualInstanceInfo<?>> entry)
+ {
+ return CURRENT_FLOW_SCOPE_MAP.equals(entry.getKey());
+ }
+
+ @Override
+ protected ContextualStorage newContextualStorage(String slotId)
+ {
+ return new ContextualStorage(beanManager, true);
+ }
+
+ public static FlowScopeContextualStorageHolder getInstance(FacesContext facesContext)
+ {
+ return getInstance(facesContext, false);
+ }
+
+ public static FlowScopeContextualStorageHolder getInstance(FacesContext facesContext, boolean create)
+ {
+ return getInstance(facesContext, FlowScopeContextualStorageHolder.class, create);
+ }
+}
diff --git a/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeExtension.java b/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeExtension.java
index 47ab63b..692f3c9 100644
--- a/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeExtension.java
+++ b/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeExtension.java
@@ -48,9 +48,8 @@ public class FlowScopeExtension implements Extension
void beforeBeanDiscovery(@Observes final BeforeBeanDiscovery event, BeanManager beanManager)
{
event.addScope(FlowScoped.class, true, true);
- // Register FlowBuilderFactoryBean as a bean with CDI annotations, so the system
- // can take it into account, and use it later when necessary.
- AnnotatedType bean = beanManager.createAnnotatedType(FlowScopeBeanHolder.class);
+
+ AnnotatedType bean = beanManager.createAnnotatedType(FlowScopeContextualStorageHolder.class);
event.addAnnotatedType(bean, bean.getJavaClass().getName());
}
@@ -76,5 +75,4 @@ public class FlowScopeExtension implements Extension
flowScopedContext = new FlowScopeContext(manager, flowBeanReferences);
event.addContext(flowScopedContext);
}
-
}
diff --git a/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeMap.java b/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeMap.java
index d8a7efd..a6bf42e 100644
--- a/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeMap.java
+++ b/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeMap.java
@@ -26,7 +26,7 @@ import jakarta.enterprise.inject.spi.BeanManager;
import java.util.Collections;
/**
- *
+ *
*
* @author Leonardo Uribe
*/
@@ -34,9 +34,9 @@ public class FlowScopeMap implements Map
{
private BeanManager beanManager;
private String currentClientWindowFlowId;
- private FlowScopeBeanHolder beanHolder;
+ private FlowScopeContextualStorageHolder storageHolder;
private boolean beanHolderInitialized = false;
-
+
public FlowScopeMap(BeanManager beanManager, String currentClientWindowFlowId)
{
this.beanManager = beanManager;
@@ -45,33 +45,33 @@ public class FlowScopeMap implements Map
private Map<Object, Object> getWrapped(boolean create)
{
- if (beanHolder == null)
+ if (storageHolder == null)
{
if (create)
{
- beanHolder = CDIUtils.get(beanManager, FlowScopeBeanHolder.class);
+ storageHolder = CDIUtils.get(beanManager, FlowScopeContextualStorageHolder.class);
}
else if (!beanHolderInitialized)
{
- beanHolder = CDIUtils.get(beanManager, FlowScopeBeanHolder.class, false);
+ storageHolder = CDIUtils.get(beanManager, FlowScopeContextualStorageHolder.class, false);
beanHolderInitialized = true;
}
}
- if (beanHolder == null)
+ if (storageHolder == null)
{
return null;
}
- return beanHolder.getFlowScopeMap(beanManager, currentClientWindowFlowId, create);
+ return storageHolder.getFlowScopeMap(beanManager, currentClientWindowFlowId, create);
}
-
+
@Override
public int size()
{
Map<Object, Object> wrapped = getWrapped(false);
return wrapped == null ? 0 : wrapped.size();
}
-
+
@Override
public boolean isEmpty()
{
diff --git a/impl/src/main/java/org/apache/myfaces/flow/impl/DefaultFacesFlowProvider.java b/impl/src/main/java/org/apache/myfaces/flow/impl/DefaultFacesFlowProvider.java
index cc8ca64..49a7912 100644
--- a/impl/src/main/java/org/apache/myfaces/flow/impl/DefaultFacesFlowProvider.java
+++ b/impl/src/main/java/org/apache/myfaces/flow/impl/DefaultFacesFlowProvider.java
@@ -125,12 +125,6 @@ public class DefaultFacesFlowProvider extends FacesFlowProvider
return map;
}
- @Override
- public void onSessionDestroyed()
- {
-
- }
-
protected String getFlowKey(Flow flow)
{
return CURRENT_FLOW_SCOPE_MAP + SEPARATOR_CHAR
diff --git a/impl/src/main/java/org/apache/myfaces/push/WebsocketComponentRenderer.java b/impl/src/main/java/org/apache/myfaces/push/WebsocketComponentRenderer.java
index 758f62f..fa2889f 100644
--- a/impl/src/main/java/org/apache/myfaces/push/WebsocketComponentRenderer.java
+++ b/impl/src/main/java/org/apache/myfaces/push/WebsocketComponentRenderer.java
@@ -119,7 +119,7 @@ public class WebsocketComponentRenderer extends Renderer implements ComponentSys
String channel = component.getChannel();
// TODO: use a single bean and entry point for this algorithm.
- BeanManager beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext());
+ BeanManager beanManager = CDIUtils.getBeanManager(facesContext);
WebsocketChannelTokenBuilderBean channelTokenBean = CDIUtils.get(
beanManager,
@@ -169,7 +169,7 @@ public class WebsocketComponentRenderer extends Renderer implements ComponentSys
else if (scope.equals("session"))
{
sessionTokenBean = (sessionTokenBean != null) ? sessionTokenBean : CDIUtils.get(
- CDIUtils.getBeanManager(facesContext.getExternalContext()),
+ CDIUtils.getBeanManager(facesContext),
WebsocketSessionBean.class);
sessionTokenBean.registerWebsocketSession(channelToken, metadata);
@@ -178,7 +178,7 @@ public class WebsocketComponentRenderer extends Renderer implements ComponentSys
{
//Default application
appTokenBean = (appTokenBean != null) ? appTokenBean : CDIUtils.get(
- CDIUtils.getBeanManager(facesContext.getExternalContext()),
+ CDIUtils.getBeanManager(facesContext),
WebsocketApplicationBean.class);
appTokenBean.registerWebsocketSession(channelToken, metadata);
diff --git a/impl/src/main/java/org/apache/myfaces/push/cdi/PushContextCDIExtension.java b/impl/src/main/java/org/apache/myfaces/push/cdi/PushContextCDIExtension.java
index 69f8613..077cdba 100644
--- a/impl/src/main/java/org/apache/myfaces/push/cdi/PushContextCDIExtension.java
+++ b/impl/src/main/java/org/apache/myfaces/push/cdi/PushContextCDIExtension.java
@@ -34,10 +34,6 @@ public class PushContextCDIExtension implements Extension
{
// Register PushContextFactoryBean as a bean with CDI annotations, so the system
// can take it into account, and use it later when necessary.
- AnnotatedType<PushContextFactoryBean> pushContextFactoryBean =
- beanManager.createAnnotatedType(PushContextFactoryBean.class);
- event.addAnnotatedType(pushContextFactoryBean, pushContextFactoryBean.getJavaClass().getName());
-
AnnotatedType wcbean = beanManager.createAnnotatedType(WebsocketChannelTokenBuilderBean.class);
event.addAnnotatedType(wcbean, wcbean.getJavaClass().getName());
diff --git a/impl/src/main/java/org/apache/myfaces/push/cdi/PushContextFactoryBean.java b/impl/src/main/java/org/apache/myfaces/push/cdi/PushContextFactoryBean.java
deleted file mode 100644
index b871d35..0000000
--- a/impl/src/main/java/org/apache/myfaces/push/cdi/PushContextFactoryBean.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.myfaces.push.cdi;
-
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.enterprise.inject.Disposes;
-import jakarta.enterprise.inject.Produces;
-import jakarta.enterprise.inject.spi.InjectionPoint;
-import jakarta.faces.push.Push;
-import jakarta.faces.push.PushContext;
-
-@ApplicationScoped
-public class PushContextFactoryBean
-{
-
- @Produces
- @Push
- public PushContext createPushContext(InjectionPoint ip)
- {
- Push push = ip.getAnnotated().getAnnotation(Push.class);
- String channel = push.channel().isEmpty() ? ip.getMember().getName() : push.channel();
- return new PushContextImpl(channel);
- }
-
- public void close(@Disposes @Push PushContext context)
- {
- }
-}
diff --git a/impl/src/main/java/org/apache/myfaces/push/cdi/PushContextImpl.java b/impl/src/main/java/org/apache/myfaces/push/cdi/PushContextImpl.java
index 25d8ca6..29ea805 100644
--- a/impl/src/main/java/org/apache/myfaces/push/cdi/PushContextImpl.java
+++ b/impl/src/main/java/org/apache/myfaces/push/cdi/PushContextImpl.java
@@ -57,7 +57,7 @@ public class PushContextImpl implements PushContext
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext != null)
{
- beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext());
+ beanManager = CDIUtils.getBeanManager(facesContext);
}
else
{
@@ -143,7 +143,7 @@ public class PushContextImpl implements PushContext
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext != null)
{
- beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext());
+ beanManager = CDIUtils.getBeanManager(facesContext);
}
else
{
diff --git a/impl/src/main/java/org/apache/myfaces/spi/FacesFlowProvider.java b/impl/src/main/java/org/apache/myfaces/spi/FacesFlowProvider.java
index 85e1630..1116544 100644
--- a/impl/src/main/java/org/apache/myfaces/spi/FacesFlowProvider.java
+++ b/impl/src/main/java/org/apache/myfaces/spi/FacesFlowProvider.java
@@ -29,8 +29,6 @@ import jakarta.faces.flow.Flow;
*/
public abstract class FacesFlowProvider
{
- public abstract void onSessionDestroyed();
-
public abstract Iterator<Flow> getAnnotatedFlows(FacesContext facesContext);
public abstract void doAfterEnterFlow(FacesContext context, Flow flow);
diff --git a/impl/src/main/java/org/apache/myfaces/view/ViewScopeProxyMap.java b/impl/src/main/java/org/apache/myfaces/view/ViewScopeProxyMap.java
index 6ea0762..637e792 100644
--- a/impl/src/main/java/org/apache/myfaces/view/ViewScopeProxyMap.java
+++ b/impl/src/main/java/org/apache/myfaces/view/ViewScopeProxyMap.java
@@ -81,7 +81,7 @@ public class ViewScopeProxyMap extends HashMap<String, Object> implements StateH
if (_viewScopeId == null)
{
- BeanManager beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext());
+ BeanManager beanManager = CDIUtils.getBeanManager(facesContext);
ViewScopeContextualStorageHolder beanHolder =
CDIUtils.get(beanManager, ViewScopeContextualStorageHolder.class);
_viewScopeId = beanHolder.generateUniqueViewScopeId();
diff --git a/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java b/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java
index 7295757..a748ad9 100644
--- a/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java
+++ b/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java
@@ -66,8 +66,6 @@ import org.apache.myfaces.push.EndpointImpl;
import org.apache.myfaces.push.WebsocketConfigurator;
import org.apache.myfaces.push.WebsocketFacesInit;
import org.apache.myfaces.util.lang.ClassUtils;
-import org.apache.myfaces.spi.FacesFlowProvider;
-import org.apache.myfaces.spi.FacesFlowProviderFactory;
import org.apache.myfaces.spi.ServiceProviderFinder;
import org.apache.myfaces.spi.ServiceProviderFinderFactory;
import org.apache.myfaces.view.facelets.ViewPoolProcessor;
@@ -165,17 +163,6 @@ public abstract class AbstractFacesInitializer implements FacesInitializer
ExternalSpecifications.isEL3Available();
ExternalSpecifications.isServlet4Available();
- FacesFlowProviderFactory facesFlowProviderFactory =
- FacesFlowProviderFactory.getFacesFlowProviderFactory(externalContext);
- FacesFlowProvider facesFlowProvider = facesFlowProviderFactory.getFacesFlowProvider(externalContext);
-
- MyFacesHttpSessionListener listener = (MyFacesHttpSessionListener) externalContext.getApplicationMap()
- .get(MyFacesHttpSessionListener.APPLICATION_MAP_KEY);
- if (listener != null)
- {
- listener.setFacesFlowProvider(facesFlowProvider);
- }
-
String useEncryption = servletContext.getInitParameter(StateUtils.USE_ENCRYPTION);
if ("false".equals(useEncryption))
{
diff --git a/impl/src/main/java/org/apache/myfaces/webapp/MyFacesHttpSessionListener.java b/impl/src/main/java/org/apache/myfaces/webapp/MyFacesHttpSessionListener.java
index 2ece7d6..7f5b99a 100644
--- a/impl/src/main/java/org/apache/myfaces/webapp/MyFacesHttpSessionListener.java
+++ b/impl/src/main/java/org/apache/myfaces/webapp/MyFacesHttpSessionListener.java
@@ -29,24 +29,17 @@ import org.apache.myfaces.cdi.view.ViewScopeContext;
import org.apache.myfaces.context.ExceptionHandlerImpl;
import org.apache.myfaces.context.servlet.StartupFacesContextImpl;
import org.apache.myfaces.context.servlet.StartupServletExternalContextImpl;
-import org.apache.myfaces.spi.FacesFlowProvider;
+import org.apache.myfaces.flow.cdi.FlowScopeContext;
public class MyFacesHttpSessionListener implements HttpSessionListener
{
public static final String APPLICATION_MAP_KEY = MyFacesHttpSessionListener.class.getName();
- private FacesFlowProvider facesFlowProvider = null;
-
- public void setFacesFlowProvider(FacesFlowProvider facesFlowProvider)
- {
- this.facesFlowProvider = facesFlowProvider;
- }
-
@Override
public void sessionCreated(HttpSessionEvent event)
{
}
-
+
@Override
public void sessionDestroyed(HttpSessionEvent event)
{
@@ -59,10 +52,7 @@ public class MyFacesHttpSessionListener implements HttpSessionListener
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext != null)
{
- if (facesFlowProvider != null)
- {
- facesFlowProvider.onSessionDestroyed();
- }
+ FlowScopeContext.destroyAll(facesContext);
ViewScopeContext.destroyAll(facesContext);
ClientWindowScopeContext.destroyAll(facesContext);
}
@@ -78,10 +68,7 @@ public class MyFacesHttpSessionListener implements HttpSessionListener
ExceptionHandler exceptionHandler = new ExceptionHandlerImpl();
facesContext = new StartupFacesContextImpl(externalContext, externalContext, exceptionHandler, false);
- if (facesFlowProvider != null)
- {
- facesFlowProvider.onSessionDestroyed();
- }
+ FlowScopeContext.destroyAll(facesContext);
ViewScopeContext.destroyAll(facesContext);
ClientWindowScopeContext.destroyAll(facesContext);
}
diff --git a/impl/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension b/impl/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension
index 5ba850d..b8ef9c3 100644
--- a/impl/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension
+++ b/impl/src/main/resources/META-INF/services/jakarta.enterprise.inject.spi.Extension
@@ -8,6 +8,5 @@ org.apache.myfaces.cdi.view.ViewScopeExtension
org.apache.myfaces.cdi.view.ViewTransientScopeExtension
org.apache.myfaces.config.annotation.CdiAnnotationProviderExtension
org.apache.myfaces.push.cdi.PushContextCDIExtension
-org.apache.myfaces.flow.cdi.FlowBuilderExtension
org.apache.myfaces.flow.cdi.FlowScopeExtension
org.apache.myfaces.cdi.clientwindow.ClientWindowScopeExtension
\ No newline at end of file