Created
November 6, 2023 15:13
-
-
Save transducer/7bb822bd3ab573301daf794b6a983bc6 to your computer and use it in GitHub Desktop.
Custom RESTEasy client for Keycloak in Clojure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns custom-resteasy-client | |
"Creates a custom `javax.ws.rs.client.Client` with settings for timeouts, | |
evicting idle connections and a retry handler. This client can be a | |
resteasyClient for KeycloakBuilder that does not lead to \"RESTEASY004655 | |
Unable to invoke request: java.net.SocketException: Connection reset errors\" | |
according to the suggestion in | |
https://github.com/keycloak/keycloak/issues/8917#issuecomment-1712895984." | |
(:import | |
(java.util.concurrent TimeUnit) | |
(org.apache.http.impl.client DefaultHttpRequestRetryHandler HttpClients) | |
(org.apache.http.impl.conn PoolingHttpClientConnectionManager) | |
(org.jboss.resteasy.client.jaxrs ResteasyClientBuilder) | |
(org.jboss.resteasy.client.jaxrs.engines ApacheHttpClient43Engine))) | |
(defn- build-http-client [] | |
(let [cm (doto (PoolingHttpClientConnectionManager.) | |
(.setValidateAfterInactivity 1000) | |
(.setMaxTotal 200) | |
(.setDefaultMaxPerRoute 20))] | |
(.. (HttpClients/custom) | |
(setConnectionManager cm) | |
evictExpiredConnections | |
(evictIdleConnections 10000 TimeUnit/MILLISECONDS) | |
(setRetryHandler DefaultHttpRequestRetryHandler/INSTANCE) | |
build))) | |
(defn build | |
"Creates a custom `javax.ws.rs.client.Client` with settings for timeouts, | |
evicting idle connections and a retry handler" | |
[] | |
(let [http-client (build-http-client) | |
engine (ApacheHttpClient43Engine. http-client)] | |
(.. (ResteasyClientBuilder/newBuilder) | |
(httpEngine engine) | |
(connectTimeout 10000 TimeUnit/MILLISECONDS) | |
(readTimeout 7000 TimeUnit/MILLISECONDS) | |
(connectionTTL -1 TimeUnit/MILLISECONDS) | |
disableTrustManager | |
build))) | |
(ns keycloak | |
(:require | |
[clojure.tools.logging :as log] | |
[custom-resteasy-client :as custom-resteasy-client] | |
[integrant.core :as ig]) | |
(:import | |
(org.keycloak OAuth2Constants) | |
(org.keycloak.admin.client KeycloakBuilder))) | |
(defn create-keycloak-client-realm | |
[realm server-url client-id client-secret username user-password] | |
(.. KeycloakBuilder | |
builder | |
(serverUrl server-url) | |
(realm realm) | |
(grantType OAuth2Constants/PASSWORD) | |
(clientId client-id) | |
(clientSecret client-secret) | |
(username username) | |
(password user-password) | |
(resteasyClient (custom-resteasy-client/build)) | |
build | |
(realm realm))) |
@johann-oikonomou this gist is a translation of someone else's java code to clojure on the GitHub issue about the socket timeouts mentioned in the comment. The settings and timeouts are sensible defaults. Note that in our case it did not solve all socket exceptions, but reduced them by a factor 10.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi!
Awesome piece of work 👍
Did you tune the settings/timeouts to your needs or are they the default ones keycloak would use?