code: public static RaftConfiguration validate(RaftConfiguration configuration) {
          // TODO (AG): understand why the validator instance cannot be static final
          Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
  
          Set<ConstraintViolation<RaftConfiguration>> violations = validator.validate(configuration);
          if (!violations.isEmpty()) {
              throw new RaftConfigurationException(violations);
          }
  
          return configuration;
      }
docs: Validates a pre-existing {@link io.libraft.agent.configuration.RaftConfiguration}
  instance. The following basic validation checks are performed:
  <ul>
  <li>All required configuration fields are present.</li>
  <li>There are no unrecognized configuration elements.</li>
  <li>Endpoints are specified in valid <em>"host:port"</em> form.</li>
  <li>All ports are in the valid port range.</li>
  <li>All timeouts have values >= 0.</li>
  </ul>
  If an optional configuration block is present, it too is validated using the rules above.
  More thorough validation is performed by components that use the configuration properties.
  
  @param configuration instance of {@code RaftConfiguration} to validate
  @return {@code configuration} (useful if callers would like to method-chain)
  
  @throws RaftConfigurationException if the configuration specified in {@code configuration} has errors