/**
   * Validates the Bean Validation constraints specified at the parameters and/or return value of
   * the intercepted method.
   *
   * @param ctx The context of the intercepted method invocation.
   * @return The result of the method invocation.
   * @throws Exception Any exception caused by the intercepted method invocation. A {@link
   *     ConstraintViolationException} in case at least one constraint violation occurred either
   *     during parameter or return value validation.
   */
  @AroundInvoke
  public Object validateMethodInvocation(InvocationContext ctx) throws Exception {
    ExecutableValidator executableValidator = validator.forExecutables();
    Set<ConstraintViolation<Object>> violations =
        executableValidator.validateParameters(
            ctx.getTarget(), ctx.getMethod(), ctx.getParameters());

    if (!violations.isEmpty()) {
      throw new ConstraintViolationException(
          getMessage(ctx.getMethod(), ctx.getParameters(), violations), violations);
    }

    Object result = ctx.proceed();

    violations = executableValidator.validateReturnValue(ctx.getTarget(), ctx.getMethod(), result);

    if (!violations.isEmpty()) {
      throw new ConstraintViolationException(
          getMessage(ctx.getMethod(), ctx.getParameters(), violations), violations);
    }

    return result;
  }