Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: UnexpectedTypeException There are multiple validator classes
PostPosted: Mon Mar 25, 2013 2:33 am 
Newbie

Joined: Mon Mar 25, 2013 1:24 am
Posts: 1
Please see the code fragment below:
Code:
import java.lang.reflect.Method;
import java.util.Map;

import javax.validation.Validation;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotEmpty;
import org.hibernate.validator.internal.engine.ValidatorImpl;
import org.junit.Test;

public class ValidatorTest {

   private static final class BeanWithByteArray{

      public @NotNull(message = "Contract cannot be null") byte[] createContract(
            @NotEmpty(message = "Contract template must be provided")   byte[] byteArray
            ,@NotNull(message = "must be provided") DocumentType documentType
            ){
         return null;
      }

      @NotNull(message = "Contract cannot be null")
      public  byte[] createContractErrorDuringValidation(
            @NotEmpty(message = "Contract template must be provided")   byte[] byteArray
            ,@NotNull(message = "must be provided") Map<String, String> map
            ,@NotNull(message = "must be provided") DocumentType documentType) {
         return null;
      }


   }

   enum DocumentType{
      DOC,DOCX
   }


   @Test
   public void validateByteArrayParameter() throws SecurityException, NoSuchMethodException{
      ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
      ValidatorImpl v = (ValidatorImpl) vf.getValidator();

      BeanWithByteArray object = new BeanWithByteArray();

      System.out.println(v.validateParameter(object, object.getClass().getMethod("createContract", byte[].class,DocumentType.class), new byte[0], 0));
   }

   @Test
   public void validateByteArrayParameterWrongValidation() throws SecurityException, NoSuchMethodException{
      ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
      ValidatorImpl v = (ValidatorImpl) vf.getValidator();

      BeanWithByteArray object = new BeanWithByteArray();

      System.out.println(v.validateParameter(object, object.getClass().getMethod("createContractErrorDuringValidation", byte[].class,Map.class,DocumentType.class), new byte[0], 0));
   }

   @Test
   public void reflectionH() throws Exception {
      BeanWithByteArray object = new BeanWithByteArray();
      Method method = object.getClass().getMethod("createContract", byte[].class,DocumentType.class);
      System.out.println(method.getGenericParameterTypes());

      method = object.getClass().getMethod("createContractErrorDuringValidation", byte[].class,Map.class,DocumentType.class);
      System.out.println(method.getGenericParameterTypes());

   }
}


Running validateByteArrayParameterWrongValidation cause UnexpectedTypeException.
Code:
javax.validation.UnexpectedTypeException: HV000031: There are multiple validator classes which could validate the type byte[]. The validator classes are: class [J, class [B, class [I, class [F, class [D.
   at org.hibernate.validator.internal.engine.ConstraintTree.verifyResolveWasUnique(ConstraintTree.java:420)
   at org.hibernate.validator.internal.engine.ConstraintTree.findMatchingValidatorClass(ConstraintTree.java:392)
   at org.hibernate.validator.internal.engine.ConstraintTree.getInitializedValidator(ConstraintTree.java:350)
   at org.hibernate.validator.internal.engine.ConstraintTree.validateConstraints(ConstraintTree.java:171)
   at org.hibernate.validator.internal.engine.ConstraintTree.validateComposingConstraints(ConstraintTree.java:259)
   at org.hibernate.validator.internal.engine.ConstraintTree.validateConstraints(ConstraintTree.java:154)
   at org.hibernate.validator.internal.engine.ConstraintTree.validateConstraints(ConstraintTree.java:124)
   at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:86)
   at org.hibernate.validator.internal.engine.ValidatorImpl.validateParameterForGroup(ValidatorImpl.java:992)
   at org.hibernate.validator.internal.engine.ValidatorImpl.validateParametersForGroup(ValidatorImpl.java:925)
   at org.hibernate.validator.internal.engine.ValidatorImpl.validateParametersInContext(ValidatorImpl.java:855)
   at org.hibernate.validator.internal.engine.ValidatorImpl.validateParameter(ValidatorImpl.java:192)
   at com.lumesse.utils.ValidatorTest.validateByteArrayParameterWrongValidation(ValidatorTest.java:58)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:597)
   at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
   at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
   at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
   at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
   at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
   at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
   at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
   at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
   at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
   at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
   at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
   at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
   at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
   at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
   at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)


Checking it deeper i found out that it was caused by different behavior of method.getGenericParameterTypes() for byte array parameter in BeanWithByteArray.createContract and BeanWithByteArray.createContractErrorDuringValidation methods.
This causes org.hibernate.validator.internal.engine.ConstraintTree.findSuitableValidatorTypes to return more than one suitable validator type.

Hibernate Validator version:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.1.Final</version>
</dependency>


Top
 Profile  
 
 Post subject: Re: UnexpectedTypeException There are multiple validator classes
PostPosted: Wed Jun 26, 2013 11:11 am 
Hibernate Team
Hibernate Team

Joined: Sat Jan 24, 2009 12:46 pm
Posts: 386
Please post questions on Hibernate Validator to https://forum.hibernate.org/viewforum.php?f=9, this is the feedback forum for the Bean Validation spec.

That said, I think you're running into a bug within Java itself, namely http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5041784. This occurs for methods with parameters of a generic type (here Map<String, String>) and causes a wrong type to be retrieved via reflection for array parameters of the same method (one gets a GenericArrayType instead of byte[].class).

To work around, either upgrade to Java 7 (your example works there for me) or avoid the combination of these parameter types if possible (e.g. by making the array a List).

--Gunnar

_________________
Visit my blog at http://musingsofaprogrammingaddict.blogspot.com/


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.