akkurate icon indicating copy to clipboard operation
akkurate copied to clipboard

Explore the idea of attaching custom details to ConstraintViolation

Open imulab opened this issue 1 year ago • 3 comments

The ConstraintViolation has path and message, which is sufficient for most cases.

But it is not the most straightforward design if I need to pinpoint on the exact constraint being violated and act on it. For instance, to pick out a particular constraint violation and throw an alternate Exception instead of the generic Exception.

Currently, to workaround this limitation, there are possibly two ways:

  • Override the path using the withPath { absolute("some_identifier") } DSL
  • Override the message using the otherwise { "some_identifier" } DSL

The first workaround loses the path in a meaningful way. And the second workaround loses human readable messages.

Is it possible to add a third field of metadata: Map<String, Any> to ConstraintViolation, so that user can freely attach whatever metadata they need to the violation instance.

Possible DSL design:

val validate = Validator<Data> {
   fieldOne.apply {
      shouldNotBeEmpty()
      constraint { it.meetsCustomCondition() } withMetadata { mapOf("key" to "customErrorKey1") }
   }
}

Then, when analyzing the ConstraintViolation:


fun handleViolation(cv: ConstraintViolation) {
   if (cv.metadata["key"] == "customErrorKey1")
      throw CustomError(cv.message)
  throw FallbackError(cv.message)
}

imulab avatar Jul 11 '24 09:07 imulab

This is clearly an issue I want to address!

I think your idea of metadata is good. We could even add a dedicated code property to ConstraintViolation, because this is definitely something a lot of people could use.

Let me think about it, but I love the idea :)

nesk avatar Jul 24 '24 10:07 nesk

I agree that we need more information in ConstraintViolation.

In valiktor the ConstraintViolation had all the information of the violation, such as the constraint with a message key and message parameters and the value that was not validated. This helps a lot when you want to sent a localised message or you want to send in JSON all the information to the UI and construct the error message there.

ageorgousakisn avatar Sep 25 '24 14:09 ageorgousakisn

To make the custom details more flexible, it may be better to make the metadata a generic type, while also providing a default implementation or type alias that fix the type parameter to be a Map<String, String> or Map<String, Any>

alphaho avatar Feb 01 '25 13:02 alphaho