You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by gp...@apache.org on 2013/05/10 22:14:25 UTC

git commit: DELTASPIKE-288 ConfigDescriptorValidator (optional)

Updated Branches:
  refs/heads/master cb8c0861e -> d3d26f8de


DELTASPIKE-288 ConfigDescriptorValidator (optional)


Project: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/commit/d3d26f8d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/tree/d3d26f8d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/diff/d3d26f8d

Branch: refs/heads/master
Commit: d3d26f8dee03e96fc21722bdbb3c501d97ba6317
Parents: cb8c086
Author: gpetracek <gp...@apache.org>
Authored: Fri May 10 21:55:20 2013 +0200
Committer: gpetracek <gp...@apache.org>
Committed: Fri May 10 22:13:09 2013 +0200

----------------------------------------------------------------------
 .../spi/config/view/ConfigDescriptorValidator.java |   37 ++++++++
 .../core/spi/config/view/ViewConfigRoot.java       |    3 +
 .../config/view/DefaultViewConfigResolver.java     |   12 ++-
 .../jsf/impl/config/view/ViewConfigExtension.java  |   46 ++++++++--
 .../config/view/ViewConfigResolverProducer.java    |    5 +-
 .../view/custom/uc005/InvalidPageConfig.java       |   27 ++++++
 .../TestInvalidConfigDescriptorValidator.java      |   34 +++++++
 .../uc005/TestValidConfigDescriptorValidator.java  |   34 +++++++
 .../config/view/custom/uc005/ValidPageConfig.java  |   27 ++++++
 .../config/view/custom/uc005/ViewConfigTest.java   |   73 +++++++++++++++
 10 files changed, 287 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d3d26f8d/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/config/view/ConfigDescriptorValidator.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/config/view/ConfigDescriptorValidator.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/config/view/ConfigDescriptorValidator.java
new file mode 100644
index 0000000..e424a37
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/config/view/ConfigDescriptorValidator.java
@@ -0,0 +1,37 @@
+/*
+ * 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.deltaspike.core.spi.config.view;
+
+import org.apache.deltaspike.core.api.config.view.metadata.ConfigDescriptor;
+
+/**
+ * Allows to validate the final view-config descriptors before they get deployed.
+ * Since the config-descriptor contains e.g. the final path,
+ * it's also possible to validate if the corresponding file exists.
+ * Use {@link ViewConfigRoot} to configure 1-n validators.
+ */
+public interface ConfigDescriptorValidator
+{
+    /**
+     * Validates the given config-descriptor
+     * @param configDescriptor (merged) config-descriptor directly before it gets deployed
+     * @return true if the descriptor is valid, false otherwise
+     */
+    boolean isValid(ConfigDescriptor configDescriptor);
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d3d26f8d/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/config/view/ViewConfigRoot.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/config/view/ViewConfigRoot.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/config/view/ViewConfigRoot.java
index 7f56f0d..19fef57 100644
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/config/view/ViewConfigRoot.java
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/config/view/ViewConfigRoot.java
@@ -49,4 +49,7 @@ public @interface ViewConfigRoot
 
     Class<? extends ViewConfigInheritanceStrategy> viewConfigInheritanceStrategy()
         default ViewConfigInheritanceStrategy.class;
+
+    Class<? extends ConfigDescriptorValidator>[] configDescriptorValidators()
+        default { };
 }

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d3d26f8d/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultViewConfigResolver.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultViewConfigResolver.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultViewConfigResolver.java
index 32f5de1..e8496ac 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultViewConfigResolver.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultViewConfigResolver.java
@@ -21,6 +21,7 @@ package org.apache.deltaspike.jsf.impl.config.view;
 import org.apache.deltaspike.core.api.config.view.DefaultErrorView;
 import org.apache.deltaspike.core.api.config.view.ViewConfig;
 import org.apache.deltaspike.core.api.config.view.metadata.ConfigDescriptor;
+import org.apache.deltaspike.core.spi.config.view.ConfigDescriptorValidator;
 import org.apache.deltaspike.core.api.config.view.metadata.ViewConfigDescriptor;
 import org.apache.deltaspike.core.api.config.view.metadata.ViewConfigResolver;
 import org.apache.deltaspike.core.spi.config.view.ConfigNodeConverter;
@@ -55,7 +56,8 @@ public class DefaultViewConfigResolver implements ViewConfigResolver
 
     public DefaultViewConfigResolver(ViewConfigNode rootViewConfigNode,
                                      ConfigNodeConverter configNodeConverter,
-                                     ViewConfigInheritanceStrategy inheritanceStrategy)
+                                     ViewConfigInheritanceStrategy inheritanceStrategy,
+                                     List<ConfigDescriptorValidator> configDescriptorValidators)
     {
         Map<Class<? extends ViewConfig>, ViewConfigDescriptor> viewConfigs =
             new HashMap<Class<? extends ViewConfig>, ViewConfigDescriptor>();
@@ -78,6 +80,14 @@ public class DefaultViewConfigResolver implements ViewConfigResolver
             currentNode.getInheritedMetaData().addAll(inheritanceStrategy.resolveInheritedMetaData(currentNode));
             ConfigDescriptor currentConfigDescriptor = configNodeConverter.convert(currentNode);
 
+            for (ConfigDescriptorValidator validator : configDescriptorValidators)
+            {
+                if (!validator.isValid(currentConfigDescriptor))
+                {
+                    throw new IllegalStateException(currentConfigDescriptor.getConfigClass().getName() + " is invalid");
+                }
+            }
+
             if (currentConfigDescriptor instanceof ViewConfigDescriptor)
             {
                 ViewConfigDescriptor currentViewConfigDescriptor = (ViewConfigDescriptor) currentConfigDescriptor;

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d3d26f8d/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/ViewConfigExtension.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/ViewConfigExtension.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/ViewConfigExtension.java
index 69921de..4620262 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/ViewConfigExtension.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/ViewConfigExtension.java
@@ -19,6 +19,7 @@
 package org.apache.deltaspike.jsf.impl.config.view;
 
 import org.apache.deltaspike.core.api.config.view.ViewConfig;
+import org.apache.deltaspike.core.spi.config.view.ConfigDescriptorValidator;
 import org.apache.deltaspike.core.api.config.view.metadata.InlineViewMetaData;
 import org.apache.deltaspike.core.api.config.view.metadata.ViewConfigResolver;
 import org.apache.deltaspike.core.spi.activation.Deactivatable;
@@ -42,6 +43,7 @@ import javax.enterprise.inject.spi.Extension;
 import javax.enterprise.inject.spi.ProcessAnnotatedType;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Constructor;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
@@ -289,6 +291,7 @@ public class ViewConfigExtension implements Extension, Deactivatable
         {
             ConfigNodeConverter configNodeConverter = new DefaultConfigNodeConverter();
             ViewConfigInheritanceStrategy inheritanceStrategy = new DefaultViewConfigInheritanceStrategy();
+            List<ConfigDescriptorValidator> configDescriptorValidators = new ArrayList<ConfigDescriptorValidator>();
 
             for (Annotation annotation : this.rootViewConfigNode.getMetaData())
             {
@@ -299,8 +302,9 @@ public class ViewConfigExtension implements Extension, Deactivatable
                     configNodeConverter = createCustomConfigNodeConverter(viewConfigRoot, configNodeConverter);
                     inheritanceStrategy = createCustomInheritanceStrategy(viewConfigRoot, inheritanceStrategy);
 
-                    this.viewConfigResolver =
-                            createCustomViewConfigResolver(viewConfigRoot, configNodeConverter, inheritanceStrategy);
+                    configDescriptorValidators = createCustomConfigDescriptorValidators(viewConfigRoot);
+                    this.viewConfigResolver = createCustomViewConfigResolver(
+                            viewConfigRoot, configNodeConverter, inheritanceStrategy, configDescriptorValidators);
                     break;
                 }
             }
@@ -308,7 +312,7 @@ public class ViewConfigExtension implements Extension, Deactivatable
             if (this.viewConfigResolver == null)
             {
                 this.viewConfigResolver = new DefaultViewConfigResolver(
-                        this.rootViewConfigNode, configNodeConverter, inheritanceStrategy);
+                        this.rootViewConfigNode, configNodeConverter, inheritanceStrategy, configDescriptorValidators);
             }
             resetRootNode();
         }
@@ -316,7 +320,8 @@ public class ViewConfigExtension implements Extension, Deactivatable
 
     private ViewConfigResolver createCustomViewConfigResolver(ViewConfigRoot viewConfigRoot,
                                                               ConfigNodeConverter configNodeConverter,
-                                                              ViewConfigInheritanceStrategy inheritanceStrategy)
+                                                              ViewConfigInheritanceStrategy inheritanceStrategy,
+                                                              List<ConfigDescriptorValidator> validators)
     {
         Class<? extends ViewConfigResolver> viewConfigResolverClass = viewConfigRoot.viewConfigResolver();
         if (!ViewConfigResolver.class.equals(viewConfigResolverClass))
@@ -325,14 +330,17 @@ public class ViewConfigExtension implements Extension, Deactivatable
             {
                 Constructor<? extends ViewConfigResolver> viewConfigResolverConstructor = viewConfigResolverClass
                         .getConstructor(new Class[]{
-                            ViewConfigNode.class, ConfigNodeConverter.class, ViewConfigInheritanceStrategy.class});
+                            ViewConfigNode.class,
+                            ConfigNodeConverter.class,
+                            ViewConfigInheritanceStrategy.class,
+                            List.class});
 
                 return viewConfigResolverConstructor
-                        .newInstance(this.rootViewConfigNode, configNodeConverter, inheritanceStrategy);
+                        .newInstance(this.rootViewConfigNode, configNodeConverter, inheritanceStrategy, validators);
             }
             catch (Exception e)
             {
-                ExceptionUtils.throwAsRuntimeException(e);
+                throw ExceptionUtils.throwAsRuntimeException(e);
             }
         }
         return null;
@@ -351,7 +359,7 @@ public class ViewConfigExtension implements Extension, Deactivatable
             }
             catch (Exception e)
             {
-                ExceptionUtils.throwAsRuntimeException(e);
+                throw ExceptionUtils.throwAsRuntimeException(e);
             }
         }
         return defaultConverter;
@@ -370,12 +378,32 @@ public class ViewConfigExtension implements Extension, Deactivatable
             }
             catch (Exception e)
             {
-                ExceptionUtils.throwAsRuntimeException(e);
+                throw ExceptionUtils.throwAsRuntimeException(e);
             }
         }
         return defaultStrategy;
     }
 
+    private List<ConfigDescriptorValidator> createCustomConfigDescriptorValidators(ViewConfigRoot viewConfigRoot)
+    {
+        List<ConfigDescriptorValidator> result = new ArrayList<ConfigDescriptorValidator>();
+
+        for (Class<? extends ConfigDescriptorValidator> validatorClass : viewConfigRoot.configDescriptorValidators())
+        {
+            try
+            {
+                ConfigDescriptorValidator validator = validatorClass.newInstance();
+                result.add(validator);
+            }
+            catch (Exception e)
+            {
+                throw ExceptionUtils.throwAsRuntimeException(e);
+            }
+        }
+
+        return result;
+    }
+
     public void freeViewConfigCache(@Observes BeforeShutdown bs)
     {
         this.viewConfigResolver = null;

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d3d26f8d/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/ViewConfigResolverProducer.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/ViewConfigResolverProducer.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/ViewConfigResolverProducer.java
index 9d12b09..1392e2e 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/ViewConfigResolverProducer.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/ViewConfigResolverProducer.java
@@ -18,12 +18,14 @@
  */
 package org.apache.deltaspike.jsf.impl.config.view;
 
+import org.apache.deltaspike.core.spi.config.view.ConfigDescriptorValidator;
 import org.apache.deltaspike.core.api.config.view.metadata.ViewConfigResolver;
 
 import javax.enterprise.context.ApplicationScoped;
 import javax.enterprise.inject.Produces;
 import javax.inject.Inject;
 import java.lang.annotation.Annotation;
+import java.util.ArrayList;
 import java.util.HashSet;
 
 @ApplicationScoped
@@ -48,7 +50,8 @@ public class ViewConfigResolverProducer
         if (!viewConfigExtension.isActivated())
         {
             return new DefaultViewConfigResolver(
-                new FolderConfigNode(null, null, new HashSet<Annotation>()), null, null);
+                new FolderConfigNode(
+                    null, null, new HashSet<Annotation>()), null, null, new ArrayList<ConfigDescriptorValidator>());
         }
 
         if (!viewConfigExtension.isTransformed()) //esp. for easier unit-tests

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d3d26f8d/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/InvalidPageConfig.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/InvalidPageConfig.java b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/InvalidPageConfig.java
new file mode 100644
index 0000000..f3fad7e
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/InvalidPageConfig.java
@@ -0,0 +1,27 @@
+/*
+ * 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.deltaspike.test.jsf.impl.config.view.custom.uc005;
+
+import org.apache.deltaspike.core.api.config.view.ViewConfig;
+import org.apache.deltaspike.core.spi.config.view.ViewConfigRoot;
+
+@ViewConfigRoot(configDescriptorValidators = TestInvalidConfigDescriptorValidator.class)
+class InvalidPageConfig implements ViewConfig
+{
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d3d26f8d/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/TestInvalidConfigDescriptorValidator.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/TestInvalidConfigDescriptorValidator.java b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/TestInvalidConfigDescriptorValidator.java
new file mode 100644
index 0000000..1026586
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/TestInvalidConfigDescriptorValidator.java
@@ -0,0 +1,34 @@
+/*
+ * 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.deltaspike.test.jsf.impl.config.view.custom.uc005;
+
+import org.apache.deltaspike.core.api.config.view.metadata.ConfigDescriptor;
+import org.apache.deltaspike.core.spi.config.view.ConfigDescriptorValidator;
+
+public class TestInvalidConfigDescriptorValidator implements ConfigDescriptorValidator
+{
+    static boolean called;
+
+    @Override
+    public boolean isValid(ConfigDescriptor configDescriptor)
+    {
+        called = true;
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d3d26f8d/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/TestValidConfigDescriptorValidator.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/TestValidConfigDescriptorValidator.java b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/TestValidConfigDescriptorValidator.java
new file mode 100644
index 0000000..673429f
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/TestValidConfigDescriptorValidator.java
@@ -0,0 +1,34 @@
+/*
+ * 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.deltaspike.test.jsf.impl.config.view.custom.uc005;
+
+import org.apache.deltaspike.core.api.config.view.metadata.ConfigDescriptor;
+import org.apache.deltaspike.core.spi.config.view.ConfigDescriptorValidator;
+
+public class TestValidConfigDescriptorValidator implements ConfigDescriptorValidator
+{
+    static boolean called;
+
+    @Override
+    public boolean isValid(ConfigDescriptor configDescriptor)
+    {
+        called = true;
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d3d26f8d/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/ValidPageConfig.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/ValidPageConfig.java b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/ValidPageConfig.java
new file mode 100644
index 0000000..34db690
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/ValidPageConfig.java
@@ -0,0 +1,27 @@
+/*
+ * 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.deltaspike.test.jsf.impl.config.view.custom.uc005;
+
+import org.apache.deltaspike.core.api.config.view.ViewConfig;
+import org.apache.deltaspike.core.spi.config.view.ViewConfigRoot;
+
+@ViewConfigRoot(configDescriptorValidators = TestValidConfigDescriptorValidator.class)
+class ValidPageConfig implements ViewConfig
+{
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d3d26f8d/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/ViewConfigTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/ViewConfigTest.java b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/ViewConfigTest.java
new file mode 100644
index 0000000..ff540a0
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/config/view/custom/uc005/ViewConfigTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.deltaspike.test.jsf.impl.config.view.custom.uc005;
+
+import org.apache.deltaspike.jsf.impl.config.view.ViewConfigExtension;
+import org.apache.deltaspike.jsf.impl.config.view.ViewConfigResolverProducer;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ViewConfigTest
+{
+    private ViewConfigExtension viewConfigExtension;
+
+    private ViewConfigResolverProducer viewConfigResolverProducer;
+
+    @Before
+    public void before()
+    {
+        this.viewConfigExtension = new ViewConfigExtension();
+        this.viewConfigResolverProducer = new ViewConfigResolverProducer(this.viewConfigExtension);
+    }
+
+    @After
+    public void after()
+    {
+        this.viewConfigExtension.freeViewConfigCache(null);
+    }
+
+    @Test
+    public void testCustomConfigDescriptorValidatorInvalid()
+    {
+        this.viewConfigExtension.addPageDefinition(InvalidPageConfig.class);
+
+        try
+        {
+            this.viewConfigResolverProducer.createViewConfigResolver();
+        }
+        catch (IllegalStateException e)
+        {
+            Assert.assertTrue(TestInvalidConfigDescriptorValidator.called);
+            Assert.assertTrue(e.getMessage().contains(InvalidPageConfig.class.getName()));
+            return;
+        }
+        Assert.fail();
+    }
+
+    @Test
+    public void testCustomConfigDescriptorValidatorValid()
+    {
+        this.viewConfigExtension.addPageDefinition(ValidPageConfig.class);
+
+        this.viewConfigResolverProducer.createViewConfigResolver();
+        Assert.assertTrue(TestValidConfigDescriptorValidator.called);
+    }
+}