I’m building a Keycloak custom provider (SPI) that adds claims to the access tokens generated by Keycloak. These claims should be obtained by performing external REST API calls. For the REST client I would like to use quarkus-rest-client-reactive-jackson
because it allows creating REST clients with interfaces (using the @RegisterRestClient
annotation), which is very fast and easy (actually, this comes from Eclipse Microprofiles). The problem is that when I call some REST endpoint I get the error Uncaught server error: java.lang.NoClassDefFoundError: org/eclipse/microprofile/rest/client/RestClientBuilder
. I have done some research and it seems that the dependency quarkus-rest-client-reactive-jackson
is not present in the Keycloak server (that is a Quarkus)… so I have to include it somehow.
The dependencies
part of my pom.xml
is the following:
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<scope>provided</scope>
<version>${keycloak.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi</artifactId>
<scope>provided</scope>
<version>${keycloak.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi-private</artifactId>
<scope>provided</scope>
<version>${keycloak.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<scope>provided</scope>
<version>${keycloak.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-jpa</artifactId>
<scope>provided</scope>
<version>${keycloak.version}</version>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<scope>provided</scope>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.json.bind</groupId>
<artifactId>jakarta.json.bind-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
<version>2.1.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.quarkus/quarkus-rest-client-reactive-jackson -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-reactive-jackson</artifactId>
<version>3.6.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
Focus on the last part, the quarkus-rest-client-reactive-jackson
dependency.
The REST client I’m using (implemented as an interface) is this one:
@RegisterRestClient()
@Path("/my-path")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public interface TokenRestInterface{
@POST
@Path("/token")
TokenDtoResponse getToken(@HeaderParam("User-Id") Integer userId, @FormParam("client_id") String clientId, @FormParam("client_secret") String clientSecret, @FormParam("grant_type") String grantType);
}
The part of the code where I call the REST client is the following:
TokenRestInterface tokenRestInterface = null;
try {
tokenRestInterface = RestClientBuilder.newBuilder().baseUrl(new URL("http://localhost:8080/")).build(TokenRestInterface.class);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
TokenDtoResponse tokenDtoResponse = keycloakRestInterface.getToken(userId, CLIENT_ID, CLIENT_SECRET, "client_credentials");
return tokenDtoResponse.getAccess_token();
The error I get when the previous code gets executed is:
2023-12-19 11:47:43,443 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-1) Uncaught server error: java.lang.NoClassDefFoundError: org/eclipse/microprofile/rest/client/RestClientBuilder
.
Based on this, I suppose the exception is thrown in the line: RestClientBuilder.newBuilder()...
.
Note that I included both jars (my provider and the dependency jar) in the providers
folder of Keycloak.
(Note that metacontratas-keycloak-provider
is the name of my project, my custom Keycloak provider)
Could you please explain to me how to solve this error? This is, do you know how to add correctly the dependency I’m using into the Keycloak service?
Thanks!