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/02/24 10:03:11 UTC

[myfaces] branch master updated: removed ViewScoped SPI and only rely on CDI

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 954ffd4  removed ViewScoped SPI and only rely on CDI
954ffd4 is described below

commit 954ffd4a4e65a91006c0044125d4468183de33bf
Author: Thomas Andraschko <ta...@apache.org>
AuthorDate: Wed Feb 24 11:03:02 2021 +0100

    removed ViewScoped SPI and only rely on CDI
---
 .../viewstate/SerializedViewCollection.java        |  27 ++--
 .../viewstate/StateCacheServerSide.java            |   7 +-
 .../cdi/clientwindow/ClientWindowScopeContext.java |   5 +
 .../myfaces/cdi/view/CDIViewScopeProviderImpl.java | 120 ------------------
 .../myfaces/cdi/view/ViewScopeBeanHolder.java      |  12 ++
 .../apache/myfaces/cdi/view/ViewScopeContext.java  |  67 ++++++++--
 .../myfaces/flow/cdi/FlowScopeBeanHolder.java      |  14 ++-
 .../org/apache/myfaces/spi/ViewScopeProvider.java  |  44 -------
 .../myfaces/spi/ViewScopeProviderFactory.java      |  91 --------------
 .../spi/impl/DefaultViewScopeProviderFactory.java  |  63 ----------
 .../org/apache/myfaces/view/ViewScopeProxyMap.java |  26 ++--
 .../myfaces/webapp/AbstractFacesInitializer.java   |   7 --
 .../myfaces/webapp/MyFacesHttpSessionListener.java |  24 +---
 .../SerializedViewCollectionTestCase.java          | 136 +++++++--------------
 14 files changed, 165 insertions(+), 478 deletions(-)

diff --git a/impl/src/main/java/org/apache/myfaces/application/viewstate/SerializedViewCollection.java b/impl/src/main/java/org/apache/myfaces/application/viewstate/SerializedViewCollection.java
index 7aac177..bd049b4 100644
--- a/impl/src/main/java/org/apache/myfaces/application/viewstate/SerializedViewCollection.java
+++ b/impl/src/main/java/org/apache/myfaces/application/viewstate/SerializedViewCollection.java
@@ -25,8 +25,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.logging.Logger;
 import jakarta.faces.context.FacesContext;
+import java.util.function.Consumer;
+import org.apache.myfaces.cdi.view.ViewScopeContext;
 import org.apache.myfaces.config.MyfacesConfig;
-import org.apache.myfaces.spi.ViewScopeProvider;
 import org.apache.myfaces.util.lang.LRULinkedHashMap;
 
 /**
@@ -59,12 +60,20 @@ class SerializedViewCollection implements Serializable
 
     public void put(FacesContext context, Object state, SerializedViewKey key, SerializedViewKey previousRestoredKey)
     {
-        put(context, state, key, previousRestoredKey, null, null);
+        put(context, state, key, previousRestoredKey, null,
+                (oldViewScopeId) -> ViewScopeContext.destroyAllActive(context, oldViewScopeId));
     }
     
     public synchronized void put(FacesContext context, Object state, 
-        SerializedViewKey key, SerializedViewKey previousRestoredKey,
-        ViewScopeProvider viewScopeProvider, String viewScopeId)
+        SerializedViewKey key, SerializedViewKey previousRestoredKey, String viewScopeId)
+    {
+        put(context, state, key, previousRestoredKey, viewScopeId,
+            (oldViewScopeId) -> ViewScopeContext.destroyAllActive(context, oldViewScopeId));
+    }
+
+    public synchronized void put(FacesContext context, Object state, 
+        SerializedViewKey key, SerializedViewKey previousRestoredKey, String viewScopeId,
+        Consumer<String> destroyCallback)
     {
         if (state == null)
         {
@@ -115,7 +124,7 @@ class SerializedViewCollection implements Serializable
         }
         _serializedViews.put(key, state);
         
-        if (viewScopeProvider != null && viewScopeId != null)
+        if (viewScopeId != null)
         {
             if (_viewScopeIds == null)
             {
@@ -163,7 +172,7 @@ class SerializedViewCollection implements Serializable
 
                     _serializedViews.remove(keyToRemove);
                     
-                    if (viewScopeProvider != null && _viewScopeIds != null)
+                    if (_viewScopeIds != null)
                     {
                         String oldViewScopeId = _viewScopeIds.remove(keyToRemove);
                         if (oldViewScopeId != null)
@@ -173,7 +182,7 @@ class SerializedViewCollection implements Serializable
                             if (vscount < 1)
                             {
                                 _viewScopeIdCounts.remove(oldViewScopeId);
-                                viewScopeProvider.destroyViewScopeMap(context, oldViewScopeId);
+                                destroyCallback.accept(oldViewScopeId);
                             }
                             else
                             {
@@ -206,7 +215,7 @@ class SerializedViewCollection implements Serializable
 
             _serializedViews.remove(key);
             
-            if (viewScopeProvider != null && _viewScopeIds != null)
+            if (_viewScopeIds != null)
             {
                 String oldViewScopeId = _viewScopeIds.remove(key);
                 if (oldViewScopeId != null)
@@ -216,7 +225,7 @@ class SerializedViewCollection implements Serializable
                     if (vscount < 1)
                     {
                         _viewScopeIdCounts.remove(oldViewScopeId);
-                        viewScopeProvider.destroyViewScopeMap(context, oldViewScopeId);
+                        destroyCallback.accept(oldViewScopeId);
                     }
                     else
                     {
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 bd30c3a..df6f771 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
@@ -45,8 +45,6 @@ import jakarta.faces.lifecycle.ClientWindow;
 import org.apache.myfaces.config.MyfacesConfig;
 import org.apache.myfaces.renderkit.RendererUtils;
 import org.apache.myfaces.util.MyFacesObjectInputStream;
-import org.apache.myfaces.spi.ViewScopeProvider;
-import org.apache.myfaces.spi.ViewScopeProviderFactory;
 import org.apache.myfaces.view.ViewScopeProxyMap;
 
 class StateCacheServerSide extends StateCache<Object, Object>
@@ -193,11 +191,8 @@ class StateCacheServerSide extends StateCache<Object, Object>
         }
         if (viewScopeProxyMap != null)
         {
-            ViewScopeProviderFactory factory = ViewScopeProviderFactory.getViewScopeHandlerFactory(
-                context.getExternalContext());
-            ViewScopeProvider handler = factory.getViewScopeHandler(context.getExternalContext());
             viewCollection.put(context, serializeView(context, serializedView), nextKey, key,
-                    handler, viewScopeProxyMap.getViewScopeId());
+                    viewScopeProxyMap.getViewScopeId());
         }
         else
         {
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 d222f0a..d4aa201 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
@@ -215,6 +215,11 @@ public class ClientWindowScopeContext implements Context
         }
     }
 
+    public static void onSessionDestroyed(FacesContext facesContext)
+    {
+        destroyAllActive(facesContext);
+    }
+    
     public static void destroyAllActive(FacesContext facesContext)
     {
         if (facesContext == null)
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/view/CDIViewScopeProviderImpl.java b/impl/src/main/java/org/apache/myfaces/cdi/view/CDIViewScopeProviderImpl.java
deleted file mode 100644
index e81aa58..0000000
--- a/impl/src/main/java/org/apache/myfaces/cdi/view/CDIViewScopeProviderImpl.java
+++ /dev/null
@@ -1,120 +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.cdi.view;
-
-import java.util.Map;
-import jakarta.enterprise.inject.spi.BeanManager;
-import jakarta.faces.context.ExternalContext;
-import jakarta.faces.context.FacesContext;
-import jakarta.servlet.ServletContext;
-import org.apache.myfaces.cdi.util.CDIUtils;
-import org.apache.myfaces.cdi.JsfApplicationArtifactHolder;
-import org.apache.myfaces.spi.ViewScopeProvider;
-
-/**
- *
- * @author Leonardo Uribe
- */
-public class CDIViewScopeProviderImpl extends ViewScopeProvider
-{
-    private BeanManager beanManager;
-    private ViewScopeBeanHolder viewScopeBeanHolder;
-
-    public CDIViewScopeProviderImpl()
-    {
-        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
-        beanManager = CDIUtils.getBeanManager(externalContext);
-        Object context = externalContext.getContext();
-        if (context instanceof ServletContext)
-        {
-            JsfApplicationArtifactHolder appBean =
-                    CDIUtils.get(beanManager, JsfApplicationArtifactHolder.class);
-            appBean.setServletContext((ServletContext) context);
-        }
-    }
-    
-    private ViewScopeBeanHolder getViewScopeBeanHolder()
-    {
-        if (viewScopeBeanHolder == null)
-        {
-            viewScopeBeanHolder = CDIUtils.get(beanManager, ViewScopeBeanHolder.class);
-        }
-        return viewScopeBeanHolder;
-    }
-
-    @Override
-    public Map<String, Object> createViewScopeMap(FacesContext facesContext, String viewScopeId)
-    {
-        return new ViewScopeCDIMap(facesContext, viewScopeId);
-    }
-    
-    @Override
-    public Map<String, Object> restoreViewScopeMap(FacesContext facesContext, String viewScopeId)
-    {
-        return new ViewScopeCDIMap(facesContext, viewScopeId);
-    }
-    
-    @Override
-    public String generateViewScopeId(FacesContext facesContext)
-    {
-        return getViewScopeBeanHolder().generateUniqueViewScopeId();
-    }
-    
-    /**
-     * 
-     */
-    @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)
-        {
-            if (isViewScopeBeanHolderCreated(facesContext))
-            {
-                getViewScopeBeanHolder().destroyBeans();                
-            }
-        }
-    }
-    
-    private boolean isViewScopeBeanHolderCreated(FacesContext facesContext)
-    {
-        if (facesContext.getExternalContext().getSession(false) == null)
-        {
-            return false;
-        }
-        
-        return facesContext.getExternalContext().
-            getSessionMap().containsKey(ViewScopeBeanHolder.CREATED);
-    }
-
-    @Override
-    public void destroyViewScopeMap(FacesContext facesContext, String viewScopeId)
-    {
-        if (isViewScopeBeanHolderCreated(facesContext))
-        {
-            getViewScopeBeanHolder().destroyBeans(viewScopeId);
-        }
-    }
-}
diff --git a/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeBeanHolder.java b/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeBeanHolder.java
index 074bbcc..980b975 100644
--- a/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeBeanHolder.java
+++ b/impl/src/main/java/org/apache/myfaces/cdi/view/ViewScopeBeanHolder.java
@@ -32,6 +32,7 @@ import jakarta.faces.context.ExternalContext;
 import jakarta.faces.context.FacesContext;
 import jakarta.inject.Inject;
 import jakarta.servlet.ServletContext;
+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.context.ExceptionHandlerImpl;
@@ -67,6 +68,17 @@ public class ViewScopeBeanHolder implements Serializable
         storageMap = new ConcurrentHashMap<>();
         FacesContext facesContext = FacesContext.getCurrentInstance();
         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);
+            }
+        }
     }
 
     /**
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 5494861..12fc8d2 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
@@ -57,19 +57,15 @@ public class ViewScopeContext implements Context
         this.passivatingScope = beanManager.isPassivatingScope(getScope());
     }
 
-    protected ViewScopeBeanHolder getViewScopeBeanHolder()
+    protected ViewScopeBeanHolder getOrCreateViewScopeBeanHolder()
     {
-        return getViewScopeBeanHolder(FacesContext.getCurrentInstance());
-    }
-    
-    protected ViewScopeBeanHolder getViewScopeBeanHolder(FacesContext facesContext)
-    {
-        ViewScopeBeanHolder beanHolder = (ViewScopeBeanHolder) facesContext.getExternalContext().getApplicationMap()
+        FacesContext facesContext = FacesContext.getCurrentInstance();
+        ViewScopeBeanHolder beanHolder = (ViewScopeBeanHolder) facesContext.getExternalContext().getSessionMap()
                 .get(ViewScopeBeanHolder.class.getName());
         if (beanHolder == null)
         {
             beanHolder = CDIUtils.get(beanManager, ViewScopeBeanHolder.class);
-            facesContext.getExternalContext().getApplicationMap().put(
+            facesContext.getExternalContext().getSessionMap().put(
                     ViewScopeBeanHolder.class.getName(),
                     beanHolder);
         }
@@ -77,6 +73,12 @@ public class ViewScopeContext implements Context
         return beanHolder;
     }
 
+    protected static ViewScopeBeanHolder getViewScopeBeanHolder(FacesContext facesContext)
+    {
+        return (ViewScopeBeanHolder) facesContext.getExternalContext().getSessionMap()
+                .get(ViewScopeBeanHolder.class.getName());
+    }
+
     public String getCurrentViewScopeId(boolean create)
     {        
         FacesContext facesContext = FacesContext.getCurrentInstance();
@@ -105,7 +107,7 @@ public class ViewScopeContext implements Context
         }
         if (viewScopeId != null)
         {
-            return getViewScopeBeanHolder().getContextualStorage(beanManager, viewScopeId);
+            return getOrCreateViewScopeBeanHolder().getContextualStorage(beanManager, viewScopeId);
         }
         return null;
     }
@@ -231,6 +233,20 @@ public class ViewScopeContext implements Context
         destroyAllActive(storage);
     }
 
+    
+    public static void destroyAllActive(FacesContext context, String viewScopeId)
+    {
+        if (isViewScopeBeanHolderCreated(context))
+        {
+            ViewScopeBeanHolder beanHolder = getViewScopeBeanHolder(context);
+            if (beanHolder != null)
+            {
+                beanHolder.destroyBeans(viewScopeId);
+            }
+        }
+    }
+
+    
     public static void destroyAllActive(ViewScopeContextualStorage storage)
     {
         destroyAllActive(storage, FacesContext.getCurrentInstance());
@@ -271,4 +287,37 @@ public class ViewScopeContext implements Context
         }
     }
 
+    private static boolean isViewScopeBeanHolderCreated(FacesContext facesContext)
+    {
+        if (facesContext.getExternalContext().getSession(false) == null)
+        {
+            return false;
+        }
+        
+        return facesContext.getExternalContext().
+            getSessionMap().containsKey(ViewScopeBeanHolder.CREATED);
+    }
+    
+    public static void onSessionDestroyed(FacesContext facesContext)
+    {
+        if (facesContext == null)
+        {
+            return;
+        }
+        
+        // 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.
+        if (isViewScopeBeanHolderCreated(facesContext))
+        {
+            ViewScopeBeanHolder beanHolder = getViewScopeBeanHolder(facesContext);
+            if (beanHolder != null)
+            {
+                beanHolder.destroyBeans();                
+            }
+        }
+    }
 }
\ No newline at end of file
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
index a20689b..7377d4e 100644
--- a/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeBeanHolder.java
+++ b/impl/src/main/java/org/apache/myfaces/flow/cdi/FlowScopeBeanHolder.java
@@ -42,6 +42,7 @@ 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;
@@ -92,8 +93,19 @@ public class FlowScopeBeanHolder implements Serializable
         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.
diff --git a/impl/src/main/java/org/apache/myfaces/spi/ViewScopeProvider.java b/impl/src/main/java/org/apache/myfaces/spi/ViewScopeProvider.java
deleted file mode 100644
index 276e797..0000000
--- a/impl/src/main/java/org/apache/myfaces/spi/ViewScopeProvider.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.spi;
-
-import java.util.Map;
-import jakarta.faces.context.FacesContext;
-
-/**
- * 
- * 
- * TODO: (Optional) provide something to cleanup the session when a view
- * is discarded.
- * 
- * @author Leonardo Uribe
- */
-public abstract class ViewScopeProvider 
-{
-    public abstract void onSessionDestroyed();
-    
-    public abstract String generateViewScopeId(FacesContext facesContext);
-    
-    public abstract Map<String, Object> createViewScopeMap(FacesContext facesContext, String viewScopeId);
-    
-    public abstract Map<String, Object> restoreViewScopeMap(FacesContext facesContext, String viewScopeId);
-    
-    public abstract void destroyViewScopeMap(FacesContext facesContext, String viewScopeId);
-
-}
diff --git a/impl/src/main/java/org/apache/myfaces/spi/ViewScopeProviderFactory.java b/impl/src/main/java/org/apache/myfaces/spi/ViewScopeProviderFactory.java
deleted file mode 100644
index 4068788..0000000
--- a/impl/src/main/java/org/apache/myfaces/spi/ViewScopeProviderFactory.java
+++ /dev/null
@@ -1,91 +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.spi;
-
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import jakarta.faces.FacesException;
-import jakarta.faces.FacesWrapper;
-import jakarta.faces.context.ExternalContext;
-import org.apache.myfaces.spi.impl.DefaultViewScopeProviderFactory;
-import org.apache.myfaces.spi.impl.SpiUtils;
-
-/**
- *
- * @author Leonardo Uribe
- */
-public abstract class ViewScopeProviderFactory implements FacesWrapper<ViewScopeProviderFactory>
-{    
-    private static final String FACTORY_KEY = ViewScopeProviderFactory.class.getName();
-    
-    public static ViewScopeProviderFactory getViewScopeHandlerFactory(ExternalContext ctx)
-    {
-        ViewScopeProviderFactory instance
-                = (ViewScopeProviderFactory) ctx.getApplicationMap().get(FACTORY_KEY);
-        if (instance != null)
-        {
-            return instance;
-        }
-        ViewScopeProviderFactory lpf = null;
-        try
-        {
-
-            if (System.getSecurityManager() != null)
-            {
-                final ExternalContext ectx = ctx;
-                lpf = (ViewScopeProviderFactory) AccessController.doPrivileged(
-                        (PrivilegedExceptionAction) () -> SpiUtils.build(ectx,
-                                ViewScopeProviderFactory.class,
-                                DefaultViewScopeProviderFactory.class));
-            }
-            else
-            {
-                lpf = (ViewScopeProviderFactory)
-                        SpiUtils.build(ctx, ViewScopeProviderFactory.class,
-                                DefaultViewScopeProviderFactory.class);
-            }
-        }
-        catch (PrivilegedActionException pae)
-        {
-            throw new FacesException(pae);
-        }
-        if (lpf != null)
-        {
-            setViewScopeHandlerFactory(ctx, lpf);
-        }
-        return lpf;
-    }
-
-    public static void setViewScopeHandlerFactory(ExternalContext ctx,
-                                                             ViewScopeProviderFactory instance)
-    {
-        ctx.getApplicationMap().put(FACTORY_KEY, instance);
-    }    
-    
-    public abstract ViewScopeProvider getViewScopeHandler(ExternalContext ctx);
-    
-    @Override
-    public ViewScopeProviderFactory getWrapped()
-    {
-        return null;
-    }
-    
-    public abstract void setViewScopeHandler(ExternalContext ctx, ViewScopeProvider viewScopeHandler);
-}
diff --git a/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultViewScopeProviderFactory.java b/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultViewScopeProviderFactory.java
deleted file mode 100644
index acbaf2b..0000000
--- a/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultViewScopeProviderFactory.java
+++ /dev/null
@@ -1,63 +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.spi.impl;
-
-import jakarta.faces.context.ExternalContext;
-import org.apache.myfaces.cdi.view.CDIViewScopeProviderImpl;
-import org.apache.myfaces.spi.ViewScopeProvider;
-import org.apache.myfaces.spi.ViewScopeProviderFactory;
-import org.apache.myfaces.util.ExternalSpecifications;
-
-/**
- *
- * @author Leonardo Uribe
- */
-public class DefaultViewScopeProviderFactory extends ViewScopeProviderFactory
-{
-    
-    public static final String VIEW_SCOPE_HANDLER = ViewScopeProvider.class.getName();
-    public static final String VIEW_SCOPE_HANDLER_INSTANCE_KEY = VIEW_SCOPE_HANDLER + ".INSTANCE";
-
-    @Override
-    public ViewScopeProvider getViewScopeHandler(ExternalContext externalContext)
-    {
-        // check for cached instance
-        ViewScopeProvider returnValue = (ViewScopeProvider)
-                externalContext.getApplicationMap().get(VIEW_SCOPE_HANDLER_INSTANCE_KEY);
-
-        if (returnValue == null)
-        {
-            if (ExternalSpecifications.isCDIAvailable(externalContext))
-            {
-                returnValue = new CDIViewScopeProviderImpl();
-            }
-
-            // cache the result on the ApplicationMap
-            externalContext.getApplicationMap().put(VIEW_SCOPE_HANDLER_INSTANCE_KEY, returnValue);
-        }
-
-        return returnValue;
-    }
-
-    @Override
-    public void setViewScopeHandler(ExternalContext externalContext, ViewScopeProvider viewScopeHandler)
-    {
-        externalContext.getApplicationMap().put(VIEW_SCOPE_HANDLER_INSTANCE_KEY, viewScopeHandler);
-    }
-}
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 def9f43..715491e 100644
--- a/impl/src/main/java/org/apache/myfaces/view/ViewScopeProxyMap.java
+++ b/impl/src/main/java/org/apache/myfaces/view/ViewScopeProxyMap.java
@@ -18,6 +18,7 @@
  */
 package org.apache.myfaces.view;
 
+import jakarta.enterprise.inject.spi.BeanManager;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
@@ -25,8 +26,10 @@ import java.util.Set;
 import jakarta.faces.component.StateHolder;
 import jakarta.faces.context.FacesContext;
 import jakarta.faces.event.PreDestroyViewMapEvent;
-import org.apache.myfaces.spi.ViewScopeProvider;
-import org.apache.myfaces.spi.ViewScopeProviderFactory;
+import org.apache.myfaces.cdi.util.CDIUtils;
+import org.apache.myfaces.cdi.view.ViewScopeBeanHolder;
+import org.apache.myfaces.cdi.view.ViewScopeCDIMap;
+import org.apache.myfaces.util.ExternalSpecifications;
 
 /**
  * This wrapper has these objectives:
@@ -69,27 +72,20 @@ public class ViewScopeProxyMap extends HashMap<String, Object> implements StateH
             
             if (facesContext != null)
             {
-                ViewScopeProviderFactory factory = ViewScopeProviderFactory.getViewScopeHandlerFactory(
-                    facesContext.getExternalContext());
-
-                ViewScopeProvider handler = factory.getViewScopeHandler(facesContext.getExternalContext());
-
                 // for unittests without CDI
-                if (handler == null)
+                if (!ExternalSpecifications.isCDIAvailable(facesContext.getExternalContext()))
                 {
                     _delegate = new ViewScope();
                     return _delegate;
                 }
-                
+
                 if (_viewScopeId == null)
                 {
-                    _viewScopeId = handler.generateViewScopeId(facesContext);
-                    _delegate = handler.createViewScopeMap(facesContext, _viewScopeId);
-                }
-                else
-                {
-                    _delegate = handler.restoreViewScopeMap(facesContext, _viewScopeId);
+                    BeanManager beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext());
+                    ViewScopeBeanHolder beanHolder = CDIUtils.get(beanManager, ViewScopeBeanHolder.class);
+                    _viewScopeId = beanHolder.generateUniqueViewScopeId();
                 }
+                _delegate = new ViewScopeCDIMap(facesContext, _viewScopeId);
             }
             else
             {
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 b344529..7295757 100644
--- a/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java
+++ b/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java
@@ -31,8 +31,6 @@ import org.apache.myfaces.cdi.util.BeanEntry;
 import org.apache.myfaces.spi.InjectionProvider;
 import org.apache.myfaces.spi.InjectionProviderException;
 import org.apache.myfaces.spi.InjectionProviderFactory;
-import org.apache.myfaces.spi.ViewScopeProvider;
-import org.apache.myfaces.spi.ViewScopeProviderFactory;
 import org.apache.myfaces.util.ExternalSpecifications;
 import org.apache.myfaces.view.facelets.tag.MetaRulesetImpl;
 
@@ -166,10 +164,6 @@ public abstract class AbstractFacesInitializer implements FacesInitializer
             ExternalSpecifications.isCDIAvailable(externalContext);
             ExternalSpecifications.isEL3Available();
             ExternalSpecifications.isServlet4Available();
-            
-            ViewScopeProviderFactory viewScopeProviderFactory =
-                    ViewScopeProviderFactory.getViewScopeHandlerFactory(externalContext);
-            ViewScopeProvider viewScopeProvider = viewScopeProviderFactory.getViewScopeHandler(externalContext);
 
             FacesFlowProviderFactory facesFlowProviderFactory =
                     FacesFlowProviderFactory.getFacesFlowProviderFactory(externalContext);
@@ -179,7 +173,6 @@ public abstract class AbstractFacesInitializer implements FacesInitializer
                     .get(MyFacesHttpSessionListener.APPLICATION_MAP_KEY);
             if (listener != null)
             {
-                listener.setViewScopeProvider(viewScopeProvider);
                 listener.setFacesFlowProvider(facesFlowProvider);
             }
             
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 b25784f..e1b7eba 100644
--- a/impl/src/main/java/org/apache/myfaces/webapp/MyFacesHttpSessionListener.java
+++ b/impl/src/main/java/org/apache/myfaces/webapp/MyFacesHttpSessionListener.java
@@ -25,24 +25,18 @@ import jakarta.servlet.ServletContext;
 import jakarta.servlet.http.HttpSessionEvent;
 import jakarta.servlet.http.HttpSessionListener;
 import org.apache.myfaces.cdi.clientwindow.ClientWindowScopeContext;
+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.spi.ViewScopeProvider;
 
 public class MyFacesHttpSessionListener implements HttpSessionListener
 {
     public static final String APPLICATION_MAP_KEY = MyFacesHttpSessionListener.class.getName();
 
-    private ViewScopeProvider viewScopeProvider = null;
     private FacesFlowProvider facesFlowProvider = null;
-    
-    public void setViewScopeProvider(ViewScopeProvider viewScopeProvider)
-    {
-        this.viewScopeProvider = viewScopeProvider;
-    }
-    
+
     public void setFacesFlowProvider(FacesFlowProvider facesFlowProvider)
     {
         this.facesFlowProvider = facesFlowProvider;
@@ -65,15 +59,12 @@ public class MyFacesHttpSessionListener implements HttpSessionListener
         FacesContext facesContext = FacesContext.getCurrentInstance();
         if (facesContext != null)
         {
-            if (viewScopeProvider != null)
-            {
-                viewScopeProvider.onSessionDestroyed();
-            }
             if (facesFlowProvider != null)
             {
                 facesFlowProvider.onSessionDestroyed();
             }
-            ClientWindowScopeContext.destroyAllActive(facesContext);
+            ViewScopeContext.onSessionDestroyed(facesContext);
+            ClientWindowScopeContext.onSessionDestroyed(facesContext);
         }
         else
         {
@@ -87,15 +78,12 @@ public class MyFacesHttpSessionListener implements HttpSessionListener
                 ExceptionHandler exceptionHandler = new ExceptionHandlerImpl();
                 facesContext = new StartupFacesContextImpl(externalContext, externalContext, exceptionHandler, false);
 
-                if (viewScopeProvider != null)
-                {
-                    viewScopeProvider.onSessionDestroyed();
-                }
                 if (facesFlowProvider != null)
                 {
                     facesFlowProvider.onSessionDestroyed();
                 }
-                ClientWindowScopeContext.destroyAllActive(facesContext);
+                ViewScopeContext.onSessionDestroyed(facesContext);
+                ClientWindowScopeContext.onSessionDestroyed(facesContext);
             }
             finally
             {
diff --git a/impl/src/test/java/org/apache/myfaces/application/viewstate/SerializedViewCollectionTestCase.java b/impl/src/test/java/org/apache/myfaces/application/viewstate/SerializedViewCollectionTestCase.java
index 41f4c53..3b3c343 100644
--- a/impl/src/test/java/org/apache/myfaces/application/viewstate/SerializedViewCollectionTestCase.java
+++ b/impl/src/test/java/org/apache/myfaces/application/viewstate/SerializedViewCollectionTestCase.java
@@ -16,10 +16,8 @@
 
 package org.apache.myfaces.application.viewstate;
 
-import java.util.Map;
-import jakarta.faces.context.FacesContext;
+import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.myfaces.config.MyfacesConfig;
-import org.apache.myfaces.spi.ViewScopeProvider;
 import org.apache.myfaces.test.base.junit.AbstractJsfTestCase;
 import org.junit.Assert;
 import org.junit.Test;
@@ -39,15 +37,15 @@ public class SerializedViewCollectionTestCase extends AbstractJsfTestCase
         String viewId = "/test.xhtml";
         SerializedViewKey key1 = new SerializedViewKeyIntInt(viewId.hashCode(), 1);
         SerializedViewKey key2 = new SerializedViewKeyIntInt(viewId.hashCode(), 2);
+                
+        AtomicInteger destroyed = new AtomicInteger();
         
-        TestViewScopeProvider provider = new TestViewScopeProvider();
-        
-        collection.put(facesContext, new Object[]{null,null,2}, key1, null, provider, "1");
+        collection.put(facesContext, new Object[]{null,null,2}, key1, null, "1", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
-        collection.put(facesContext, new Object[]{null,null,2}, key2, null, provider, "2");
+        collection.put(facesContext, new Object[]{null,null,2}, key2, null, "2", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key2));
         Assert.assertNull(collection.get(key1));
-        Assert.assertEquals(provider.getDestroyCount(), 1);
+        Assert.assertEquals(destroyed.get(), 1);
         
     }
     
@@ -63,18 +61,18 @@ public class SerializedViewCollectionTestCase extends AbstractJsfTestCase
         SerializedViewKey key2 = new SerializedViewKeyIntInt(viewId.hashCode(), 2);
         SerializedViewKey key3 = new SerializedViewKeyIntInt(viewId.hashCode(), 3);
         
-        TestViewScopeProvider provider = new TestViewScopeProvider();
+        AtomicInteger destroyed = new AtomicInteger();
         
-        collection.put(facesContext, new Object[]{null,null,2}, key1, null, provider, "1");
+        collection.put(facesContext, new Object[]{null,null,2}, key1, null, "1", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
-        collection.put(facesContext, new Object[]{null,null,2}, key3, null, provider, "3");
+        collection.put(facesContext, new Object[]{null,null,2}, key3, null, "3", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
         Assert.assertNotNull(collection.get(key3));
-        collection.put(facesContext, new Object[]{null,null,2}, key2, key1, provider, "2");
+        collection.put(facesContext, new Object[]{null,null,2}, key2, key1, "2", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key2));
         Assert.assertNotNull(collection.get(key3));
         Assert.assertNull(collection.get(key1));
-        Assert.assertEquals(provider.getDestroyCount(), 1);
+        Assert.assertEquals(destroyed.get(), 1);
         
     }    
     
@@ -89,20 +87,20 @@ public class SerializedViewCollectionTestCase extends AbstractJsfTestCase
         SerializedViewKey key2 = new SerializedViewKeyIntInt(viewId.hashCode(), 2);
         SerializedViewKey key3 = new SerializedViewKeyIntInt(viewId.hashCode(), 3);
         
-        TestViewScopeProvider provider = new TestViewScopeProvider();
+        AtomicInteger destroyed = new AtomicInteger();
         
-        collection.put(facesContext, new Object[]{null,null,2}, key1, null, provider, "1");
+        collection.put(facesContext, new Object[]{null,null,2}, key1, null, "1", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
-        collection.put(facesContext, new Object[]{null,null,2}, key2, null, provider, "1");
+        collection.put(facesContext, new Object[]{null,null,2}, key2, null, "1", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key2));
         Assert.assertNull(collection.get(key1));
         // Destroy should not happen, because there is still one view holding the viewScopeId.
-        Assert.assertEquals(provider.getDestroyCount(), 0);
-        collection.put(facesContext, new Object[]{null,null,2}, key3, null, provider, "2");
+        Assert.assertEquals(destroyed.get(), 0);
+        collection.put(facesContext, new Object[]{null,null,2}, key3, null, "2", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key3));
         Assert.assertNull(collection.get(key2));
         // Now it should be destroyed the view 1
-        Assert.assertEquals(provider.getDestroyCount(), 1);
+        Assert.assertEquals(destroyed.get(), 1);
     }
     
     @Test
@@ -117,18 +115,18 @@ public class SerializedViewCollectionTestCase extends AbstractJsfTestCase
         SerializedViewKey key2 = new SerializedViewKeyIntInt(viewId.hashCode(), 2);
         SerializedViewKey key3 = new SerializedViewKeyIntInt(viewId.hashCode(), 3);
         
-        TestViewScopeProvider provider = new TestViewScopeProvider();
+        AtomicInteger destroyed = new AtomicInteger();
         
-        collection.put(facesContext, new Object[]{null,null,2}, key1, null, provider, "1");
+        collection.put(facesContext, new Object[]{null,null,2}, key1, null, "1", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
-        collection.put(facesContext, new Object[]{null,null,2}, key3, null, provider, "3");
+        collection.put(facesContext, new Object[]{null,null,2}, key3, null, "3", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
         Assert.assertNotNull(collection.get(key3));
-        collection.put(facesContext, new Object[]{null,null,2}, key2, key1, provider, "1");
+        collection.put(facesContext, new Object[]{null,null,2}, key2, key1, "1", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key2));
         Assert.assertNotNull(collection.get(key3));
         Assert.assertNull(collection.get(key1));
-        Assert.assertEquals(provider.getDestroyCount(), 0);
+        Assert.assertEquals(destroyed.get(), 0);
         
     }   
     
@@ -145,32 +143,32 @@ public class SerializedViewCollectionTestCase extends AbstractJsfTestCase
         SerializedViewKey key3 = new SerializedViewKeyIntInt(viewId.hashCode(), 3);
         SerializedViewKey key4 = new SerializedViewKeyIntInt(viewId.hashCode(), 4);
         
-        TestViewScopeProvider provider = new TestViewScopeProvider();
+        AtomicInteger destroyed = new AtomicInteger();
         
-        collection.put(facesContext, new Object[]{null,null,2}, key1, null, provider, "1");
+        collection.put(facesContext, new Object[]{null,null,2}, key1, null, "1", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
-        collection.put(facesContext, new Object[]{null,null,2}, key2, null, provider, "2");
+        collection.put(facesContext, new Object[]{null,null,2}, key2, null, "2", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
         Assert.assertNotNull(collection.get(key2));
-        collection.put(facesContext, new Object[]{null,null,2}, key3, null, provider, "3");
+        collection.put(facesContext, new Object[]{null,null,2}, key3, null, "3", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
         Assert.assertNotNull(collection.get(key2));
         Assert.assertNotNull(collection.get(key3));
-        collection.put(facesContext, new Object[]{null,null,2}, key1, null, provider, "1");
+        collection.put(facesContext, new Object[]{null,null,2}, key1, null, "1", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
         Assert.assertNotNull(collection.get(key2));
         Assert.assertNotNull(collection.get(key3));
         
         // The are 3 slots, and when enters key4 the algorithm should not discard the most
         // recently used, so key1 and key3 should be preserved and key2 discarded.
-        collection.put(facesContext, new Object[]{null,null,2}, key4, null, provider, "4");
+        collection.put(facesContext, new Object[]{null,null,2}, key4, null, "4", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
         Assert.assertNull(collection.get(key2));
         Assert.assertNotNull(collection.get(key3));
         Assert.assertNotNull(collection.get(key4));
         
 
-        Assert.assertEquals(provider.getDestroyCount(), 1);
+        Assert.assertEquals(destroyed.get(), 1);
     }
     
     @Test
@@ -191,30 +189,30 @@ public class SerializedViewCollectionTestCase extends AbstractJsfTestCase
         SerializedViewKey key8 = new SerializedViewKeyIntInt(viewId.hashCode(), 8);
         SerializedViewKey key9 = new SerializedViewKeyIntInt(viewId.hashCode(), 9);
         
-        TestViewScopeProvider provider = new TestViewScopeProvider();
+        AtomicInteger destroyed = new AtomicInteger();
         
-        collection.put(facesContext, new Object[]{null,null,2}, key1, null, provider, "1");
+        collection.put(facesContext, new Object[]{null,null,2}, key1, null, "1", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
-        collection.put(facesContext, new Object[]{null,null,2}, key2, key1, provider, "2");
+        collection.put(facesContext, new Object[]{null,null,2}, key2, key1, "2", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
         Assert.assertNotNull(collection.get(key2));
-        collection.put(facesContext, new Object[]{null,null,2}, key3, null, provider, "3");
+        collection.put(facesContext, new Object[]{null,null,2}, key3, null, "3", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
         Assert.assertNotNull(collection.get(key2));
         Assert.assertNotNull(collection.get(key3));
-        collection.put(facesContext, new Object[]{null,null,2}, key4, key3, provider, "4");
+        collection.put(facesContext, new Object[]{null,null,2}, key4, key3, "4", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
         Assert.assertNotNull(collection.get(key2));
         Assert.assertNotNull(collection.get(key3));
         Assert.assertNotNull(collection.get(key4));
-        collection.put(facesContext, new Object[]{null,null,2}, key2, null, provider, "2");
+        collection.put(facesContext, new Object[]{null,null,2}, key2, null, "2", (id) -> destroyed.incrementAndGet());
         Assert.assertNotNull(collection.get(key1));
         Assert.assertNotNull(collection.get(key2));
         Assert.assertNotNull(collection.get(key3));
         Assert.assertNotNull(collection.get(key4));
         
         // The collection is full, but under a new key should remove key1
-        collection.put(facesContext, new Object[]{null,null,2}, key5, null, provider, "5");
+        collection.put(facesContext, new Object[]{null,null,2}, key5, null, "5", (id) -> destroyed.incrementAndGet());
         Assert.assertNull(collection.get(key1));
         Assert.assertNotNull(collection.get(key2));
         Assert.assertNotNull(collection.get(key3));
@@ -222,7 +220,7 @@ public class SerializedViewCollectionTestCase extends AbstractJsfTestCase
         Assert.assertNotNull(collection.get(key5));
         
         // The next oldest is key2, but it was refreshed, so the next one in age is key3
-        collection.put(facesContext, new Object[]{null,null,2}, key6, null, provider, "6");
+        collection.put(facesContext, new Object[]{null,null,2}, key6, null, "6", (id) -> destroyed.incrementAndGet());
         Assert.assertNull(collection.get(key1));
         Assert.assertNotNull(collection.get(key2));
         Assert.assertNull(collection.get(key3));
@@ -231,7 +229,7 @@ public class SerializedViewCollectionTestCase extends AbstractJsfTestCase
         Assert.assertNotNull(collection.get(key6));
         
         // There is a sequential view for key6, destroy the oldest one, which is key4
-        collection.put(facesContext, new Object[]{null,null,2}, key7, key6, provider, "7");
+        collection.put(facesContext, new Object[]{null,null,2}, key7, key6, "7", (id) -> destroyed.incrementAndGet());
         Assert.assertNull(collection.get(key1));
         Assert.assertNotNull(collection.get(key2));
         Assert.assertNull(collection.get(key3));
@@ -242,7 +240,7 @@ public class SerializedViewCollectionTestCase extends AbstractJsfTestCase
         
         // Since org.apache.myfaces.NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION is 2, and we have
         // the sequence [key6, key7, key8] , the one to destroy is key6. 
-        collection.put(facesContext, new Object[]{null,null,2}, key8, key7, provider, "8");
+        collection.put(facesContext, new Object[]{null,null,2}, key8, key7, "8", (id) -> destroyed.incrementAndGet());
         Assert.assertNull(collection.get(key1));
         Assert.assertNotNull(collection.get(key2));
         Assert.assertNull(collection.get(key3));
@@ -254,7 +252,7 @@ public class SerializedViewCollectionTestCase extends AbstractJsfTestCase
         
         // This is a sequence [key2, key9], but the oldest one is key2, so in this case
         // key2 should be removed.
-        collection.put(facesContext, new Object[]{null,null,2}, key9, key2, provider, "9");
+        collection.put(facesContext, new Object[]{null,null,2}, key9, key2, "9", (id) -> destroyed.incrementAndGet());
         Assert.assertNull(collection.get(key1));
         Assert.assertNull(collection.get(key2));
         Assert.assertNull(collection.get(key3));
@@ -265,58 +263,6 @@ public class SerializedViewCollectionTestCase extends AbstractJsfTestCase
         Assert.assertNotNull(collection.get(key8));
         Assert.assertNotNull(collection.get(key9));
         
-        Assert.assertEquals(provider.getDestroyCount(), 5);
-    }
-    
-    private static class TestViewScopeProvider extends ViewScopeProvider
-    {
-        private int destroyCount = 0;
-
-        @Override
-        public void onSessionDestroyed()
-        {
-            throw new UnsupportedOperationException("Not supported yet.");
-        }
-
-        @Override
-        public String generateViewScopeId(FacesContext facesContext)
-        {
-            throw new UnsupportedOperationException("Not supported yet.");
-        }
-
-        @Override
-        public Map<String, Object> createViewScopeMap(FacesContext facesContext, String viewScopeId)
-        {
-            throw new UnsupportedOperationException("Not supported yet.");
-        }
-
-        @Override
-        public Map<String, Object> restoreViewScopeMap(FacesContext facesContext, String viewScopeId)
-        {
-            throw new UnsupportedOperationException("Not supported yet.");
-        }
-
-        @Override
-        public void destroyViewScopeMap(FacesContext facesContext, String viewScopeId)
-        {
-            destroyCount++;
-        }
-
-        /**
-         * @return the destroyCount
-         */
-        public int getDestroyCount()
-        {
-            return destroyCount;
-        }
-
-        /**
-         * @param destroyCount the destroyCount to set
-         */
-        public void setDestroyCount(int destroyCount)
-        {
-            this.destroyCount = destroyCount;
-        }
-        
+        Assert.assertEquals(destroyed.get(), 5);
     }
 }