You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2017/02/03 01:48:37 UTC

svn commit: r1781492 - in /myfaces/core/branches/2.3.x: api/src/main/java/javax/faces/convert/ api/src/main/java/javax/faces/validator/ impl/src/main/java/org/apache/myfaces/application/ impl/src/main/java/org/apache/myfaces/cdi/behavior/ impl/src/main...

Author: lu4242
Date: Fri Feb  3 01:48:37 2017
New Revision: 1781492

URL: http://svn.apache.org/viewvc?rev=1781492&view=rev
Log:
MYFACES-4079 Implement CDI changes for JSF 2.3 (@FacesConverter and @FacesValidator)

Added:
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/_ApplicationUtils.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/behavior/
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/ConverterInfo.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/DynamicConverterProducer.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterAnnotationLiteral.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterCDIWrapper.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterExtension.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/DynamicValidatorProducer.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorAnnotationLiteral.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorCDIWrapper.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorExtension.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/ValidatorInfo.java
Modified:
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/convert/FacesConverter.java
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/validator/FacesValidator.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
    myfaces/core/branches/2.3.x/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension

Modified: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/convert/FacesConverter.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/convert/FacesConverter.java?rev=1781492&r1=1781491&r2=1781492&view=diff
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/convert/FacesConverter.java (original)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/convert/FacesConverter.java Fri Feb  3 01:48:37 2017
@@ -23,13 +23,15 @@ import java.lang.annotation.Inherited;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
+import javax.inject.Qualifier;
 
 /**
  * @since 2.0
  */
 @Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
+@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
 @Inherited
+@Qualifier
 public @interface FacesConverter
 {
     /**
@@ -44,4 +46,6 @@ public @interface FacesConverter
      * @return
      */
     public String value() default "";
+    
+    public boolean managed() default false;
 }

Modified: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/validator/FacesValidator.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/validator/FacesValidator.java?rev=1781492&r1=1781491&r2=1781492&view=diff
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/validator/FacesValidator.java (original)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/validator/FacesValidator.java Fri Feb  3 01:48:37 2017
@@ -23,6 +23,7 @@ import java.lang.annotation.Inherited;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
+import javax.inject.Qualifier;
 
 /**
  * @since 2.0
@@ -30,6 +31,7 @@ import java.lang.annotation.Target;
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.TYPE)
 @Inherited
+@Qualifier
 public @interface FacesValidator
 {
     /**
@@ -43,4 +45,7 @@ public @interface FacesValidator
      * {@link javax.faces.application.Application#addDefaultValidatorId(java.lang.String)}.</ 
      */
     boolean isDefault() default false;
+    
+    public boolean managed() default false;
+
 }

Modified: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java?rev=1781492&r1=1781491&r2=1781492&view=diff
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java (original)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java Fri Feb  3 01:48:37 2017
@@ -46,6 +46,7 @@ import javax.el.ExpressionFactory;
 import javax.el.MethodExpression;
 import javax.el.ValueExpression;
 import javax.faces.FacesException;
+import javax.faces.FacesWrapper;
 import javax.faces.application.Application;
 import javax.faces.application.NavigationHandler;
 import javax.faces.application.ProjectStage;
@@ -67,6 +68,7 @@ import javax.faces.component.search.Sear
 import javax.faces.context.FacesContext;
 import javax.faces.convert.Converter;
 import javax.faces.convert.DateTimeConverter;
+import javax.faces.convert.FacesConverter;
 import javax.faces.el.MethodBinding;
 import javax.faces.el.PropertyResolver;
 import javax.faces.el.ReferenceSyntaxException;
@@ -85,6 +87,7 @@ import javax.faces.render.ClientBehavior
 import javax.faces.render.RenderKit;
 import javax.faces.render.Renderer;
 import javax.faces.render.RendererWrapper;
+import javax.faces.validator.FacesValidator;
 import javax.faces.validator.Validator;
 import javax.faces.view.ViewDeclarationLanguage;
 import javax.naming.Context;
@@ -96,6 +99,8 @@ import org.apache.myfaces.application.cd
 import org.apache.myfaces.cdi.util.ExternalArtifactResolver;
 import org.apache.myfaces.application.cdi.ValidatorWrapper;
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
+import org.apache.myfaces.cdi.converter.FacesConverterCDIWrapper;
+import org.apache.myfaces.cdi.validator.FacesValidatorCDIWrapper;
 import org.apache.myfaces.component.search.AllSearchKeywordResolver;
 import org.apache.myfaces.component.search.ChildSearchKeywordResolver;
 import org.apache.myfaces.component.search.CompositeComponentParentSearchKeywordResolver;
@@ -244,6 +249,12 @@ public class ApplicationImpl extends App
     private List<Class<? extends Converter>> _noArgConstructorConverterClasses 
             = new CopyOnWriteArrayList<Class<? extends Converter>>();
     
+    private Map<Class<? extends Converter>, Boolean> _cdiManagedConverterMap
+            = new ConcurrentHashMap<Class<? extends Converter>, Boolean>();
+    
+    private Map<Class<? extends Validator>, Boolean> _cdiManagedValidatorMap
+            = new ConcurrentHashMap<Class<? extends Validator>, Boolean>();
+    
     /** Value of javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE parameter */
     private boolean _dateTimeConverterDefaultTimeZoneIsSystemTimeZone = false; 
     
@@ -613,7 +624,8 @@ public class ApplicationImpl extends App
                 // SystemEventListenerHolder.getListenersForEventClass(java.lang.Class) on it, passing the
                 // systemEventClass
                 // argument. If the list is not empty, perform algorithm traverseListenerList on the list.
-                event = _traverseListenerList(holder.getListenersForEventClass(systemEventClass), systemEventClass,
+                event = _ApplicationUtils._traverseListenerList(
+                        holder.getListenersForEventClass(systemEventClass), systemEventClass,
                                               source, event);
             }
             
@@ -621,7 +633,8 @@ public class ApplicationImpl extends App
             if (uiViewRoot != null)
             {
                 //Call listeners on view level
-                event = _traverseListenerListWithCopy(uiViewRoot.getViewListenersForEventClass(systemEventClass), 
+                event = _ApplicationUtils._traverseListenerListWithCopy(
+                        uiViewRoot.getViewListenersForEventClass(systemEventClass), 
                         systemEventClass, source, event);
             }
 
@@ -1554,13 +1567,40 @@ public class ApplicationImpl extends App
             throw new FacesException("Could not find any registered converter-class by converterId : " + converterId);
         }
 
+        if (!_cdiManagedConverterMap.containsKey(converterClass))
+        {
+            FacesConverter annotation = converterClass.getAnnotation(FacesConverter.class);
+            if (annotation != null && annotation.managed())
+            {
+                _cdiManagedConverterMap.put(converterClass, true);
+            }
+            else
+            {
+                _cdiManagedConverterMap.put(converterClass, false);
+            }
+        }
+        
         try
         {
-            final Converter converter = createConverterInstance(converterClass);
-
-            setConverterProperties(converterClass, converter);
+            Converter converter = null;
             
-            _handleAttachedResourceDependencyAnnotations(FacesContext.getCurrentInstance(), converter);
+            if (Boolean.TRUE.equals(_cdiManagedConverterMap.get(converterClass)))
+            {
+                converter = new FacesConverterCDIWrapper(converterClass, null, converterId);
+                
+                setConverterProperties(converterClass, ((FacesWrapper<Converter>)converter).getWrapped());
+
+                _handleAttachedResourceDependencyAnnotations(FacesContext.getCurrentInstance(), 
+                        ((FacesWrapper<Converter>)converter).getWrapped());
+            }
+            else
+            {
+                converter = createConverterInstance(converterClass);
+
+                setConverterProperties(converterClass, converter);
+
+                _handleAttachedResourceDependencyAnnotations(FacesContext.getCurrentInstance(), converter);
+            }
 
             return converter;
         }
@@ -1650,39 +1690,62 @@ public class ApplicationImpl extends App
                     _converterTargetClassToConverterClassMap.remove(targetClass);
                 }
                 
+                boolean managed = false;
+                if (!_cdiManagedConverterMap.containsKey(converterClass))
+                {
+                    FacesConverter annotation = converterClass.getAnnotation(FacesConverter.class);
+                    if (annotation != null && annotation.managed())
+                    {
+                        _cdiManagedConverterMap.put(converterClass, true);
+                    }
+                    else
+                    {
+                        _cdiManagedConverterMap.put(converterClass, false);
+                    }
+                }
+                
                 Converter converter = null;
                 
-                // check cached constructor information
-                if (!_noArgConstructorConverterClasses.contains(converterClass))
+                if (Boolean.TRUE.equals(_cdiManagedConverterMap.get(converterClass)))
                 {
-                    // the converter class either supports the one-arg constructor
-                    // or has never been processed before
-                    try
+                    converter = new FacesConverterCDIWrapper(converterClass, targetClass, null);
+                    
+                    setConverterProperties(converterClass, ((FacesWrapper<Converter>)converter).getWrapped());
+                }
+                else
+                {
+                    // check cached constructor information
+                    if (!_noArgConstructorConverterClasses.contains(converterClass))
                     {
-                        // look for a constructor that takes a single Class object
-                        // See JSF 1.2 javadoc for Converter
-                        Constructor<? extends Converter> constructor = converterClass
-                                .getConstructor(new Class[] { Class.class });
+                        // the converter class either supports the one-arg constructor
+                        // or has never been processed before
+                        try
+                        {
+                            // look for a constructor that takes a single Class object
+                            // See JSF 1.2 javadoc for Converter
+                            Constructor<? extends Converter> constructor = converterClass
+                                    .getConstructor(new Class[] { Class.class });
+
+                            converter = constructor.newInstance(new Object[] { targetClass });
+                        }
+                        catch (Exception e)
+                        {
+                            // the constructor does not exist
+                            // add the class to the no-arg constructor classes cache
+                            _noArgConstructorConverterClasses.add(converterClass);
 
-                        converter = constructor.newInstance(new Object[] { targetClass });
+                            // use no-arg constructor
+                            converter = createConverterInstance(converterClass);
+                        }
                     }
-                    catch (Exception e)
+                    else
                     {
-                        // the constructor does not exist
-                        // add the class to the no-arg constructor classes cache
-                        _noArgConstructorConverterClasses.add(converterClass);
-                        
                         // use no-arg constructor
                         converter = createConverterInstance(converterClass);
                     }
+                    
+                    setConverterProperties(converterClass, converter);
                 }
-                else
-                {
-                    // use no-arg constructor
-                    converter = createConverterInstance(converterClass);
-                }
-
-                setConverterProperties(converterClass, converter);
 
                 return converter;
             }
@@ -2044,12 +2107,37 @@ public class ApplicationImpl extends App
             log.severe(message);
             throw new FacesException(message);
         }
+        
+        if (!_cdiManagedValidatorMap.containsKey(validatorClass))
+        {
+            FacesValidator annotation = validatorClass.getAnnotation(FacesValidator.class);
+            if (annotation != null && annotation.managed())
+            {
+                _cdiManagedValidatorMap.put(validatorClass, true);
+            }
+            else
+            {
+                _cdiManagedValidatorMap.put(validatorClass, false);
+            }
+        }
 
         try
         {
-            Validator validator = createValidatorInstance(validatorClass);
+            Validator validator = null;
             
-            _handleAttachedResourceDependencyAnnotations(FacesContext.getCurrentInstance(), validator);
+            if (Boolean.TRUE.equals(_cdiManagedValidatorMap.get(validatorClass)))
+            {
+                validator = new FacesValidatorCDIWrapper(validatorClass, validatorId);
+                
+                _handleAttachedResourceDependencyAnnotations(FacesContext.getCurrentInstance(), 
+                        ((FacesWrapper<Validator>)validator).getWrapped());
+            }
+            else
+            {
+                validator = createValidatorInstance(validatorClass);
+        
+                _handleAttachedResourceDependencyAnnotations(FacesContext.getCurrentInstance(), validator);
+            }
             
             return validator;
         }
@@ -2173,41 +2261,6 @@ public class ApplicationImpl extends App
         }
     }
 
-    private static SystemEvent _createEvent(Class<? extends SystemEvent> systemEventClass, Object source,
-                                            SystemEvent event)
-    {
-        if (event == null)
-        {
-            try
-            {
-                Constructor<?>[] constructors = systemEventClass.getConstructors();
-                Constructor<? extends SystemEvent> constructor = null;
-                for (Constructor<?> c : constructors)
-                {
-                    if (c.getParameterTypes().length == 1)
-                    {
-                        // Safe cast, since the constructor belongs
-                        // to a class of type SystemEvent
-                        constructor = (Constructor<? extends SystemEvent>) c;
-                        break;
-                    }
-                }
-                if (constructor != null)
-                {
-                    event = constructor.newInstance(source);
-                }
-
-            }
-            catch (Exception e)
-            {
-                throw new FacesException("Couldn't instanciate system event of type " + 
-                        systemEventClass.getName(), e);
-            }
-        }
-
-        return event;
-    }
-
     private void _handleAnnotations(FacesContext context, Object inspected, UIComponent component)
     {   
         // determine the ProjectStage setting via the given FacesContext
@@ -2584,136 +2637,6 @@ public class ApplicationImpl extends App
         }
     }
 
-    private static SystemEvent _traverseListenerList(List<? extends SystemEventListener> listeners,
-                                                     Class<? extends SystemEvent> systemEventClass, Object source,
-                                                     SystemEvent event)
-    {
-        if (listeners != null && !listeners.isEmpty())
-        {
-            // perf: org.apache.myfaces.application.ApplicationImpl.
-            //    SystemListenerEntry.getSpecificSourceListenersNotNull(Class<?>)
-            // or javax.faces.component.UIComponent.subscribeToEvent(
-            //      Class<? extends SystemEvent>, ComponentSystemEventListener)
-            // creates a ArrayList:
-            for (int i  = 0, size = listeners.size(); i < size; i++)
-            {
-                SystemEventListener listener = listeners.get(i);
-                // Call SystemEventListener.isListenerForSource(java.lang.Object), passing the source argument.
-                // If this returns false, take no action on the listener.
-                if (listener.isListenerForSource(source))
-                {
-                    // Otherwise, if the event to be passed to the listener instances has not yet been constructed,
-                    // construct the event, passing source as the argument to the one-argument constructor that takes
-                    // an Object. This same event instance must be passed to all listener instances.
-                    event = _createEvent(systemEventClass, source, event);
-
-                    // Call SystemEvent.isAppropriateListener(javax.faces.event.FacesListener), passing the listener
-                    // instance as the argument. If this returns false, take no action on the listener.
-                    if (event.isAppropriateListener(listener))
-                    {
-                        // Call SystemEvent.processListener(javax.faces.event.FacesListener), passing the listener
-                        // instance.
-                        event.processListener(listener);
-                    }
-                }
-            }
-        }
-
-        return event;
-    }
-    
-    private static SystemEvent _traverseListenerListWithCopy(List<? extends SystemEventListener> listeners,
-            Class<? extends SystemEvent> systemEventClass, Object source,
-            SystemEvent event)
-    {
-        if (listeners != null && !listeners.isEmpty())
-        {
-            List<SystemEventListener> listenersCopy = new ArrayList<SystemEventListener>();
-            int processedListenerIndex = 0;
-            
-            for (int i = 0; i < listeners.size(); i++)
-            {
-                listenersCopy.add(listeners.get(i));
-            }
-            
-            // If the inner for is succesful, processedListenerIndex == listenersCopy.size()
-            // and the loop will be complete.
-            while (processedListenerIndex < listenersCopy.size())
-            {                
-                for (; processedListenerIndex < listenersCopy.size(); processedListenerIndex++ )
-                {
-                    SystemEventListener listener = listenersCopy.get(processedListenerIndex);
-                    // Call SystemEventListener.isListenerForSource(java.lang.Object), passing the source argument.
-                    // If this returns false, take no action on the listener.
-                    if (listener.isListenerForSource(source))
-                    {
-                        // Otherwise, if the event to be passed to the listener instances has not yet been constructed,
-                        // construct the event, passing source as the argument
-                        // to the one-argument constructor that takes
-                        // an Object. This same event instance must be passed to all listener instances.
-                        event = _createEvent(systemEventClass, source, event);
-    
-                        // Call SystemEvent.isAppropriateListener(javax.faces.event.FacesListener), passing the listener
-                        // instance as the argument. If this returns false, take no action on the listener.
-                        if (event.isAppropriateListener(listener))
-                        {
-                            // Call SystemEvent.processListener(javax.faces.event.FacesListener), passing the listener
-                            // instance.
-                            event.processListener(listener);
-                        }
-                    }
-                }
-                
-                boolean listChanged = false;
-                if (listeners.size() == listenersCopy.size())
-                {
-                    for (int i = 0; i < listenersCopy.size(); i++)
-                    {
-                        if (listenersCopy.get(i) != listeners.get(i))
-                        {
-                            listChanged = true;
-                            break;
-                        }
-                    }
-                }
-                else
-                {
-                    listChanged = true;
-                }
-                
-                if (listChanged)
-                {
-                    for (int i = 0; i < listeners.size(); i++)
-                    {
-                        SystemEventListener listener = listeners.get(i);
-                        
-                        // check if listenersCopy.get(i) is valid
-                        if (i < listenersCopy.size())
-                        {
-                            // The normal case is a listener was added, 
-                            // so as heuristic, check first
-                            // if we can find it at the same location
-                            if (!listener.equals(listenersCopy.get(i)) &&
-                                !listenersCopy.contains(listener))
-                            {
-                                listenersCopy.add(listener);
-                            }
-                        }
-                        else
-                        {
-                            if (!listenersCopy.contains(listener))
-                            {
-                                listenersCopy.add(listener);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        return event;
-    }
-
     /**
      * Method to handle determining if the first request has 
      * been handled by the associated LifecycleImpl.
@@ -2799,10 +2722,11 @@ public class ApplicationImpl extends App
         {
             if (source != null && _sourceClassMap != null)
             {
-                event = _traverseListenerList(_sourceClassMap.get(classSource), systemEventClass, source, event);
+                event = _ApplicationUtils._traverseListenerList(
+                        _sourceClassMap.get(classSource), systemEventClass, source, event);
             }
 
-            _traverseListenerList(_lstSystemEventListener, systemEventClass, source, event);
+            _ApplicationUtils._traverseListenerList(_lstSystemEventListener, systemEventClass, source, event);
         }
 
         private void addListenerNoDuplicate(List<SystemEventListener> listeners, SystemEventListener listener)

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/_ApplicationUtils.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/_ApplicationUtils.java?rev=1781492&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/_ApplicationUtils.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/application/_ApplicationUtils.java Fri Feb  3 01:48:37 2017
@@ -0,0 +1,202 @@
+/*
+ * 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.application;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.List;
+import javax.faces.FacesException;
+import javax.faces.event.SystemEvent;
+import javax.faces.event.SystemEventListener;
+
+/**
+ *
+ * lu4242
+ */
+class _ApplicationUtils
+{
+    
+    static SystemEvent _createEvent(Class<? extends SystemEvent> systemEventClass, Object source,
+                                            SystemEvent event)
+    {
+        if (event == null)
+        {
+            try
+            {
+                Constructor<?>[] constructors = systemEventClass.getConstructors();
+                Constructor<? extends SystemEvent> constructor = null;
+                for (Constructor<?> c : constructors)
+                {
+                    if (c.getParameterTypes().length == 1)
+                    {
+                        // Safe cast, since the constructor belongs
+                        // to a class of type SystemEvent
+                        constructor = (Constructor<? extends SystemEvent>) c;
+                        break;
+                    }
+                }
+                if (constructor != null)
+                {
+                    event = constructor.newInstance(source);
+                }
+
+            }
+            catch (Exception e)
+            {
+                throw new FacesException("Couldn't instanciate system event of type " + 
+                        systemEventClass.getName(), e);
+            }
+        }
+
+        return event;
+    }
+
+    static SystemEvent _traverseListenerList(List<? extends SystemEventListener> listeners,
+                                                     Class<? extends SystemEvent> systemEventClass, Object source,
+                                                     SystemEvent event)
+    {
+        if (listeners != null && !listeners.isEmpty())
+        {
+            // perf: org.apache.myfaces.application.ApplicationImpl.
+            //    SystemListenerEntry.getSpecificSourceListenersNotNull(Class<?>)
+            // or javax.faces.component.UIComponent.subscribeToEvent(
+            //      Class<? extends SystemEvent>, ComponentSystemEventListener)
+            // creates a ArrayList:
+            for (int i  = 0, size = listeners.size(); i < size; i++)
+            {
+                SystemEventListener listener = listeners.get(i);
+                // Call SystemEventListener.isListenerForSource(java.lang.Object), passing the source argument.
+                // If this returns false, take no action on the listener.
+                if (listener.isListenerForSource(source))
+                {
+                    // Otherwise, if the event to be passed to the listener instances has not yet been constructed,
+                    // construct the event, passing source as the argument to the one-argument constructor that takes
+                    // an Object. This same event instance must be passed to all listener instances.
+                    event = _ApplicationUtils._createEvent(systemEventClass, source, event);
+
+                    // Call SystemEvent.isAppropriateListener(javax.faces.event.FacesListener), passing the listener
+                    // instance as the argument. If this returns false, take no action on the listener.
+                    if (event.isAppropriateListener(listener))
+                    {
+                        // Call SystemEvent.processListener(javax.faces.event.FacesListener), passing the listener
+                        // instance.
+                        event.processListener(listener);
+                    }
+                }
+            }
+        }
+
+        return event;
+    }
+    
+    static SystemEvent _traverseListenerListWithCopy(List<? extends SystemEventListener> listeners,
+            Class<? extends SystemEvent> systemEventClass, Object source,
+            SystemEvent event)
+    {
+        if (listeners != null && !listeners.isEmpty())
+        {
+            List<SystemEventListener> listenersCopy = new ArrayList<SystemEventListener>();
+            int processedListenerIndex = 0;
+            
+            for (int i = 0; i < listeners.size(); i++)
+            {
+                listenersCopy.add(listeners.get(i));
+            }
+            
+            // If the inner for is succesful, processedListenerIndex == listenersCopy.size()
+            // and the loop will be complete.
+            while (processedListenerIndex < listenersCopy.size())
+            {                
+                for (; processedListenerIndex < listenersCopy.size(); processedListenerIndex++ )
+                {
+                    SystemEventListener listener = listenersCopy.get(processedListenerIndex);
+                    // Call SystemEventListener.isListenerForSource(java.lang.Object), passing the source argument.
+                    // If this returns false, take no action on the listener.
+                    if (listener.isListenerForSource(source))
+                    {
+                        // Otherwise, if the event to be passed to the listener instances has not yet been constructed,
+                        // construct the event, passing source as the argument
+                        // to the one-argument constructor that takes
+                        // an Object. This same event instance must be passed to all listener instances.
+                        event = _ApplicationUtils._createEvent(systemEventClass, source, event);
+    
+                        // Call SystemEvent.isAppropriateListener(javax.faces.event.FacesListener), passing the listener
+                        // instance as the argument. If this returns false, take no action on the listener.
+                        if (event.isAppropriateListener(listener))
+                        {
+                            // Call SystemEvent.processListener(javax.faces.event.FacesListener), passing the listener
+                            // instance.
+                            event.processListener(listener);
+                        }
+                    }
+                }
+                
+                boolean listChanged = false;
+                if (listeners.size() == listenersCopy.size())
+                {
+                    for (int i = 0; i < listenersCopy.size(); i++)
+                    {
+                        if (listenersCopy.get(i) != listeners.get(i))
+                        {
+                            listChanged = true;
+                            break;
+                        }
+                    }
+                }
+                else
+                {
+                    listChanged = true;
+                }
+                
+                if (listChanged)
+                {
+                    for (int i = 0; i < listeners.size(); i++)
+                    {
+                        SystemEventListener listener = listeners.get(i);
+                        
+                        // check if listenersCopy.get(i) is valid
+                        if (i < listenersCopy.size())
+                        {
+                            // The normal case is a listener was added, 
+                            // so as heuristic, check first
+                            // if we can find it at the same location
+                            if (!listener.equals(listenersCopy.get(i)) &&
+                                !listenersCopy.contains(listener))
+                            {
+                                listenersCopy.add(listener);
+                            }
+                        }
+                        else
+                        {
+                            if (!listenersCopy.contains(listener))
+                            {
+                                listenersCopy.add(listener);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return event;
+    }
+
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/ConverterInfo.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/ConverterInfo.java?rev=1781492&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/ConverterInfo.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/ConverterInfo.java Fri Feb  3 01:48:37 2017
@@ -0,0 +1,118 @@
+/*
+ * 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.converter;
+
+import java.io.Serializable;
+import java.lang.reflect.Type;
+import java.util.Objects;
+
+/**
+ *
+ */
+public class ConverterInfo implements Serializable
+{
+    private Type type;
+    
+    private Class forClass;
+    
+    private String converterId;
+
+    public ConverterInfo(Type type, Class forClass, String converterId)
+    {
+        this.type = type;
+        this.forClass = forClass;
+        this.converterId = converterId;
+    }
+
+    /**
+     * @return the converterId
+     */
+    public String getConverterId()
+    {
+        return converterId;
+    }
+
+    /**
+     * @param converterId the converterId to set
+     */
+    public void setConverterId(String converterId)
+    {
+        this.converterId = converterId;
+    }
+
+    public Class getForClass()
+    {
+        return forClass;
+    }
+
+    public void setForClass(Class forClass)
+    {
+        this.forClass = forClass;
+    }
+
+    public Type getType()
+    {
+        return type;
+    }
+
+    public void setType(Type type)
+    {
+        this.type = type;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int hash = 7;
+        hash = 53 * hash + Objects.hashCode(this.type);
+        hash = 53 * hash + Objects.hashCode(this.forClass);
+        hash = 53 * hash + Objects.hashCode(this.converterId);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (obj == null)
+        {
+            return false;
+        }
+        if (getClass() != obj.getClass())
+        {
+            return false;
+        }
+        final ConverterInfo other = (ConverterInfo) obj;
+        if (!Objects.equals(this.type, other.type))
+        {
+            return false;
+        }
+        if (!Objects.equals(this.forClass, other.forClass))
+        {
+            return false;
+        }
+        if (!Objects.equals(this.converterId, other.converterId))
+        {
+            return false;
+        }
+        return true;
+    }
+
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/DynamicConverterProducer.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/DynamicConverterProducer.java?rev=1781492&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/DynamicConverterProducer.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/DynamicConverterProducer.java Fri Feb  3 01:48:37 2017
@@ -0,0 +1,153 @@
+/*
+ * 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.converter;
+
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import static java.util.Arrays.asList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.Typed;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.PassivationCapable;
+import javax.faces.FacesException;
+import javax.faces.convert.Converter;
+import org.apache.myfaces.shared.util.ClassUtils;
+
+/**
+ *
+ */
+@Typed
+public class DynamicConverterProducer implements Bean<Converter>, Serializable, PassivationCapable
+{
+    private static final long serialVersionUID = 1L;
+
+    private BeanManager beanManager;
+    private ConverterInfo typeInfo;
+    private Set<Type> types;
+    private Class<?> beanClass;
+
+    public DynamicConverterProducer(BeanManager beanManager, ConverterInfo typeInfo)
+    {
+        this.beanManager = beanManager;
+        this.typeInfo = typeInfo;
+        types = new HashSet<Type>(asList(typeInfo.getType(), Object.class));
+        beanClass = ClassUtils.simpleClassForName(typeInfo.getType().getTypeName());
+    }
+
+    @Override
+    public String getId()
+    {
+        String forClass = typeInfo.getForClass() == null ? "" : 
+                ((typeInfo.getForClass() == Object.class) ? "" : typeInfo.getForClass().getName());
+        String converterId = typeInfo.getConverterId() == null ? "" : typeInfo.getConverterId();
+        return ""+typeInfo.getType()+"_"+forClass+"_"+converterId;
+    }
+
+    @Override
+    public Class<?> getBeanClass()
+    {
+        return beanClass;
+    }
+
+    @Override
+    public Set<Type> getTypes()
+    {
+        return types;
+    }
+    
+    @Override
+    public Set<Annotation> getQualifiers()
+    {
+        return Collections.singleton(
+                (Annotation) new FacesConverterAnnotationLiteral(
+                        typeInfo.getForClass() == null ? Object.class : typeInfo.getForClass(), 
+                        typeInfo.getConverterId() == null ? "" : typeInfo.getConverterId(), true));
+    }
+
+    @Override
+    public Class<? extends Annotation> getScope()
+    {
+        return Dependent.class;
+    }
+
+    @Override
+    public String getName()
+    {
+        return null;
+    }
+    
+
+    @Override
+    public Set<Class<? extends Annotation>> getStereotypes()
+    {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public boolean isAlternative()
+    {
+        return false;
+    }
+    
+    @Override
+    public Set<InjectionPoint> getInjectionPoints()
+    {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public boolean isNullable()
+    {
+        return true;
+    }
+    
+    @Override
+    public Converter create(CreationalContext<Converter> cc)
+    {
+        Class<? extends Converter> converterClass = (Class<? extends Converter>) beanClass;        
+        Converter converter = null;
+        try
+        {
+            converter = converterClass.newInstance();
+        }
+        catch (Exception ex)
+        {
+            Logger.getLogger(DynamicConverterProducer.class.getName()).log(
+                    Level.SEVERE, "Could not instantiate converter " + beanClass.getName().toString(), ex);
+            throw new FacesException("Could not instantiate converter: " + beanClass.getName().toString(), ex);
+            
+        }
+        return converter;
+    }
+
+    @Override
+    public void destroy(Converter t, CreationalContext<Converter> cc)
+    {
+    }
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterAnnotationLiteral.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterAnnotationLiteral.java?rev=1781492&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterAnnotationLiteral.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterAnnotationLiteral.java Fri Feb  3 01:48:37 2017
@@ -0,0 +1,98 @@
+/*
+ * 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.converter;
+
+import java.util.Objects;
+import javax.enterprise.util.AnnotationLiteral;
+import javax.faces.convert.FacesConverter;
+
+/**
+ *
+ */
+public class FacesConverterAnnotationLiteral extends AnnotationLiteral<FacesConverter> implements FacesConverter
+{
+    private static final long serialVersionUID = 1L;
+
+    private String value;
+    private Class forClass;
+    private boolean managed;
+
+    public FacesConverterAnnotationLiteral(Class forClass, String value, boolean managed)
+    {
+        this.forClass = forClass;
+        this.value = value;
+        this.managed = managed;
+    }
+
+    @Override
+    public String value()
+    {
+        return value;
+    }
+
+    @Override
+    public Class forClass()
+    {
+        return forClass;
+    }
+
+    @Override
+    public boolean managed()
+    {
+        return managed;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int hash = 7;
+        hash = 59 * hash + Objects.hashCode(this.value);
+        hash = 59 * hash + Objects.hashCode(this.forClass);
+        hash = 59 * hash + (this.managed ? 1 : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (obj == null)
+        {
+            return false;
+        }
+        if (getClass() != obj.getClass())
+        {
+            return false;
+        }
+        final FacesConverterAnnotationLiteral other = (FacesConverterAnnotationLiteral) obj;
+        if (!Objects.equals(this.value, other.value))
+        {
+            return false;
+        }
+        if (!Objects.equals(this.forClass, other.forClass))
+        {
+            return false;
+        }
+        if (this.managed != other.managed)
+        {
+            return false;
+        }
+        return true;
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterCDIWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterCDIWrapper.java?rev=1781492&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterCDIWrapper.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterCDIWrapper.java Fri Feb  3 01:48:37 2017
@@ -0,0 +1,140 @@
+/*
+ * 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.converter;
+
+import javax.faces.FacesWrapper;
+import javax.faces.component.PartialStateHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+import org.apache.myfaces.cdi.util.CDIUtils;
+
+/**
+ *
+ */
+public class FacesConverterCDIWrapper implements PartialStateHolder, Converter, FacesWrapper<Converter>
+{
+    private transient Converter delegate;
+    
+    //private Class<? extends Converter> converterClass;
+    private Class<?> forClass;
+    private String converterId;
+    private boolean _transient;
+
+    public FacesConverterCDIWrapper()
+    {
+    }
+
+    public FacesConverterCDIWrapper(Class<? extends Converter> converterClass, Class<?> forClass, String converterId)
+    {
+        //this.converterClass = converterClass;
+        this.forClass = forClass;
+        this.converterId = converterId;
+    }
+
+    @Override
+    public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException
+    {
+        return getWrapped().getAsObject(context, component, value);
+    }
+
+    @Override
+    public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException
+    {
+        return getWrapped().getAsString(context, component, value);
+    }
+
+    @Override
+    public Converter getWrapped()
+    {
+        if (delegate == null)
+        {
+            if (converterId != null)
+            {
+                delegate = (Converter) CDIUtils.getInstance(CDIUtils.getBeanManager(
+                    FacesContext.getCurrentInstance().getExternalContext()), 
+                        Converter.class, true, new FacesConverterAnnotationLiteral(Object.class, converterId, true));
+            }
+            else if (forClass != null)
+            {
+                delegate = (Converter) CDIUtils.getInstance(CDIUtils.getBeanManager(
+                    FacesContext.getCurrentInstance().getExternalContext()), 
+                        Converter.class, true, new FacesConverterAnnotationLiteral(forClass, "", true));
+            }
+        }
+        return delegate;
+    }
+    
+    @Override
+    public Object saveState(FacesContext context)
+    {
+        if (!initialStateMarked())
+        {
+            Object values[] = new Object[2];
+            //values[0] = converterClass;
+            values[0] = forClass;
+            values[1] = converterId;
+            return values;
+        }
+        return null;
+    }
+
+    @Override
+    public void restoreState(FacesContext context, Object state)
+    {
+        if (state != null)
+        {
+            Object values[] = (Object[])state;
+            //converterClass = (Class)values[0];            
+            forClass = (Class)values[0];
+            converterId = (String)values[1];
+        }
+    }
+
+    @Override
+    public boolean isTransient()
+    {
+        return _transient;
+    }
+
+    @Override
+    public void setTransient(boolean newTransientValue)
+    {
+        _transient = newTransientValue;
+    }
+
+    private boolean _initialStateMarked = false;
+
+    public void clearInitialState()
+    {
+        _initialStateMarked = false;
+    }
+
+    public boolean initialStateMarked()
+    {
+        return _initialStateMarked;
+    }
+
+    public void markInitialState()
+    {
+        _initialStateMarked = true;
+    }
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterExtension.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterExtension.java?rev=1781492&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterExtension.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/converter/FacesConverterExtension.java Fri Feb  3 01:48:37 2017
@@ -0,0 +1,77 @@
+/*
+ * 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.converter;
+
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ProcessManagedBean;
+import javax.faces.convert.FacesConverter;
+
+/**
+ *
+ */
+public class FacesConverterExtension implements Extension
+{
+    private Set<ConverterInfo> types = new HashSet<ConverterInfo>();
+
+    public <T> void collect(@Observes ProcessManagedBean<T> event)
+    {
+        if (event.getAnnotatedBeanClass().isAnnotationPresent(FacesConverter.class))
+        {
+            Annotated annotated = event.getAnnotatedBeanClass();
+            
+            Type type = annotated.getBaseType();
+
+            FacesConverter conv = (FacesConverter) annotated.getAnnotation(FacesConverter.class);
+            
+            if (conv.managed())
+            {
+                boolean hasForClass = !Object.class.equals(conv.forClass());
+                boolean hasValue = conv.value().length() > 0;
+                if (hasForClass || hasValue)
+                {
+                    if (hasForClass)
+                    {
+                        types.add(new ConverterInfo(type, conv.forClass(), ""));
+                    }
+                    if (hasValue)
+                    {
+                        types.add(new ConverterInfo(type, Object.class, conv.value()));
+                    }
+                }
+            }
+        }
+    }
+    
+    public void afterBean(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager)
+    {
+        for (ConverterInfo typeInfo : types)
+        {
+            afterBeanDiscovery.addBean(new DynamicConverterProducer(beanManager, typeInfo));
+        }
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/DynamicValidatorProducer.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/DynamicValidatorProducer.java?rev=1781492&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/DynamicValidatorProducer.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/DynamicValidatorProducer.java Fri Feb  3 01:48:37 2017
@@ -0,0 +1,150 @@
+/*
+ * 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.validator;
+
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import static java.util.Arrays.asList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.Typed;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.PassivationCapable;
+import javax.faces.FacesException;
+import javax.faces.validator.Validator;
+import org.apache.myfaces.shared.util.ClassUtils;
+
+/**
+ *
+ */
+@Typed
+public class DynamicValidatorProducer implements Bean<Validator>, Serializable, PassivationCapable
+{
+    private static final long serialVersionUID = 1L;
+
+    private BeanManager beanManager;
+    private ValidatorInfo typeInfo;
+    private Set<Type> types;
+    private Class<?> beanClass;
+
+    public DynamicValidatorProducer(BeanManager beanManager, ValidatorInfo typeInfo)
+    {
+        this.beanManager = beanManager;
+        this.typeInfo = typeInfo;
+        types = new HashSet<Type>(asList(typeInfo.getType(), Object.class));
+        beanClass = ClassUtils.simpleClassForName(typeInfo.getType().getTypeName());
+    }
+
+    @Override
+    public String getId()
+    {
+        String converterId = typeInfo.getValidatorId() == null ? "" : typeInfo.getValidatorId();
+        return ""+typeInfo.getType()+"_"+converterId;
+    }
+
+    @Override
+    public Class<?> getBeanClass()
+    {
+        return beanClass;
+    }
+
+    @Override
+    public Set<Type> getTypes()
+    {
+        return types;
+    }
+    
+    @Override
+    public Set<Annotation> getQualifiers()
+    {
+        return Collections.singleton(
+                (Annotation) new FacesValidatorAnnotationLiteral(
+                        typeInfo.getValidatorId() == null ? "" : typeInfo.getValidatorId(), false, true));
+    }
+
+    @Override
+    public Class<? extends Annotation> getScope()
+    {
+        return Dependent.class;
+    }
+
+    @Override
+    public String getName()
+    {
+        return null;
+    }
+    
+
+    @Override
+    public Set<Class<? extends Annotation>> getStereotypes()
+    {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public boolean isAlternative()
+    {
+        return false;
+    }
+    
+    @Override
+    public Set<InjectionPoint> getInjectionPoints()
+    {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public boolean isNullable()
+    {
+        return true;
+    }
+    
+    @Override
+    public Validator create(CreationalContext<Validator> cc)
+    {
+        Class<? extends Validator> converterClass = (Class<? extends Validator>) beanClass;        
+        Validator converter = null;
+        try
+        {
+            converter = converterClass.newInstance();
+        }
+        catch (Exception ex)
+        {
+            Logger.getLogger(DynamicValidatorProducer.class.getName()).log(
+                    Level.SEVERE, "Could not instantiate converter " + beanClass.getName().toString(), ex);
+            throw new FacesException("Could not instantiate converter: " + beanClass.getName().toString(), ex);
+            
+        }
+        return converter;
+    }
+
+    @Override
+    public void destroy(Validator t, CreationalContext<Validator> cc)
+    {
+    }
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorAnnotationLiteral.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorAnnotationLiteral.java?rev=1781492&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorAnnotationLiteral.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorAnnotationLiteral.java Fri Feb  3 01:48:37 2017
@@ -0,0 +1,98 @@
+/*
+ * 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.validator;
+
+import java.util.Objects;
+import javax.enterprise.util.AnnotationLiteral;
+import javax.faces.validator.FacesValidator;
+
+/**
+ *
+ */
+public class FacesValidatorAnnotationLiteral extends AnnotationLiteral<FacesValidator> implements FacesValidator
+{
+    private static final long serialVersionUID = 1L;
+
+    private String value;
+    private boolean defaultValue;
+    private boolean managed;
+
+    public FacesValidatorAnnotationLiteral(String value,boolean defaultValue, boolean managed)
+    {
+        this.value = value;
+        this.defaultValue = defaultValue;
+        this.managed = managed;
+    }
+
+    @Override
+    public String value()
+    {
+        return value;
+    }
+
+    @Override
+    public boolean managed()
+    {
+        return managed;
+    }
+
+    @Override
+    public boolean isDefault()
+    {
+        return defaultValue;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int hash = 5;
+        hash = 79 * hash + Objects.hashCode(this.value);
+        hash = 79 * hash + (this.defaultValue ? 1 : 0);
+        hash = 79 * hash + (this.managed ? 1 : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (obj == null)
+        {
+            return false;
+        }
+        if (getClass() != obj.getClass())
+        {
+            return false;
+        }
+        final FacesValidatorAnnotationLiteral other = (FacesValidatorAnnotationLiteral) obj;
+        if (!Objects.equals(this.value, other.value))
+        {
+            return false;
+        }
+        if (this.defaultValue != other.defaultValue)
+        {
+            return false;
+        }
+        if (this.managed != other.managed)
+        {
+            return false;
+        }
+        return true;
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorCDIWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorCDIWrapper.java?rev=1781492&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorCDIWrapper.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorCDIWrapper.java Fri Feb  3 01:48:37 2017
@@ -0,0 +1,118 @@
+/*
+ * 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.validator;
+
+import javax.faces.FacesWrapper;
+import javax.faces.component.PartialStateHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.Validator;
+import javax.faces.validator.ValidatorException;
+import org.apache.myfaces.cdi.util.CDIUtils;
+
+/**
+ *
+ */
+public class FacesValidatorCDIWrapper implements PartialStateHolder, Validator, FacesWrapper<Validator>
+{
+    private transient Validator delegate;
+    
+    private String validatorId;
+    private boolean _transient;
+
+    public FacesValidatorCDIWrapper()
+    {
+    }
+
+    public FacesValidatorCDIWrapper(Class<? extends Validator> validatorClass, String validatorId)
+    {
+        this.validatorId = validatorId;
+    }
+
+    @Override
+    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException
+    {
+        getWrapped().validate(context, component, value);
+    }
+
+    @Override
+    public Validator getWrapped()
+    {
+        if (delegate == null)
+        {
+            delegate = (Validator) CDIUtils.getInstance(CDIUtils.getBeanManager(
+                FacesContext.getCurrentInstance().getExternalContext()), 
+                    Validator.class, true, new FacesValidatorAnnotationLiteral(validatorId, false, true));
+        }
+        return delegate;
+    }
+    
+    @Override
+    public Object saveState(FacesContext context)
+    {
+        if (!initialStateMarked())
+        {
+            Object values[] = new Object[1];
+            values[0] = validatorId;
+            return values;
+        }
+        return null;
+    }
+
+    @Override
+    public void restoreState(FacesContext context, Object state)
+    {
+        if (state != null)
+        {
+            Object values[] = (Object[])state;
+            validatorId = (String)values[0];
+        }
+    }
+
+    @Override
+    public boolean isTransient()
+    {
+        return _transient;
+    }
+
+    @Override
+    public void setTransient(boolean newTransientValue)
+    {
+        _transient = newTransientValue;
+    }
+
+    private boolean _initialStateMarked = false;
+
+    public void clearInitialState()
+    {
+        _initialStateMarked = false;
+    }
+
+    public boolean initialStateMarked()
+    {
+        return _initialStateMarked;
+    }
+
+    public void markInitialState()
+    {
+        _initialStateMarked = true;
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorExtension.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorExtension.java?rev=1781492&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorExtension.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/FacesValidatorExtension.java Fri Feb  3 01:48:37 2017
@@ -0,0 +1,69 @@
+/*
+ * 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.validator;
+
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ProcessManagedBean;
+import javax.faces.validator.FacesValidator;
+
+/**
+ *
+ */
+public class FacesValidatorExtension implements Extension
+{
+    private Set<ValidatorInfo> types = new HashSet<ValidatorInfo>();
+
+    public <T> void collect(@Observes ProcessManagedBean<T> event)
+    {
+        if (event.getAnnotatedBeanClass().isAnnotationPresent(FacesValidator.class))
+        {
+            Annotated annotated = event.getAnnotatedBeanClass();
+            
+            Type type = annotated.getBaseType();
+
+            FacesValidator conv = (FacesValidator) annotated.getAnnotation(FacesValidator.class);
+            
+            if (conv.managed())
+            {
+                boolean hasValue = conv.value().length() > 0;
+                if (hasValue)
+                {
+                    types.add(new ValidatorInfo(type, conv.value()));
+                }
+            }
+        }
+    }
+    
+    public void afterBean(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager)
+    {
+        for (ValidatorInfo typeInfo : types)
+        {
+            afterBeanDiscovery.addBean(new DynamicValidatorProducer(beanManager, typeInfo));
+        }
+    }
+
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/ValidatorInfo.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/ValidatorInfo.java?rev=1781492&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/ValidatorInfo.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/cdi/validator/ValidatorInfo.java Fri Feb  3 01:48:37 2017
@@ -0,0 +1,100 @@
+/*
+ * 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.validator;
+
+import java.io.Serializable;
+import java.lang.reflect.Type;
+import java.util.Objects;
+
+/**
+ *
+ */
+public class ValidatorInfo implements Serializable
+{
+    private Type type;
+    
+    private String validatorId;
+
+    public ValidatorInfo(Type type, String validatorId)
+    {
+        this.type = type;
+        this.validatorId = validatorId;
+    }
+
+    /**
+     * @return the validatorId
+     */
+    public String getValidatorId()
+    {
+        return validatorId;
+    }
+
+    /**
+     * @param validatorId the validatorId to set
+     */
+    public void setValidatorId(String validatorId)
+    {
+        this.validatorId = validatorId;
+    }
+
+    public Type getType()
+    {
+        return type;
+    }
+
+    public void setType(Type type)
+    {
+        this.type = type;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int hash = 7;
+        hash = 53 * hash + Objects.hashCode(this.type);
+        hash = 53 * hash + Objects.hashCode(this.validatorId);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (obj == null)
+        {
+            return false;
+        }
+        if (getClass() != obj.getClass())
+        {
+            return false;
+        }
+        final ValidatorInfo other = (ValidatorInfo) obj;
+        if (!Objects.equals(this.type, other.type))
+        {
+            return false;
+        }
+        if (!Objects.equals(this.validatorId, other.validatorId))
+        {
+            return false;
+        }
+        return true;
+    }
+
+
+}

Modified: myfaces/core/branches/2.3.x/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension?rev=1781492&r1=1781491&r2=1781492&view=diff
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension (original)
+++ myfaces/core/branches/2.3.x/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension Fri Feb  3 01:48:37 2017
@@ -8,3 +8,5 @@ org.apache.myfaces.cdi.faces.FacesScopeC
 org.apache.myfaces.cdi.viewTransient.ViewTransientScopeContextExtension
 org.apache.myfaces.cdi.component.ComponentBindingExtension
 org.apache.myfaces.cdi.bean.ManagedPropertyExtension
+org.apache.myfaces.cdi.converter.FacesConverterExtension
+org.apache.myfaces.cdi.validator.FacesValidatorExtension