Class RestClientProcessor

java.lang.Object
javax.annotation.processing.AbstractProcessor
com.shri.restinpeace.processor.RestClientProcessor
All Implemented Interfaces:
Processor

@SupportedAnnotationTypes("com.shri.restinpeace.annotation.marker.RestClient") @SupportedSourceVersion(RELEASE_8) public class RestClientProcessor extends AbstractProcessor
Generates a compile-time implementation (<Interface>_RipImpl) of every @RestClient interface with at least one method that falls within the currently-supported shape: a single fixed HTTP verb, @PathParam/@QueryParam/@HeaderParam/ @QueryMap/@HeaderMap/@Body/@Url/ @Part/@PartMap/@Field/@FieldMap/ @Destination/an UploadProgressListener/ DownloadProgressListener parameter, optional @Timeout/ @Retry/@Headers/@ErrorType/@Multipart/ @FormUrlEncoded, and a void, String, non-generic POJO, byte[], File, or RipResponse<T> (for any of the previous return-type shapes) return type. RIP.getClient(...) prefers this generated class over the reflective java.lang.reflect.Proxy it falls back to entirely for an interface with no codegen-eligible method at all - see docs/design/compile-time-proxy-generation.md for the full design this is step 2 of.

A default method needs no generated override at all - the generated class simply doesn't declare one, so ordinary Java default-method dispatch resolves it via the generated class's own inherited implementation (including any call back into another interface method, which still reaches this processor's generated override for it). A static method isn't part of the implementing contract at all and is never called through an instance, so nothing is generated for it either.

A method using a feature outside the supported shape above (a generic collection return type like List<User>, a raw CompletableFuture, ...) no longer disqualifies the whole interface's codegen - only that one method falls back, delegating to a lazily-built internal java.lang.reflect.Proxy (see appendReflectiveFallbackAccessor(java.lang.StringBuilder, java.lang.String)) backed by this exact client's own RequestExecutor, so it still shares this client's retry/cache/ interceptor/timeout config. Every other method on the same interface still gets a real generated implementation. An interface with no codegen-eligible method at all still isn't generated for - the plain reflective proxy already covers that case with less indirection than a generated class made entirely of fallback-delegating methods would add. A nested/private interface declaration is a separate, structural precondition unrelated to any one method's shape, and still disqualifies the whole interface (not yet supported at all).

Before any of that, every @RestClient interface this processor sees - whether or not it also happens to have a codegen-eligible method - is run through CompileTimeRestClientValidator, the compile-time counterpart of ReflectiveRestClientValidator's semantic rules (an invalid @Retry, a malformed @Headers entry, an unmatched path param, ...). A problem there fails compilation outright, with the same message ReflectiveRestClientValidator would otherwise only report at the first RIP.getClient(...) call - step 4 of docs/design/compile-time-proxy-generation.md.

  • Constructor Details

    • RestClientProcessor

      public RestClientProcessor()
      Instantiated reflectively by the annotation-processing tool via its META-INF/services SPI registration.
  • Method Details