Permalink
Browse files

HV-876 Retrieving parameter names via reflection

  • Loading branch information...
1 parent e20c12a commit 9f50adc35af606453a210a534579e79379f47bdf @khalidq khalidq committed with hferentschik May 27, 2014
@@ -72,7 +72,7 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
- <compilerArgument>-proc:none</compilerArgument>
+ <proc>none</proc>
</configuration>
</plugin>
<plugin>
@@ -302,15 +302,24 @@ instance can be altered in the initialize() method.
[[section-parameter-name-provider]]
==== ParameterNameProvider
-In case a method or constructor parameter constraint is violated, the ParameterNameProvider
-interface is used to retrieve the parameter's name and make it available to the user via the
-constraint violation's property path.
-
-The default implementation returns parameter names in the form +arg0+, +arg1+ etc., while custom
-implementations could e.g. be based on parameter annotations, debug symbols or a feature for
-retrieving parameter names at runtime possibly provided by future Java versions.
-
-Custom ParameterNameProvider implementations are used as demonstrated in
+In case a method or constructor parameter constraint is violated, the +ParameterNameProvider+
+interface is used to retrieve the parameter name and make it available to the user via the
+property path of the constraint violation.
+
+The default implementation returns parameter names in the form of +arg0+, +arg1+ etc, while custom
+implementations can retrieve the parameter names using methods such as parameter annotations,
+debug symbols, or Java 8 reflection.
+
+An implementation for retrieving the parameter names using reflection in Java 8 is provided with
++ReflectionParameterNameProvider+. For this parameter name provider to work, the
+source must be compiled using the +–parameters+ compiler argument. Otherwise, the provider will
+return synthetic names in the form of +arg0+, +arg1+, etc.
+
+To use +ReflectionParameterNameProvider+ or another custom provider either pass an instance of
+the provider during bootstrapping as shown in <<example-using-custom-parameter-name-provider>>,
+or specify the fully qualified class name of the provider as value for
+the &lt;parameter-name-provider&gt; element in the _META-INF/validation.xml_ file
+(see <<section-configuration-validation-xml>>). This is demonstrated in
<<example-using-custom-parameter-name-provider>>.
[[example-using-custom-parameter-name-provider]]
@@ -466,8 +466,8 @@ a post-compile step or annotations such as the @Named annotation from JSR 330.
In order to use ParanamerParameterNameProvider, either pass an instance when bootstrapping a
validator as shown in <<example-using-custom-parameter-name-provider>> or specify
-org.hibernate.validator.parameternameprovider.ParanamerParameterNameProvider as value for the &lt
-;parameter-name-provider&gt; element in the _META-INF/validation.xml_ file.
+org.hibernate.validator.parameternameprovider.ParanamerParameterNameProvider as value for the
+&lt;parameter-name-provider&gt; element in the _META-INF/validation.xml_ file.
[TIP]
@@ -490,7 +490,7 @@ Sometimes it is required to unwrap values prior to the validation. E.g. in
link:$$http://docs.oracle.com/javafx/$$[JavaFX] are used to define an element of some domain model.
[[example-using-unwrapvalidatedvalue]]
-.Using@UnwrapValidatedValue
+.Using +@UnwrapValidatedValue+
====
[source, JAVA]
----
@@ -16,12 +16,10 @@
*/
package org.hibernate.validator.internal.metadata;
-import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import javax.validation.ParameterNameProvider;
-import org.hibernate.validator.internal.engine.DefaultParameterNameProvider;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl.BeanMetaDataBuilder;
@@ -96,22 +94,6 @@
private final ExecutableHelper executableHelper;
/**
- * Creates a new {@code BeanMetaDataManager}. {@link DefaultParameterNameProvider} is used as parameter name
- * provider, no meta data providers besides the annotation-based providers are used.
- *
- * @param constraintHelper the constraint helper
- * @param executableHelper the executable helper
- */
- public BeanMetaDataManager(ConstraintHelper constraintHelper, ExecutableHelper executableHelper) {
- this(
- constraintHelper,
- executableHelper,
- new DefaultParameterNameProvider(),
- Collections.<MetaDataProvider>emptyList()
- );
- }
-
- /**
* Creates a new {@code BeanMetaDataManager}.
*
* @param constraintHelper the constraint helper
@@ -0,0 +1,58 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.validator.parameternameprovider;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.List;
+import javax.validation.ParameterNameProvider;
+
+import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList;
+
+/**
+ * Uses Java 8 reflection to get the parameter names.
+ *
+ * <p>For this provider to return the actual parameter names, classes must be compiled with the '-parameters' compiler
+ * argument. Otherwise, the JDK will return synthetic names in the form {@code arg0}, {@code arg1}, etc.</p>
+ *
+ * <p>See also <a href="http://openjdk.java.net/jeps/118">JEP 118</a></p>
+ * @author Khalid Alqinyah
+ */
+public class ReflectionParameterNameProvider implements ParameterNameProvider {
+
+ @Override
+ public List<String> getParameterNames(Constructor<?> constructor) {
+ return getParameterNames( constructor.getParameters() );
+ }
+
+ @Override
+ public List<String> getParameterNames(Method method) {
+ return getParameterNames( method.getParameters() );
+ }
+
+ private List<String> getParameterNames(Parameter[] parameters) {
+ List<String> parameterNames = newArrayList();
+
+ for ( Parameter parameter : parameters ) {
+ // If '-parameters' is used at compile time, actual names will be returned. Otherwise, it will be arg0, arg1...
+ parameterNames.add( parameter.getName() );
+ }
+
+ return parameterNames;
+ }
+}
@@ -16,7 +16,7 @@
*/
/**
- * <p>A custom parameter name provider based on the <a href="http://paranamer.codehaus.org/">ParaNamer</a> library.</p>
+ * <p>Custom Hibernate Validator {@code javax.validation.ParameterNameProvider} implementations.</p>
* <p>This package is part of the public Hibernate Validator API.</p>
*/
package org.hibernate.validator.parameternameprovider;
@@ -16,6 +16,7 @@
*/
package org.hibernate.validator.test.internal.engine.path;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -28,10 +29,12 @@
import org.testng.annotations.Test;
+import org.hibernate.validator.internal.engine.DefaultParameterNameProvider;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.hibernate.validator.internal.metadata.BeanMetaDataManager;
import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData;
import org.hibernate.validator.internal.metadata.core.ConstraintHelper;
+import org.hibernate.validator.internal.metadata.provider.MetaDataProvider;
import org.hibernate.validator.internal.metadata.raw.ExecutableElement;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.TypeResolutionHelper;
@@ -192,7 +195,9 @@ public void testCreationOfExecutablePath() throws Exception {
);
BeanMetaDataManager beanMetaDataManager = new BeanMetaDataManager(
new ConstraintHelper(),
- new ExecutableHelper( new TypeResolutionHelper() )
+ new ExecutableHelper( new TypeResolutionHelper() ),
+ new DefaultParameterNameProvider(),
+ Collections.<MetaDataProvider>emptyList()
);
ExecutableMetaData executableMetaData = beanMetaDataManager.getBeanMetaData( Container.class )
@@ -21,15 +21,18 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import org.hibernate.validator.internal.engine.DefaultParameterNameProvider;
import org.hibernate.validator.internal.metadata.BeanMetaDataManager;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl;
import org.hibernate.validator.internal.metadata.core.ConstraintHelper;
+import org.hibernate.validator.internal.metadata.provider.MetaDataProvider;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.TypeResolutionHelper;
import org.hibernate.validator.internal.util.logging.Log;
@@ -54,7 +57,9 @@
public void setUpBeanMetaDataManager() {
metaDataManager = new BeanMetaDataManager(
new ConstraintHelper(),
- new ExecutableHelper( new TypeResolutionHelper() )
+ new ExecutableHelper( new TypeResolutionHelper() ),
+ new DefaultParameterNameProvider(),
+ Collections.<MetaDataProvider>emptyList()
);
}
@@ -19,6 +19,7 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
+import java.util.Collections;
import javax.validation.ElementKind;
import javax.validation.constraints.NotNull;
import javax.validation.groups.Default;
@@ -27,11 +28,13 @@
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import org.hibernate.validator.internal.engine.DefaultParameterNameProvider;
import org.hibernate.validator.internal.metadata.BeanMetaDataManager;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData;
import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData;
import org.hibernate.validator.internal.metadata.core.ConstraintHelper;
import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl;
+import org.hibernate.validator.internal.metadata.provider.MetaDataProvider;
import org.hibernate.validator.internal.metadata.raw.ExecutableElement;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.TypeResolutionHelper;
@@ -58,7 +61,9 @@
public void setupBeanMetaData() {
BeanMetaDataManager beanMetaDataManager = new BeanMetaDataManager(
new ConstraintHelper(),
- new ExecutableHelper( new TypeResolutionHelper() )
+ new ExecutableHelper( new TypeResolutionHelper() ),
+ new DefaultParameterNameProvider(),
+ Collections.<MetaDataProvider>emptyList()
);
beanMetaData = beanMetaDataManager.getBeanMetaData( CustomerRepositoryExt.class );
@@ -17,18 +17,21 @@
package org.hibernate.validator.test.internal.metadata.aggregated;
import java.lang.reflect.Method;
+import java.util.Collections;
import java.util.Set;
import javax.validation.constraints.NotNull;
import javax.validation.groups.Default;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import org.hibernate.validator.internal.engine.DefaultParameterNameProvider;
import org.hibernate.validator.internal.metadata.BeanMetaDataManager;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData;
import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData;
import org.hibernate.validator.internal.metadata.aggregated.ParameterMetaData;
import org.hibernate.validator.internal.metadata.core.ConstraintHelper;
+import org.hibernate.validator.internal.metadata.provider.MetaDataProvider;
import org.hibernate.validator.internal.metadata.raw.ExecutableElement;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.TypeResolutionHelper;
@@ -55,7 +58,9 @@
public void setupBeanMetaData() {
BeanMetaDataManager beanMetaDataManager = new BeanMetaDataManager(
new ConstraintHelper(),
- new ExecutableHelper( new TypeResolutionHelper() )
+ new ExecutableHelper( new TypeResolutionHelper() ),
+ new DefaultParameterNameProvider(),
+ Collections.<MetaDataProvider>emptyList()
);
beanMetaData = beanMetaDataManager.getBeanMetaData( CustomerRepository.class );
@@ -16,6 +16,7 @@
*/
package org.hibernate.validator.test.internal.metadata.aggregated;
+import java.util.Collections;
import java.util.Set;
import javax.validation.ConstraintDeclarationException;
@@ -25,9 +26,12 @@
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+
+import org.hibernate.validator.internal.engine.DefaultParameterNameProvider;
import org.hibernate.validator.internal.metadata.BeanMetaDataManager;
import org.hibernate.validator.internal.metadata.aggregated.PropertyMetaData;
import org.hibernate.validator.internal.metadata.core.ConstraintHelper;
+import org.hibernate.validator.internal.metadata.provider.MetaDataProvider;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.valuehandling.UnwrapValidatedValue;
import org.hibernate.validator.internal.util.TypeResolutionHelper;
@@ -47,7 +51,9 @@
public void setupBeanMetaDataManager() {
beanMetaDataManager = new BeanMetaDataManager(
new ConstraintHelper(),
- new ExecutableHelper( new TypeResolutionHelper() )
+ new ExecutableHelper( new TypeResolutionHelper() ),
+ new DefaultParameterNameProvider(),
+ Collections.<MetaDataProvider>emptyList()
);
}
Oops, something went wrong.

0 comments on commit 9f50adc

Please sign in to comment.