Class BeanValidator

java.lang.Object
org.apache.juneau.rest.server.validation.BeanValidator

public final class BeanValidator extends Object
Static dispatcher for the optional Jakarta Bean Validation 3.x integration.

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
  1. A user-supplied Validator bean visible from the supplied BeanStore — 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.
  2. 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.
  3. 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 single WARNING per 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 Details

    • isValidationRequested

      public static boolean isValidationRequested(ParameterInfo paramInfo)
      Returns true if the supplied parameter carries any of the recognized validation opt-in markers (currently jakarta.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 be null.
      Returns:
      true if the parameter has been opted into validation.
    • validate

      public static <T> T validate(T bean, BeanStore beanStore)
      Runs Jakarta Bean Validation against the supplied bean and throws a ValidationException if any constraints are violated.

      Resolution order for the Validator is 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 returns bean unchanged — preserving the off-by-default contract even when an arg resolver was constructed with @Valid but the deployment forgot to ship a provider.

      A null bean returns null without invoking the validator (Jakarta's validator.validate(null) throws IllegalArgumentException, 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 be null.
      beanStore - The op-session bean store consulted for a user-supplied Validator. May be null (treated as "no user override").
      Returns:
      The input bean (unchanged).
      Throws:
      ValidationException - If one or more constraints are violated.
    • resetCachedDefaultForTesting

      public static void resetCachedDefaultForTesting()
      Test/diagnostic hook — resets the JVM-wide default-validator cache so the next call to validate(Object, BeanStore) re-resolves the provider. Not part of the public contract; intended for unit tests that simulate provider-missing scenarios.
    • simulateProviderMissingForTesting

      public static void 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. Call resetCachedDefaultForTesting() afterwards to restore normal lookup.