myfaces-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From lu4...@apache.org
Subject svn commit: r1792968 - in /myfaces/core/branches/2.3.x: api/src/main/java/javax/faces/validator/ impl/src/main/java/org/apache/myfaces/component/validate/ impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/
Date Fri, 28 Apr 2017 00:35:53 GMT
Author: lu4242
Date: Fri Apr 28 00:35:53 2017
New Revision: 1792968

URL: http://svn.apache.org/viewvc?rev=1792968&view=rev
Log:
MYFACES-4109 Implement f:validateWholeBean

Added:
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/CopyBeanInterceptorELResolver.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/ValidateWholeBeanComponent.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/WholeBeanValidator.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_BeanValidatorUELUtils.java
      - copied, changed from r1790638, myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/validator/_BeanValidatorUELUtils.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ELContextDecorator.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ValueReferenceResolver.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ValueReferenceWrapper.java
Modified:
    myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/validator/BeanValidator.java
    myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/CoreLibrary.java

Modified: myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/validator/BeanValidator.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/validator/BeanValidator.java?rev=1792968&r1=1792967&r2=1792968&view=diff
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/validator/BeanValidator.java (original)
+++ myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/validator/BeanValidator.java Fri Apr 28 00:35:53 2017
@@ -24,6 +24,7 @@ import java.security.PrivilegedActionExc
 import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
@@ -114,9 +115,20 @@ public class BeanValidator implements Va
      */
     public static final String EMPTY_VALIDATION_GROUPS_PATTERN = "^[\\W,]*$";
     
+    /**
+     * Enable f:validateWholeBean use.
+     */
+    @JSFWebConfigParam(since="2.3", defaultValue = "false", expectedValues = "true, false", group="validation")
+    public static final String ENABLE_VALIDATE_WHOLE_BEAN_PARAM_NAME = 
+            "javax.faces.validator.ENABLE_VALIDATE_WHOLE_BEAN";
+    
     private static final Class<?>[] DEFAULT_VALIDATION_GROUPS_ARRAY = new Class<?>[] { Default.class };
 
     private static final String DEFAULT_VALIDATION_GROUP_NAME = "javax.validation.groups.Default";
+    
+    private static final String CANDIDATE_COMPONENT_VALUES_MAP = "oam.WBV.candidatesMap";
+    
+    private static final String BEAN_VALIDATION_FAILED = "oam.WBV.validationFailed";
 
     private String validationGroups;
 
@@ -189,6 +201,21 @@ public class BeanValidator implements Va
         // Note that validationGroupsArray was initialized when createValidator was called
         Class[] validationGroupsArray = this.validationGroupsArray;
 
+        // JSF 2.3: If the ENABLE_VALIDATE_WHOLE_BEAN_PARAM_NAME application parameter is enabled and this Validator 
+        // instance has validation groups other than or in addition to the Default group
+        boolean containsOtherValidationGroup = false;
+        if (validationGroupsArray != null && validationGroupsArray.length > 0)
+        {
+            for (Class<?> clazz : validationGroupsArray)
+            {
+                if (!Default.class.equals(clazz))
+                {
+                    containsOtherValidationGroup = true;
+                    break;
+                }
+            }
+        }
+        
         // Delegate to Bean Validation.
         Set constraintViolations = validator.validateValue(valueBaseClass, valueProperty, value, validationGroupsArray);
         if (!constraintViolations.isEmpty())
@@ -202,8 +229,59 @@ public class BeanValidator implements Va
                 FacesMessage msg = _MessageUtils.getErrorMessage(context, MESSAGE_ID, args);
                 messages.add(msg);
             }
+            
+            if (isValidateWholeBeanEnabled(context) && containsOtherValidationGroup)
+            {
+                // JSF 2.3: record the fact that this field failed validation so that any <f:validateWholeBean /> 
+                // component later in the tree is able to skip class-level validation for the bean for which this 
+                // particular field is a property. Regardless of whether or not 
+                // ENABLE_VALIDATE_WHOLE_BEAN_PARAM_NAME is set, throw the new exception.            
+                context.getViewRoot().getTransientStateHelper().putTransient(BEAN_VALIDATION_FAILED, Boolean.TRUE);
+            }
+            
             throw new ValidatorException(messages);
         }
+        else
+        {
+            
+            // JSF 2.3: If the returned Set is empty, the ENABLE_VALIDATE_WHOLE_BEAN_PARAM_NAME application parameter
+            // is enabled and this Validator instance has validation groups other than or in addition to the 
+            // Default group
+            if (isValidateWholeBeanEnabled(context) && containsOtherValidationGroup)
+            {
+                // record the fact that this field passed validation so that any <f:validateWholeBean /> component 
+                // later in the tree is able to allow class-level validation for the bean for which this particular 
+                // field is a property.
+                
+                Map<String, Object> candidatesMap = (Map<String, Object>) context.getViewRoot()
+                        .getTransientStateHelper().getTransient(CANDIDATE_COMPONENT_VALUES_MAP);
+                if (candidatesMap == null)
+                {
+                    candidatesMap = new LinkedHashMap<String, Object>();
+                    context.getViewRoot().getTransientStateHelper().putTransient(
+                            CANDIDATE_COMPONENT_VALUES_MAP, candidatesMap);
+                }
+                candidatesMap.put(component.getClientId(context), value);
+            }
+        }
+    }
+    
+    private boolean isValidateWholeBeanEnabled(FacesContext facesContext)
+    {
+        Boolean value = (Boolean) facesContext.getAttributes().get(ENABLE_VALIDATE_WHOLE_BEAN_PARAM_NAME);
+        if (value == null)
+        {
+            String enabled = facesContext.getExternalContext().getInitParameter(ENABLE_VALIDATE_WHOLE_BEAN_PARAM_NAME);
+            if (enabled == null)
+            {
+                value = Boolean.FALSE;
+            }
+            else
+            {
+                value = Boolean.valueOf(enabled);
+            }
+        }
+        return Boolean.TRUE.equals(value);
     }
 
     private javax.validation.Validator createValidator(final ValidatorFactory validatorFactory, FacesContext context)

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/CopyBeanInterceptorELResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/CopyBeanInterceptorELResolver.java?rev=1792968&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/CopyBeanInterceptorELResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/CopyBeanInterceptorELResolver.java Fri Apr 28 00:35:53 2017
@@ -0,0 +1,87 @@
+/*
+ * 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.component.validate;
+
+import java.beans.FeatureDescriptor;
+import java.util.Iterator;
+import javax.el.ELContext;
+import javax.el.ELResolver;
+
+/**
+ *
+ */
+public class CopyBeanInterceptorELResolver extends ELResolver
+{
+    private final ELResolver resolver;
+    private final Object base;
+    private final Object copy;
+
+
+    /**
+     * Constructor is only used internally.
+     * @param elResolver An ELResolver from the current ELContext.
+     */
+    public CopyBeanInterceptorELResolver(final ELResolver elResolver, Object base, Object copy)
+    {
+        this.resolver = elResolver;
+        this.base = base;
+        this.copy = copy;
+    }
+
+    @Override
+    public Object getValue(final ELContext context, final Object base, final Object property)
+    {
+        Object value = resolver.getValue(context, base, property);
+        if (this.base == value || this.base.equals(value))
+        {
+            //Pass the copy instead
+            return this.copy;
+        }
+        else
+        {
+            return value;
+        }
+    }
+
+    public Class<?> getType(final ELContext ctx, final Object base, final Object property)
+    {
+        return resolver.getType(ctx, base, property);
+    }
+
+    public void setValue(final ELContext ctx, final Object base, final Object property, final Object value)
+    {
+        resolver.setValue(ctx, base, property, value);
+    }
+
+    public boolean isReadOnly(final ELContext ctx, final Object base, final Object property)
+    {
+        return resolver.isReadOnly(ctx, base, property);
+    }
+
+    public Iterator<FeatureDescriptor> getFeatureDescriptors(final ELContext ctx, final Object base)
+    {
+        return resolver.getFeatureDescriptors(ctx, base);
+    }
+
+    public Class<?> getCommonPropertyType(final ELContext ctx, final Object base)
+    {
+        return resolver.getCommonPropertyType(ctx, base);
+    }
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/ValidateWholeBeanComponent.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/ValidateWholeBeanComponent.java?rev=1792968&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/ValidateWholeBeanComponent.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/ValidateWholeBeanComponent.java Fri Apr 28 00:35:53 2017
@@ -0,0 +1,103 @@
+/*
+ * 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.component.validate;
+
+import javax.faces.component.UIInput;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.validator.BeanValidator;
+import javax.faces.validator.Validator;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
+import org.apache.myfaces.shared.util.WebConfigParamUtils;
+
+/**
+ *
+ */
+@JSFComponent
+public class ValidateWholeBeanComponent extends UIInput
+{
+    static public final String COMPONENT_FAMILY =
+        "javax.faces.Input";
+    static public final String COMPONENT_TYPE =
+        "org.apache.myfaces.component.validate.ValidateWholeBean";
+
+    public ValidateWholeBeanComponent()
+    {
+        setRendererType(null);
+    }
+
+    @Override
+    public Object getSubmittedValue()
+    {
+        return "WholeBeanValidator";
+    }
+
+    @Override
+    public void addValidator(Validator validator)
+    {
+        // No-op. It does not make sense to allow additional validators to be installed.
+    }
+
+    @Override
+    public void validate(FacesContext context)
+    {
+        
+        Boolean enabled = WebConfigParamUtils.getBooleanInitParameter(context.getExternalContext(), 
+                BeanValidator.ENABLE_VALIDATE_WHOLE_BEAN_PARAM_NAME, Boolean.FALSE);
+        
+        if (Boolean.TRUE.equals(enabled))
+        {
+            
+            //Install WholeBeanValidator
+            Validator[] validators = this.getValidators();
+            if (validators != null && validators.length > 0)
+            {
+                //No op
+            }
+            else
+            {
+                super.addValidator(new WholeBeanValidator());
+            }
+            super.validate(context);
+        }
+    }
+
+    @Override
+    public void setConverter(Converter converter)
+    {
+        // No-op. It does not make sense to allow a converter to be installed.
+    }
+    
+    @JSFProperty
+    public String getValidationGroups()
+    {
+        return (String) getStateHelper().eval(PropertyKeys.validationGroups);
+    }
+    
+    public void setValidationGroups(String validationGroups)
+    {
+        getStateHelper().put(PropertyKeys.validationGroups, validationGroups );
+    }
+    
+    enum PropertyKeys
+    {
+        validationGroups
+    }
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/WholeBeanValidator.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/WholeBeanValidator.java?rev=1792968&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/WholeBeanValidator.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/WholeBeanValidator.java Fri Apr 28 00:35:53 2017
@@ -0,0 +1,605 @@
+/*
+ * 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.component.validate;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+import javax.faces.FacesException;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.component.visit.VisitCallback;
+import javax.faces.component.visit.VisitContext;
+import javax.faces.component.visit.VisitResult;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.BeanValidator;
+import static javax.faces.validator.BeanValidator.EMPTY_VALIDATION_GROUPS_PATTERN;
+import static javax.faces.validator.BeanValidator.MESSAGE_ID;
+import static javax.faces.validator.BeanValidator.VALIDATION_GROUPS_DELIMITER;
+import static javax.faces.validator.BeanValidator.VALIDATOR_FACTORY_KEY;
+import javax.faces.validator.Validator;
+import javax.faces.validator.ValidatorException;
+import javax.validation.ConstraintViolation;
+import javax.validation.MessageInterpolator;
+import javax.validation.Validation;
+import javax.validation.ValidatorFactory;
+import javax.validation.groups.Default;
+import javax.validation.metadata.BeanDescriptor;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
+import org.apache.myfaces.shared.util.MessageUtils;
+import org.apache.myfaces.util.ExternalSpecifications;
+
+/**
+ *
+ */
+public class WholeBeanValidator implements Validator
+{
+    private static final Logger log = Logger.getLogger(WholeBeanValidator.class.getName());
+    
+    private static final Class<?>[] DEFAULT_VALIDATION_GROUPS_ARRAY = new Class<?>[] { Default.class };
+
+    private static final String DEFAULT_VALIDATION_GROUP_NAME = "javax.validation.groups.Default";
+    
+    private static final String CANDIDATE_COMPONENT_VALUES_MAP = "oam.WBV.candidatesMap";
+    
+    private static final String BEAN_VALIDATION_FAILED = "oam.WBV.validationFailed";
+
+    private Class<?>[] validationGroupsArray;
+
+    @Override
+    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException
+    {
+        if (context == null)
+        {
+            throw new NullPointerException("context");
+        }
+        if (component == null)
+        {
+            throw new NullPointerException("component");
+        }
+
+        ValueExpression valueExpression = component.getValueExpression("value");
+        if (valueExpression == null)
+        {
+            log.warning("cannot validate component with empty value: " 
+                    + component.getClientId(context));
+            return;
+        }
+
+        // Obtain a reference to the to-be-validated object and the property name.
+        /*
+        _ValueReferenceWrapper reference = getValueReference(valueExpression, context);
+        if (reference == null)
+        {
+            return;
+        }
+        Object base = reference.getBase();
+        if (base == null)
+        {
+            return;
+        }*/
+        Object base = valueExpression.getValue(context.getELContext());
+                
+        Class<?> valueBaseClass = base.getClass();
+        if (valueBaseClass == null)
+        {
+            return;
+        }
+        /*
+        Object referenceProperty = reference.getProperty();
+        if (!(referenceProperty instanceof String))
+        {
+            // if the property is not a String, the ValueReference does not
+            // point to a bean method, but e.g. to a value in a Map, thus we 
+            // can exit bean validation here
+            return;
+        }
+        String valueProperty = (String) referenceProperty;
+        */
+
+        // Initialize Bean Validation.
+        ValidatorFactory validatorFactory = createValidatorFactory(context);
+        javax.validation.Validator validator = createValidator(validatorFactory, context, 
+                (ValidateWholeBeanComponent)component);
+        BeanDescriptor beanDescriptor = validator.getConstraintsForClass(valueBaseClass);
+        if (!beanDescriptor.isBeanConstrained())
+        {
+            return;
+        }
+        
+        // Note that validationGroupsArray was initialized when createValidator was called
+        Class[] validationGroupsArray = this.validationGroupsArray;
+
+        // Delegate to Bean Validation.
+        
+        // TODO: Use validator.validate(...) over the copy instance.
+        
+        Boolean beanValidationFailed = (Boolean) context.getViewRoot().getTransientStateHelper()
+                .getTransient(BEAN_VALIDATION_FAILED);
+        
+        if (Boolean.TRUE.equals(beanValidationFailed))
+        {
+            // JSF 2.3 Skip class level validation
+            return;
+        }
+        
+        Map<String, Object> candidatesMap = (Map<String, Object>) context.getViewRoot()
+                .getTransientStateHelper().getTransient(CANDIDATE_COMPONENT_VALUES_MAP);
+        if (candidatesMap != null)
+        {
+            Object copy = createBeanCopy(base);
+            
+            UpdateBeanCopyCallback callback = new UpdateBeanCopyCallback(this, base, copy, candidatesMap);
+            context.getViewRoot().visitTree(
+                    VisitContext.createVisitContext(context, candidatesMap.keySet(), null), 
+                    callback);
+            
+            Set constraintViolations = validator.validate(copy, validationGroupsArray);
+            if (!constraintViolations.isEmpty())
+            {
+                Set<FacesMessage> messages = new LinkedHashSet<FacesMessage>(constraintViolations.size());
+                for (Object violation: constraintViolations)
+                {
+                    ConstraintViolation constraintViolation = (ConstraintViolation) violation;
+                    String message = constraintViolation.getMessage();
+                    Object[] args = new Object[]{ message, MessageUtils.getLabel(context, component) };
+                    FacesMessage msg = MessageUtils.getMessage(FacesMessage.SEVERITY_ERROR, MESSAGE_ID, args, context);
+                    messages.add(msg);
+                }
+                throw new ValidatorException(messages);
+            }
+        }
+    }
+    
+    private Object createBeanCopy(Object base)
+    {
+        Object copy = null;
+        try
+        {
+            copy = base.getClass().newInstance();
+        }
+        catch (InstantiationException ex)
+        {
+            Logger.getLogger(WholeBeanValidator.class.getName()).log(Level.FINEST, null, ex);
+        }
+        catch (IllegalAccessException ex)
+        {
+            Logger.getLogger(WholeBeanValidator.class.getName()).log(Level.FINEST, null, ex);
+        }
+        if (base instanceof Serializable)
+        {
+            copy = copySerializableObject(base);
+        }
+        else if(base instanceof Cloneable)
+        { 
+            Method cloneMethod;
+            try
+            {
+                cloneMethod = base.getClass().getMethod("clone");
+                copy = cloneMethod.invoke(base);
+            }
+            catch (NoSuchMethodException ex) 
+            {
+                Logger.getLogger(WholeBeanValidator.class.getName()).log(Level.FINEST, null, ex);
+            }
+            catch (SecurityException ex) 
+            {
+                Logger.getLogger(WholeBeanValidator.class.getName()).log(Level.FINEST, null, ex);
+            }
+            catch (IllegalAccessException ex)
+            {
+                Logger.getLogger(WholeBeanValidator.class.getName()).log(Level.FINEST, null, ex);
+            }
+            catch (IllegalArgumentException ex)
+            {
+                Logger.getLogger(WholeBeanValidator.class.getName()).log(Level.FINEST, null, ex);
+            }
+            catch (InvocationTargetException ex)
+            {
+                Logger.getLogger(WholeBeanValidator.class.getName()).log(Level.FINEST, null, ex);
+            }
+        }
+        else
+        {
+            Class<?> clazz = base.getClass();
+            try
+            {
+                Constructor<?> copyConstructor = clazz.getConstructor(clazz);
+                if (copyConstructor != null)
+                {
+                    copy = copyConstructor.newInstance(base);
+                }
+            }
+            catch (NoSuchMethodException ex)
+            {
+                Logger.getLogger(WholeBeanValidator.class.getName()).log(Level.FINEST, null, ex);
+            }
+            catch (SecurityException ex)
+            {
+                Logger.getLogger(WholeBeanValidator.class.getName()).log(Level.FINEST, null, ex);
+            }
+            catch (IllegalAccessException ex)
+            {
+                Logger.getLogger(WholeBeanValidator.class.getName()).log(Level.FINEST, null, ex);
+            }
+            catch (IllegalArgumentException ex)
+            {
+                Logger.getLogger(WholeBeanValidator.class.getName()).log(Level.FINEST, null, ex);
+            }
+            catch (InvocationTargetException ex)
+            {
+                Logger.getLogger(WholeBeanValidator.class.getName()).log(Level.FINEST, null, ex);
+            }
+            catch (InstantiationException ex)
+            {
+                Logger.getLogger(WholeBeanValidator.class.getName()).log(Level.FINEST, null, ex);
+            }
+        }
+        if (copy == null)
+        {
+            throw new FacesException("Cannot create copy for wholeBeanValidator: "+base.getClass().getName());
+        }
+        return copy;
+    }
+    
+    private Object copySerializableObject(Object base)
+    {
+        Object copy = null;
+        try 
+        {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ObjectOutputStream oos = new ObjectOutputStream(baos);
+            oos.writeObject(base);
+            oos.flush();
+            oos.close();
+            baos.close();
+            byte[] byteData = baos.toByteArray();
+            ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
+            try 
+            {
+                copy = new ObjectInputStream(bais).readObject();
+            }
+            catch (ClassNotFoundException e)
+            {
+                //e.printStackTrace();
+            }
+        }
+        catch (IOException e) 
+        {
+            //e.printStackTrace();
+        }
+        return copy;
+    }    
+    
+    private javax.validation.Validator createValidator(final ValidatorFactory validatorFactory, 
+            FacesContext context, ValidateWholeBeanComponent component)
+    {
+        // Set default validation group when setValidationGroups has not been called.
+        // The null check is there to prevent it from happening twice.
+        if (validationGroupsArray == null)
+        {
+            postSetValidationGroups(component);
+        }
+
+        return validatorFactory //
+                .usingContext() //
+                .messageInterpolator(new FacesMessageInterpolator(
+                        validatorFactory.getMessageInterpolator(), context)) //
+                .getValidator();
+
+    }
+
+    // This boolean is used to make sure that the log isn't trashed with warnings.
+    private static volatile boolean firstValueReferenceWarning = true;
+
+    /**
+     * Get the ValueReference from the ValueExpression.
+     *
+     * @param valueExpression The ValueExpression for value.
+     * @param context The FacesContext.
+     * @return A ValueReferenceWrapper with the necessary information about the ValueReference.
+     */
+    private _ValueReferenceWrapper getValueReference(
+            final ValueExpression valueExpression, final FacesContext context)
+    {
+        ELContext elCtx = context.getELContext();
+        if (ExternalSpecifications.isUnifiedELAvailable())
+        {
+            // unified el 2.2 is available --> we can use ValueExpression.getValueReference()
+            // we can't access ValueExpression.getValueReference() directly here, because
+            // Class loading would fail in applications with el-api versions prior to 2.2
+            _ValueReferenceWrapper wrapper = _BeanValidatorUELUtils.getUELValueReferenceWrapper(valueExpression, elCtx);
+            if (wrapper != null)
+            {
+                if (wrapper.getProperty() == null)
+                {
+                    // Fix for issue in Glassfish EL-impl-2.2.3
+                    if (firstValueReferenceWarning && log.isLoggable(Level.WARNING))
+                    {
+                        firstValueReferenceWarning = false;
+                        log.warning("ValueReference.getProperty() is null. " +
+                                    "Falling back to classic ValueReference resolving. " +
+                                    "This fallback may hurt performance. " +
+                                    "This may be caused by a bug your EL implementation. " +
+                                    "Glassfish EL-impl-2.2.3 is known for this issue. " +
+                                    "Try switching to a different EL implementation.");
+                    }
+                }
+                else
+                {
+                    return wrapper;
+                }
+            }
+        }
+
+        // get base object and property name the "old-fashioned" way
+        return _ValueReferenceResolver.resolve(valueExpression, elCtx);
+    }
+
+    /**
+     * This method creates ValidatorFactory instances or retrieves them from the container.
+     *
+     * Once created, ValidatorFactory instances are stored in the container under the key
+     * VALIDATOR_FACTORY_KEY for performance.
+     *
+     * @param context The FacesContext.
+     * @return The ValidatorFactory instance.
+     * @throws FacesException if no ValidatorFactory can be obtained because: a) the
+     * container is not a Servlet container or b) because Bean Validation is not available.
+     */
+    private ValidatorFactory createValidatorFactory(FacesContext context)
+    {
+        Map<String, Object> applicationMap = context.getExternalContext().getApplicationMap();
+        Object attr = applicationMap.get(VALIDATOR_FACTORY_KEY);
+        if (attr instanceof ValidatorFactory)
+        {
+            return (ValidatorFactory) attr;
+        }
+        else
+        {
+            synchronized (this)
+            {
+                if (ExternalSpecifications.isBeanValidationAvailable())
+                {
+                    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
+                    applicationMap.put(VALIDATOR_FACTORY_KEY, factory);
+                    return factory;
+                }
+                else
+                {
+                    throw new FacesException("Bean Validation is not present");
+                }
+            }
+        }
+    }
+
+    /**
+     * Fully initialize the validation groups if needed.
+     * If no validation groups are specified, the Default validation group is used.
+     */
+    private void postSetValidationGroups(ValidateWholeBeanComponent component)
+    {
+        String validationGroups = getValidationGroups(component);
+        if (validationGroups == null || validationGroups.matches(EMPTY_VALIDATION_GROUPS_PATTERN))
+        {
+            this.validationGroupsArray = DEFAULT_VALIDATION_GROUPS_ARRAY;
+        }
+        else
+        {
+            String[] classes = validationGroups.split(VALIDATION_GROUPS_DELIMITER);
+            List<Class<?>> validationGroupsList = new ArrayList<Class<?>>(classes.length);
+
+            for (String clazz : classes)
+            {
+                clazz = clazz.trim();
+                if (!clazz.equals(""))
+                {
+                    Class<?> theClass = null;
+                    ClassLoader cl = null;
+                    if (System.getSecurityManager() != null) 
+                    {
+                        try 
+                        {
+                            cl = AccessController.doPrivileged(new PrivilegedExceptionAction<ClassLoader>()
+                                    {
+                                        public ClassLoader run() throws PrivilegedActionException
+                                        {
+                                            return Thread.currentThread().getContextClassLoader();
+                                        }
+                                    });
+                        }
+                        catch (PrivilegedActionException pae)
+                        {
+                            throw new FacesException(pae);
+                        }
+                    }
+                    else
+                    {
+                        cl = Thread.currentThread().getContextClassLoader();
+                    }
+                    
+                    try
+                    {                        
+                        // Try WebApp ClassLoader first
+                        theClass = Class.forName(clazz,false,cl);
+                    }
+                    catch (ClassNotFoundException ignore)
+                    {
+                        try
+                        {
+                            // fallback: Try ClassLoader for BeanValidator (i.e. the myfaces.jar lib)
+                            theClass = Class.forName(clazz,false, BeanValidator.class.getClassLoader());
+                        }
+                        catch (ClassNotFoundException e)
+                        {
+                            throw new RuntimeException("Could not load validation group", e);
+                        }                        
+                    }
+                    // the class was found
+                    validationGroupsList.add(theClass);
+                }
+            }
+                    
+            this.validationGroupsArray = validationGroupsList.toArray(new Class[validationGroupsList.size()]);
+        }
+    }
+
+    /**
+     * Get the Bean Validation validation groups.
+     * @return The validation groups String.
+     */
+    @JSFProperty
+    public String getValidationGroups(ValidateWholeBeanComponent component)
+    {
+        return component.getValidationGroups();
+    }
+
+    /**
+     * Set the Bean Validation validation groups.
+     * @param validationGroups The validation groups String, separated by
+     *                         {@link BeanValidator#VALIDATION_GROUPS_DELIMITER}.
+     */
+    public void setValidationGroups(ValidateWholeBeanComponent component, final String validationGroups)
+    {
+        component.setValidationGroups(validationGroups);
+    }
+
+    /**
+     * Note: Before 2.1.5/2.0.11 there was another strategy for this point to minimize
+     * the instances used, but after checking this with a profiler, it is more expensive to
+     * call FacesContext.getCurrentInstance() than create this object for bean validation.
+     * 
+     * Standard MessageInterpolator, as described in the JSR-314 spec.
+     */
+    private static class FacesMessageInterpolator implements MessageInterpolator
+    {
+        private final FacesContext facesContext;
+        private final MessageInterpolator interpolator;
+
+        public FacesMessageInterpolator(final MessageInterpolator interpolator, final FacesContext facesContext)
+        {
+            this.interpolator = interpolator;
+            this.facesContext = facesContext;
+        }
+
+        public String interpolate(final String s, final MessageInterpolator.Context context)
+        {
+            Locale locale = facesContext.getViewRoot().getLocale();
+            return interpolator.interpolate(s, context, locale);
+        }
+
+        public String interpolate(final String s, final MessageInterpolator.Context context, final Locale locale)
+        {
+            return interpolator.interpolate(s, context, locale);
+        }
+    }
+
+    private static class UpdateBeanCopyCallback implements VisitCallback
+    {
+        private WholeBeanValidator validator;
+        private Object wholeBeanBase;
+        private Object wholeBeanBaseCopy;
+        private Map<String, Object> candidateValuesMap;
+
+        public UpdateBeanCopyCallback(WholeBeanValidator validator, Object wholeBeanBase, Object wholeBeanBaseCopy,
+                Map<String, Object> candidateValuesMap)
+        {
+            this.validator = validator;
+            this.wholeBeanBase = wholeBeanBase;
+            this.wholeBeanBaseCopy = wholeBeanBaseCopy;
+            this.candidateValuesMap = candidateValuesMap;
+        }
+
+        @Override
+        public VisitResult visit(VisitContext context, UIComponent target)
+        {
+            // The idea is follow almost the same algorithm used by Bean Validation. This 
+            // algorithm calculates the base of the ValueExpression used by the component.
+            // Then a simple equals() check will do the trick to decide when to call
+            // setValue and affect the model. If the base is the same than the value returned by
+            // f:validateWholeBean, you are affecting to same instance.
+            // 
+            
+            ValueExpression valueExpression = target.getValueExpression("value");
+            if (valueExpression == null)
+            {
+                log.warning("cannot validate component with empty value: " 
+                        + target.getClientId(context.getFacesContext()));
+                return VisitResult.ACCEPT;
+            }
+
+            // Obtain a reference to the to-be-validated object and the property name.
+            _ValueReferenceWrapper reference = validator.getValueReference(
+                    valueExpression, context.getFacesContext());
+            if (reference == null)
+            {
+                return VisitResult.ACCEPT;
+            }
+            Object base = reference.getBase();
+            if (base == null)
+            {
+                return VisitResult.ACCEPT;
+            }
+
+            Object referenceProperty = reference.getProperty();
+            if (!(referenceProperty instanceof String))
+            {
+                // if the property is not a String, the ValueReference does not
+                // point to a bean method, but e.g. to a value in a Map, thus we 
+                // can exit bean validation here
+                return VisitResult.ACCEPT;
+            }
+            String valueProperty = (String) referenceProperty;
+            
+            // If the base of the EL expression is the same to the base of the one in f:validateWholeBean
+            if (base == this.wholeBeanBase || base.equals(this.wholeBeanBase))
+            {
+                // Do the trick over ELResolver and apply it to the copy.
+                
+                ELContext elCtxDecorator = new _ELContextDecorator(context.getFacesContext().getELContext(),
+                        new CopyBeanInterceptorELResolver(context.getFacesContext().getApplication().getELResolver(),
+                            this.wholeBeanBase, this.wholeBeanBaseCopy));
+                
+                valueExpression.setValue(elCtxDecorator, candidateValuesMap.get(
+                        target.getClientId(context.getFacesContext())));
+            }
+            return VisitResult.ACCEPT;
+        }
+    }
+}
\ No newline at end of file

Copied: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_BeanValidatorUELUtils.java (from r1790638, myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/validator/_BeanValidatorUELUtils.java)
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_BeanValidatorUELUtils.java?p2=myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_BeanValidatorUELUtils.java&p1=myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/validator/_BeanValidatorUELUtils.java&r1=1790638&r2=1792968&rev=1792968&view=diff
==============================================================================
--- myfaces/core/branches/2.3.x/api/src/main/java/javax/faces/validator/_BeanValidatorUELUtils.java (original)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_BeanValidatorUELUtils.java Fri Apr 28 00:35:53 2017
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package javax.faces.validator;
+package org.apache.myfaces.component.validate;
 
 import javax.el.ELContext;
 import javax.el.ValueExpression;

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ELContextDecorator.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ELContextDecorator.java?rev=1792968&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ELContextDecorator.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ELContextDecorator.java Fri Apr 28 00:35:53 2017
@@ -0,0 +1,99 @@
+/*
+ * 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.component.validate;
+
+import java.util.Locale;
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.FunctionMapper;
+import javax.el.VariableMapper;
+
+/**
+ * This ELContext is used to hook into the EL handling, by decorating the
+ * ELResolver chain with a custom ELResolver.
+ */
+final class _ELContextDecorator extends ELContext
+{
+    private final ELContext ctx;
+    private final ELResolver interceptingResolver;
+
+    /**
+     * Only used by ValueExpressionResolver.
+     *
+     * @param elContext The standard ELContext. All method calls, except getELResolver, are delegated to it.
+     * @param interceptingResolver The ELResolver to be returned by getELResolver.
+     */
+    _ELContextDecorator(final ELContext elContext, final ELResolver interceptingResolver)
+    {
+        this.ctx = elContext;
+        this.interceptingResolver = interceptingResolver;
+    }
+
+    /**
+     * This is the important one, it returns the passed ELResolver.
+     * @return The ELResolver passed into the constructor.
+     */
+    @Override
+    public ELResolver getELResolver()
+    {
+        return interceptingResolver;
+    }
+
+    // ############################ Standard delegating implementations ############################
+    public FunctionMapper getFunctionMapper()
+    {
+        return ctx.getFunctionMapper();
+    }
+
+    public VariableMapper getVariableMapper()
+    {
+        return ctx.getVariableMapper();
+    }
+
+    public void setPropertyResolved(final boolean resolved)
+    {
+        ctx.setPropertyResolved(resolved);
+    }
+
+    public boolean isPropertyResolved()
+    {
+        return ctx.isPropertyResolved();
+    }
+
+    public void putContext(final Class key, Object contextObject)
+    {
+        ctx.putContext(key, contextObject);
+    }
+
+    public Object getContext(final Class key)
+    {
+        return ctx.getContext(key);
+    }
+
+    public Locale getLocale()
+    {
+        return ctx.getLocale();
+    }
+
+    public void setLocale(final Locale locale)
+    {
+        ctx.setLocale(locale);
+    }
+}

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ValueReferenceResolver.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ValueReferenceResolver.java?rev=1792968&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ValueReferenceResolver.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ValueReferenceResolver.java Fri Apr 28 00:35:53 2017
@@ -0,0 +1,127 @@
+/*
+ * 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.component.validate;
+
+import java.beans.FeatureDescriptor;
+import java.util.Iterator;
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.ValueExpression;
+import javax.faces.el.CompositeComponentExpressionHolder;
+
+/**
+ *
+ */
+/**
+ * This class inspects the EL expression and returns a ValueReferenceWrapper
+ * when Unified EL is not available.
+ */
+final class _ValueReferenceResolver extends ELResolver
+{
+    private final ELResolver resolver;
+
+    /**
+     * This is a simple solution to keep track of the resolved objects,
+     * since ELResolver provides no way to know if the current ELResolver
+     * is the last one in the chain. By assigning (and effectively overwriting)
+     * this field, we know that the value after invoking the chain is always
+     * the last one.
+     *
+     * This solution also deals with nested objects (like: #{myBean.prop.prop.prop}.
+     */
+    private _ValueReferenceWrapper lastObject;
+
+    /**
+     * Constructor is only used internally.
+     * @param elResolver An ELResolver from the current ELContext.
+     */
+    _ValueReferenceResolver(final ELResolver elResolver)
+    {
+        this.resolver = elResolver;
+    }
+
+    /**
+     * This method can be used to extract the ValueReferenceWrapper from the given ValueExpression.
+     *
+     * @param valueExpression The ValueExpression to resolve.
+     * @param elCtx The ELContext, needed to parse and execute the expression.
+     * @return The ValueReferenceWrapper.
+     */
+    public static _ValueReferenceWrapper resolve(ValueExpression valueExpression, final ELContext elCtx)
+    {
+        _ValueReferenceResolver resolver = new _ValueReferenceResolver(elCtx.getELResolver());
+        ELContext elCtxDecorator = new _ELContextDecorator(elCtx, resolver);
+        
+        valueExpression.getValue(elCtxDecorator);
+        
+        while (resolver.lastObject.getBase() instanceof CompositeComponentExpressionHolder)
+        {
+            valueExpression = ((CompositeComponentExpressionHolder) resolver.lastObject.getBase())
+                                  .getExpression((String) resolver.lastObject.getProperty());
+            valueExpression.getValue(elCtxDecorator);
+        }
+
+        return resolver.lastObject;
+    }
+
+    /**
+     * This method is the only one that matters. It keeps track of the objects in the EL expression.
+     *
+     * It creates a new ValueReferenceWrapper and assigns it to lastObject.
+     *
+     * @param context The ELContext.
+     * @param base The base object, may be null.
+     * @param property The property, may be null.
+     * @return The resolved value
+     */
+    @Override
+    public Object getValue(final ELContext context, final Object base, final Object property)
+    {
+        lastObject = new _ValueReferenceWrapper(base, property);
+        return resolver.getValue(context, base, property);
+    }
+
+    // ############################ Standard delegating implementations ############################
+    public Class<?> getType(final ELContext ctx, final Object base, final Object property)
+    {
+        return resolver.getType(ctx, base, property);
+    }
+
+    public void setValue(final ELContext ctx, final Object base, final Object property, final Object value)
+    {
+        resolver.setValue(ctx, base, property, value);
+    }
+
+    public boolean isReadOnly(final ELContext ctx, final Object base, final Object property)
+    {
+        return resolver.isReadOnly(ctx, base, property);
+    }
+
+    public Iterator<FeatureDescriptor> getFeatureDescriptors(final ELContext ctx, final Object base)
+    {
+        return resolver.getFeatureDescriptors(ctx, base);
+    }
+
+    public Class<?> getCommonPropertyType(final ELContext ctx, final Object base)
+    {
+        return resolver.getCommonPropertyType(ctx, base);
+    }
+}
+

Added: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ValueReferenceWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ValueReferenceWrapper.java?rev=1792968&view=auto
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ValueReferenceWrapper.java (added)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/component/validate/_ValueReferenceWrapper.java Fri Apr 28 00:35:53 2017
@@ -0,0 +1,60 @@
+/*
+ * 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.component.validate;
+
+/**
+ * This class provides access to the object pointed to by the EL expression.
+ *
+ * It makes the BeanValidator work when Unified EL is not available.
+ */
+final class _ValueReferenceWrapper
+{
+    private final Object base;
+    private final Object property;
+
+    /**
+     * Full constructor.
+     *
+     * @param base The object the reference points to.
+     * @param property The property the reference points to.
+     */
+    public _ValueReferenceWrapper(final Object base, final Object property)
+    {
+        this.base = base;
+        this.property = property;
+    }
+
+    /**
+     * The object the reference points to.
+     * @return base.
+     */
+    public Object getBase()
+    {
+        return base;
+    }
+
+    /**
+     * The property the reference points to.
+     * @return property.
+     */
+    public Object getProperty()
+    {
+        return property;
+    }
+}

Modified: myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/CoreLibrary.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/CoreLibrary.java?rev=1792968&r1=1792967&r2=1792968&view=diff
==============================================================================
--- myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/CoreLibrary.java (original)
+++ myfaces/core/branches/2.3.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/CoreLibrary.java Fri Apr 28 00:35:53 2017
@@ -32,6 +32,7 @@ import javax.faces.validator.LengthValid
 import javax.faces.validator.LongRangeValidator;
 import javax.faces.validator.RegexValidator;
 import javax.faces.validator.RequiredValidator;
+import org.apache.myfaces.component.validate.ValidateWholeBeanComponent;
 
 import org.apache.myfaces.view.facelets.tag.AbstractTagLibrary;
 
@@ -120,6 +121,8 @@ public final class CoreLibrary extends A
 
         this.addComponent("verbatim", "javax.faces.HtmlOutputText", "javax.faces.Text", VerbatimHandler.class);
         
+        this.addComponent("validateWholeBean", ValidateWholeBeanComponent.COMPONENT_TYPE, null);
+        
         this.addComponent("websocket", "javax.faces.Websocket", 
                 "javax.faces.Websocket", WebsocketHandler.class);
     }



Mime
View raw message