Class BeanValidator
Acts as a thin shim between Juneau's REST argument resolvers (ContentArg, FormDataArg,
RequestBeanArg) and the jakarta.validation.Validator engine. Per the package-level contract
(see package overview), validation is off by default and never
runs automatically: callers query isValidationRequested(ParameterInfo) once at arg-resolver
construction time, then conditionally invoke validate(Object, BeanStore) per request only when an
explicit @jakarta.validation.Valid (or equivalent) marker is present.
Validator resolution order
- A user-supplied
Validatorbean visible from the suppliedBeanStore— typically contributed via a@Bean public Validator validator()factory on a@Rest-annotated resource. This is the recommended path when the application needs custom message interpolators, group sequences, or constraint-validator factories. - A lazily-built JVM-wide default obtained from
Validation.buildDefaultValidatorFactory(). Cached after the first successful build so the factory cost is paid at most once per JVM. null— signals graceful degradation when neither a bean-store entry nor a runtime provider is available.validate(Object, BeanStore)returns the input bean unchanged in this case and logs a singleWARNINGper JVM so misconfigured deployments are visible without flooding the log.
Why static dispatch?
Each REST argument resolver is built once per @RestOp method at servlet startup, then invoked on
every request. By keeping the validator lookup off the arg-resolver constructor and inside this class's
cached static accessor, the cost of locating the Validator is paid once per JVM rather than once
per request — and resolvers for @RestOp methods that never opt in pay nothing at all (the
static initializer doesn't run until the first call to validate(Object, BeanStore)).
See Also:
- Since:
- 10.0.0
-
Method Summary
Modifier and TypeMethodDescriptionstatic booleanisValidationRequested(ParameterInfo paramInfo) Returnstrue if the supplied parameter carries any of the recognized validation opt-in markers (currentlyjakarta.validation.Valid,javax.validation.Valid, or Spring's@Validated).static voidTest/diagnostic hook — resets the JVM-wide default-validator cache so the next call tovalidate(Object, BeanStore)re-resolves the provider.static voidTest/diagnostic hook — forces the "no provider on classpath" code path.static <T> TRuns Jakarta Bean Validation against the supplied bean and throws aValidationExceptionif any constraints are violated.
-
Method Details
-
isValidationRequested
Returnstrue if the supplied parameter carries any of the recognized validation opt-in markers (currentlyjakarta.validation.Valid,javax.validation.Valid, or Spring's@Validated).Detection is purely FQN-based via
JsrSupport.isValidAnnotation(AnnotationInfo)— no compile-time dependency on the Jakarta Validation or Spring annotation classes themselves is required to recognize the marker.Arg resolvers should call this exactly once at construction time and cache the result; the per-request hot path then becomes a single boolean check before deciding whether to call
validate(Object, BeanStore).- Parameters:
paramInfo- The Java method parameter being inspected. Must not benull .- Returns:
true if the parameter has been opted into validation.
-
validate
Runs Jakarta Bean Validation against the supplied bean and throws aValidationExceptionif any constraints are violated.Resolution order for the
Validatoris described on the class javadoc. When no validator can be obtained (no bean-store entry, no runtime provider), this method logs a one-shot warning and returnsbeanunchanged — preserving the off-by-default contract even when an arg resolver was constructed with@Validbut the deployment forgot to ship a provider.A
nullbeanreturnsnullwithout invoking the validator (Jakarta'svalidator.validate(null)throwsIllegalArgumentException, which would just produce an unhelpful 500 instead of the natural "missing body" 400 the upstream arg resolver already surfaces).- Type Parameters:
T- The bean type being validated.- Parameters:
bean- The resolved bean to validate. May benull .beanStore- The op-session bean store consulted for a user-suppliedValidator. May benull (treated as "no user override").- Returns:
- The input
bean(unchanged). - Throws:
ValidationException- If one or more constraints are violated.
-
resetCachedDefaultForTesting
Test/diagnostic hook — resets the JVM-wide default-validator cache so the next call tovalidate(Object, BeanStore)re-resolves the provider. Not part of the public contract; intended for unit tests that simulate provider-missing scenarios. -
simulateProviderMissingForTesting
Test/diagnostic hook — forces the "no provider on classpath" code path. Not part of the public contract; intended for unit tests that need to assert the graceful-degradation behavior without actually removing the Hibernate Validator JAR from the test classpath.After calling this,
validate(Object, BeanStore)will behave as if no Jakarta Bean Validation provider is reachable: it short-circuits to a no-op and emits the one-shot "missing provider" warning. CallresetCachedDefaultForTesting()afterwards to restore normal lookup.
-