protovalidate-java icon indicating copy to clipboard operation
protovalidate-java copied to clipboard

1.0 update usage question

Open dtanner opened this issue 2 months ago • 1 comments

I'm updating to the 1.0 version of protovalidate-java, and there's a breaking change in how I consume the violations that I'm confused by.

Given this sample message:

message GuesAAddress {
  optional string zip_code = 1 [
    (buf.validate.field).required = true,
    (buf.validate.field).string.len = 5
  ];
}

I guessed at the changes I needed to make to unit test this.

 package common.guest.v1
 
-import build.buf.protovalidate.Validator
+import build.buf.protovalidate.ValidatorFactory
@@ -9,7 +9,7 @@ import org.junit.jupiter.api.Test
 
 class GuestAddressTest {
 
-    private val validator = Validator()
+    private val validator = ValidatorFactory.newBuilder().build()
 
     @Test
     fun `validate guest address - field wrong length`() {
@@ -24,8 +24,8 @@ class GuestAddressTest {
 
         result.violations.size shouldBe 1
         assertSoftly(result.violations[0]) {
-            constraintId shouldBe "string.len"
-            fieldPath shouldBe "zip_code"
+            fieldValue?.descriptor?.fullName shouldBe "common.guest.v1.GuestAddress.zip_code"
+            ruleValue?.descriptor?.fullName shouldBe "buf.validate.StringRules.len"
         }
     }
 }

Is what I did the expected usage change, or is there a cleaner way to inspect the fields? Them being nullable felt odd, and the path to get to those fields was not obvious to me.

Appreciate it - thanks.

dtanner avatar Oct 22 '25 22:10 dtanner

Hi @dtanner! What version were you on prior to switching to v1? There've been a lot of changes to the shape of the protos leading up to v1 that you're seeing here.

The emergence of nullables arises from the syntax switching to proto2, which (effectively) makes all fields nullable. This change was made to support predefined rules (mainly, you cannot extend messages other than descriptor *Options in proto3 syntax, and proto editions are not widely supported yet).

The violation structure has also changed to provide more contextual information. For the rule ID (formerly, constraint ID), it looks like we're not exposing that at the top level anymore. You can look that up on the underlying Violation proto, however:

toProto().rule_id shouldBe "string.len"

And for the field name, if you don't want the fully-qualified version:

fieldValue?.descriptor?.name shouldBe "zip_code"

rodaine avatar Oct 24 '25 14:10 rodaine