0

When I tried to validate a Scala's Map, no matter mutable or immutable, I got an exception like:

javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint 'javax.validation.constraints.Size' validating type 'scala.collection.mutable.Map<java.lang.String, java.lang.String>'. Check configuration for 'corporationSecrets'
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.throwExceptionForNullValidator(ConstraintTree.java:229) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.getConstraintValidatorNoUnwrapping(ConstraintTree.java:310) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.getConstraintValidatorInstanceForAutomaticUnwrapping(ConstraintTree.java:244) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.getInitializedConstraintValidator(ConstraintTree.java:163) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:116) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateComposingConstraints(ConstraintTree.java:398) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:98) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:87) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:73) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:621) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:584) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidatorImpl.java:528) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:496) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:461) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:411) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:208) ~[hibernate-validator-5.3.6.Final.jar:5.3.6.Final]
    at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:102) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.validation.DataBinder.validate(DataBinder.java:877) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.boot.bind.PropertiesConfigurationFactory.doBindPropertiesToTarget(PropertiesConfigurationFactory.java:274) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
    at org.springframework.boot.bind.PropertiesConfigurationFactory.bindPropertiesToTarget(PropertiesConfigurationFactory.java:240) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:330) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
    ... 29 common frames omitted

My code is very simple, like

@NotEmpty
val corporationSecrets : scala.collection.mutable.Map[String, String] = new scala.collection.mutable.HashMap[String, String]

How can I validate a scala's map to check whether it is empty or not?

Tonny Tc
  • 852
  • 1
  • 12
  • 37
  • I'm not really a Scala person but by looking at the error that you;ve provided and checking the Scala doc - http://www.scala-lang.org/api/2.9.3/scala/collection/mutable/HashMap.html the problem is that you are trying to place an annotation on a scala type, for which there's no validator implemented, as it's a scala collection. Here's also an answer that you might find helpful - https://stackoverflow.com/a/24291593/4940126 So I think if you'd like to use BeanValidation for your scala types you will need to implement validators for those types. – mark_o Jan 19 '18 at 09:45
  • Yes, the problem is just as what you said, Scala does not support JSR303. Those links are all some time ago, so I just want to get some new info. about the case to see whether there's any changes in Scala. – Tonny Tc Jan 19 '18 at 14:51

2 Answers2

1

So what you have to understand is that in Hibernate Validator, for a given constraint, you register constraint validators for different types.

Typically, for the @Size constraint, we will register constraint validators for String, Collection, Map, arrays...

The issue you have here is that the Scala types don't implement the classical Java interfaces so we can't find a constraint validator for them. That's why you get your exception: HV recognizes the constraint but can't find a constraint validator to apply it on your Scala Map.

As far as I can see from the code, https://github.com/bean-validation-scala/bean-validation-scala would be the way to go to get BV and HV support for Scala. It delegates the validation to the original HV implementations so you should have a very similar behavior to what is done with Java.

I don't think it's outdated as keep in mind that the BV/HV project didn't change too much for a while, before we started the work on BV 2.0 and HV 6.0. It might be a good idea to ping the original author regarding the BV 2.0 and HV 6.0 support (we have new constraints and so on).

Guillaume Smet
  • 9,921
  • 22
  • 29
  • Thanks a lot for your detail explanation, Guillaume. Actually, JSR303 is a Java specification, and I will not complain if it doesn't work in Scala. I'll try to post the case in Scala's forums. – Tonny Tc Jan 19 '18 at 14:43
0

If you want to check if a map collection is empty or not you could do this: if(mapVariable.isEmpty() || mapVariable == null){...}

Or write traversable shouldBe empty or javaMap should not be empty as stated in the second link (link to the API). Check out this or this for further information.

EDIT

Try to add @Valid to the collection.

Here is an example from the Hibernate Validator Reference.

public class Car { 
@NotNull 
@Valid 
private List<Person> passengers = new ArrayList<Person>(); 
}

This is standard JSR-303 behavior. See Section 3.1.3 of the spec.

Alex Cuadrón
  • 638
  • 12
  • 19
  • Thanks a lot for your reply, but what I concerned is not how to check a map collection is empty or not. I just ask about how to use JSR 303 in Scala. There're some related question like [this](https://stackoverflow.com/questions/24284592/does-scala-suport-jsr-303-validation) and [this](http://www.scala-lang.org/old/node/3251), and further more, there's a [bean-validation-scala](https://github.com/bean-validation-scala/bean-validation-scala). But all of them seems past a period time, and so, I want to know whether there's new update for using JSR 303 in Scala. – Tonny Tc Jan 19 '18 at 06:02
  • @TonnyTc check it out now. If it's not the answer you were looking for just let me know and I'll work out other way. :D – Alex Cuadrón Jan 19 '18 at 06:15
  • Actually, `@NotNull` works fine, but `@NotEmpty` means both `@NotNull` and `@Size(min=1)`. The exception indicates that the `@Size` cannot validate the Scala's Map. Meanwhile, for Java's Map, everything works because JSR 303 is a Java specification ... – Tonny Tc Jan 19 '18 at 06:22
  • It also makes the same exception. And I don't think the exception is just about the validation's result (whether the map is empty or not), but there's something wrong about the validator itself. – Tonny Tc Jan 19 '18 at 06:31
  • @TonnyTc `@NotNull` checks that the object is "pointing" to a reference in memory while `@NotEmpty` checks if it contains at least one value added. So the exception is being fired due to the lack of `@Size(min value,max value)` try adding it and let me know if it'd worked – Alex Cuadrón Jan 19 '18 at 06:39
  • As I've said, `@NotEmpty` means both `@NotNull` and `@Size(min=1)`, why should I add `@Size` again? And the same exception occurs when I change `@NotEmpty` to `@Size(min = 1)`. – Tonny Tc Jan 19 '18 at 06:56
  • @TonnyTc I'm afraid I have no clue why is that happening sorry :(. If it works with NotNull could you use it? Or you need to check for the Size compulsory? – Alex Cuadrón Jan 19 '18 at 06:59
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/163459/discussion-between-tonny-tc-and-alex-cuadron). – Tonny Tc Jan 19 '18 at 07:04