Class RIP

java.lang.Object
com.shri.restinpeace.RIP

public class RIP extends Object
Entry point for REST-in-peace: turns an annotated @RestClient interface into a working HTTP client backed by a JDK dynamic proxy, via getClient(Class).
  • Method Details

    • getClient

      public static <T> T getClient(Class<T> restClient)
      Validates restClient and returns a proxy implementing it, where each method call issues the HTTP request its annotations describe.
      Type Parameters:
      T - the rest client interface type
      Parameters:
      restClient - an interface annotated with @RestClient
      Returns:
      a proxy instance implementing restClient
      Throws:
      RestInPeaceException - if the interface is missing @RestClient or fails validation
    • getClient

      public static <T> T getClient(Class<T> restClient, String baseUrl)
      Same as getClient(Class), but every relative method URL is resolved against baseUrl instead of the interface's @BaseUrl - for a base URL that's only known at runtime (e.g. an app that deploys the same @RestClient interface against a different environment per deployment, read from an env var or config file). An absolute method URL still ignores this, same as it ignores @BaseUrl; @BaseUrl on the interface is itself optional when every relative method URL is covered by baseUrl here.
      Type Parameters:
      T - the rest client interface type
      Parameters:
      restClient - an interface annotated with @RestClient
      baseUrl - the runtime base URL to resolve relative method URLs against, or null to require @BaseUrl on the interface instead
      Returns:
      a proxy instance implementing restClient
      Throws:
      RestInPeaceException - if the interface is missing @RestClient or fails validation
    • getClient

      public static <T> T getClient(Class<T> restClient, RipClientConfig config)
      Same as getClient(Class), but resolves the base URL, connect/read timeout, and proxy from config instead of the interface's @BaseUrl and the shared client's global config - for a @RestClient whose environment (base URL, timeout, proxy) differs from every other client's. See RipClientConfig.
      Type Parameters:
      T - the rest client interface type
      Parameters:
      restClient - an interface annotated with @RestClient
      config - the per-client settings
      Returns:
      a proxy instance implementing restClient
      Throws:
      RestInPeaceException - if the interface is missing @RestClient or fails validation
    • useDaemonThreadsForAsync

      public static void useDaemonThreadsForAsync()
      Opt-in: makes a CompletableFuture-returning call use daemon threads for Unirest's async client, so a short-lived program can exit on its own after an async call instead of hanging on non-daemon I/O threads. Not the default, since it reconfigures Unirest's shared global client - call this once at startup, before building any client, only if your app doesn't already configure Unirest's async client itself.

      Covers every client sharing the app-wide static Unirest client and every RipClientConfig-backed client with its own dedicated UnirestInstance constructed after this call - a config'd client already built before this runs keeps whatever async client it was constructed with, the same "call once at startup, before building any client" requirement every other global RIP setting (setObjectMapper(kong.unirest.ObjectMapper), setCache(com.shri.restinpeace.cache.Cache)) already has.

    • setObjectMapper

      public static void setObjectMapper(kong.unirest.ObjectMapper objectMapper)
      Sets the ObjectMapper used to (de)serialize JSON request/response bodies for every client sharing the app-wide static Unirest client (i.e. every client not built with a RipClientConfig that sets its own timeout/proxy/objectMapper). RIP defaults to Unirest's own Gson-backed kong.unirest.JsonObjectMapper - call this to use Jackson or another mapper instead. A RipClientConfig-configured client with its own dedicated Unirest instance needs RipClientConfig.Builder.objectMapper(ObjectMapper) instead; this method has no effect on it.
      Parameters:
      objectMapper - the mapper to use
    • setCache

      public static void setCache(Cache cache)
      Sets the shared default Cache for response caching, used by every client not built with a RipClientConfig that sets its own via RipClientConfig.Builder.cache(Cache). Only GET responses are ever cached, and only those the server itself marks cacheable via Cache-Control/ETag/Last-Modified - no cache configured (the default) means no caching at all, byte-for- byte today's behavior.
      Parameters:
      cache - the shared default cache, or null to disable caching for every client without its own Cache
    • setCacheKeyIncludesQueryString

      public static void setCacheKeyIncludesQueryString(boolean includeQueryString)
      Sets whether the cache key includes the request's query string, for every client not built with a RipClientConfig that sets its own via RipClientConfig.Builder.cacheKeyIncludesQueryString(boolean). Defaults to true - /items?page=1 and /items?page=2 are cached separately, matching today's behavior. Turn this off for an endpoint whose query params don't affect the response (e.g. an analytics/tracking param), so every query-string variant of the same path shares one cache entry instead - trading that precision for a higher hit rate. Has no effect on a client with no Cache configured at all.
      Parameters:
      includeQueryString - whether the cache key includes the query string
    • setNegativeCacheTtlMillis

      public static void setNegativeCacheTtlMillis(long ttlMillis)
      Sets the shared default negative-cache TTL, for every client not built with a RipClientConfig that sets its own via RipClientConfig.Builder.negativeCacheTtlMillis(long). A confirmed 404 is then stored for ttlMillis, regardless of whether the response itself carries any Cache-Control/ ETag/Last-Modified at all - unlike every other cached status, which is only ever stored when the server's own headers say so - so a client stops hammering a downstream for a resource it already confirmed doesn't exist. Not called at all (the default) means no negative caching, byte-for-byte today's behavior. Has no effect on a client with no Cache configured at all, and is skipped the same way by @NoCache.
      Parameters:
      ttlMillis - how long a confirmed 404 stays negatively cached, in milliseconds; must be positive
    • addInterceptor

      public static void addInterceptor(RequestInterceptor interceptor)
      Registers a global hook into every request/response made through RIP - see RequestInterceptor for what it can and can't do.
      Parameters:
      interceptor - the interceptor to register
    • removeInterceptor

      public static void removeInterceptor(RequestInterceptor interceptor)
      Removes one previously registered global interceptor by identity, leaving every other registered interceptor - including other instances of the same class - untouched. For an embedder (e.g. a dependency-injection framework's auto-configuration) that registers its own beans as global interceptors on startup and needs to reverse exactly those on shutdown, since clearInterceptors() would also wipe out interceptors some other, still-live part of the same JVM registered (this registry is shared process-wide, not scoped to any one caller).
      Parameters:
      interceptor - the interceptor instance to remove; a no-op if it was never registered (or already removed)
    • clearInterceptors

      public static void clearInterceptors()
      Removes all registered interceptors. Mainly useful for tests - removes every interceptor registered by anyone, not just the caller's own; see removeInterceptor(RequestInterceptor) for a narrower alternative.
    • addCallAdapterFactory

      public static void addCallAdapterFactory(CallAdapterFactory factory)
      Registers a global CallAdapterFactory, letting a method declare a return type RIP itself has no built-in support for (e.g. Project Reactor's Mono<T>/Flux<T>, via the separate rest-in-peace-reactor module). Call once at startup, before building any client - the same "configure globals first" requirement setObjectMapper(kong.unirest.ObjectMapper)/setCache(com.shri.restinpeace.cache.Cache)/useDaemonThreadsForAsync() already have, since a factory needs to be registered before ReflectiveRestClientValidator validates a method claiming it. See docs/design/reactor-call-adapter.md.
      Parameters:
      factory - the factory to register
    • removeCallAdapterFactory

      public static void removeCallAdapterFactory(CallAdapterFactory factory)
      Removes one previously registered global CallAdapterFactory by identity; a no-op if it was never registered (or already removed).
      Parameters:
      factory - the factory instance to remove
    • clearCallAdapterFactories

      public static void clearCallAdapterFactories()
      Removes every registered CallAdapterFactory. Mainly useful for tests.
    • addPaginatedCallAdapterFactory

      public static void addPaginatedCallAdapterFactory(PaginatedCallAdapterFactory factory)
      Registers a global PaginatedCallAdapterFactory, letting a @Paginated method declare a return type RIP itself has no built-in support for (e.g. Project Reactor's Flux<T>, via the separate rest-in-peace-reactor module) - the pagination-aware counterpart of addCallAdapterFactory(com.shri.restinpeace.CallAdapterFactory). Call once at startup, before building any client, for the same reason. See docs/design/reactor-call-adapter.md ยง7.2.
      Parameters:
      factory - the factory to register
    • removePaginatedCallAdapterFactory

      public static void removePaginatedCallAdapterFactory(PaginatedCallAdapterFactory factory)
      Removes one previously registered global PaginatedCallAdapterFactory by identity; a no-op if it was never registered (or already removed).
      Parameters:
      factory - the factory instance to remove
    • clearPaginatedCallAdapterFactories

      public static void clearPaginatedCallAdapterFactories()
      Removes every registered PaginatedCallAdapterFactory. Mainly useful for tests.