Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inclusion of resteasy-jackson2-provider in a Keycloak extension causes build failure #25589

Closed
1 task done
xgp opened this issue Dec 14, 2023 · 14 comments
Closed
1 task done

Comments

@xgp
Copy link
Contributor

xgp commented Dec 14, 2023

Before reporting an issue

  • I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.

Area

admin/client/java

Describe the bug

Sometimes extensions include the use of keycloak-admin-client, which depends on resteasy-jackson2-provider. >=23, after the upgrade to resteasy reactive, this seems to cause a build problem

Version

23

Expected behavior

This should allow the resteasy-jackson2-provider jar to be included in the providers/ dir.

Actual behavior

#0 3.859 Caused by: java.lang.NullPointerException: Cannot invoke "org.jboss.jandex.ClassInfo.name()" because "currentClazz" is null
#0 3.859 	at io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor.createTypedAnnotationInstance(ResteasyReactiveProcessor.java:850)
#0 3.859 	at io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor$6.transform(ResteasyReactiveProcessor.java:832)
#0 3.859 	at io.quarkus.arc.processor.AnnotationStore.transform(AnnotationStore.java:108)
#0 3.859 	at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1740)
#0 3.859 	at io.quarkus.arc.processor.AnnotationStore.getAnnotations(AnnotationStore.java:61)
#0 3.859 	at io.quarkus.arc.processor.AnnotationStore.hasAnnotation(AnnotationStore.java:85)
#0 3.859 	at io.quarkus.arc.processor.BeanDeployment.isVetoed(BeanDeployment.java:1277)
#0 3.859 	at io.quarkus.arc.processor.BeanDeployment.findBeans(BeanDeployment.java:1000)
#0 3.859 	at io.quarkus.arc.processor.BeanDeployment.registerBeans(BeanDeployment.java:271)
#0 3.859 	at io.quarkus.arc.processor.BeanProcessor.registerBeans(BeanProcessor.java:141)
#0 3.859 	at io.quarkus.arc.deployment.ArcProcessor.registerBeans(ArcProcessor.java:419)
#0 3.859 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
#0 3.859 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
#0 3.859 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
#0 3.859 	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
#0 3.859 	at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:864)
#0 3.860 	at io.quarkus.builder.BuildContext.run(BuildContext.java:282)
#0 3.860 	at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
#0 3.860 	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
#0 3.860 	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
#0 3.860 	at java.base/java.lang.Thread.run(Thread.java:840)
#0 3.860 	at org.jboss.threads.JBossThread.run(JBossThread.java:501)

How to Reproduce?

Create a Dockerfile that extends the base image with the resteasy-jackson2-provider jar in the providers/ dir and then runs build.

COPY ./org.jboss.resteasy-resteasy-jackson2-provider-6.2.4.Final.jar /opt/keycloak/providers/

RUN /opt/keycloak/bin/kc.sh --verbose build

Anything else?

Already noticed here #25265

Tried on nightly.

@xgp xgp added kind/bug Categorizes a PR related to a bug status/triage labels Dec 14, 2023
@koplas
Copy link

koplas commented Dec 22, 2023

@xgp Can you include the required keycloak-admin-client dependency in quarkus/runtime/pom.xml and build the server as described here: Building keycloak?
If you then declare the dependency in your extension as provided, it should no longer cause a conflict.

@xgp
Copy link
Contributor Author

xgp commented Dec 22, 2023 via email

@vince760
Copy link

I can try this. Can you explain exactly what this does? What is special about this library that requires a custom build of Keycloak? Are there other libraries with the same requirements? Is there any documentation that explains this? Thank you!

I am getting a build error when I do as suggested by @koplas...would be curious to know if yours builds.
image

@koplas
Copy link

koplas commented Dec 24, 2023

I am getting a build error when I do as suggested by @koplas...would be curious to know if yours builds. image

The following works for me:

  1. Clone the keycloak repo

  2. Run mvn -DskipTests clean install

  3. Add keycloak-admin-client-reactive to the runtime and keycloak-admin-client-reactive-deployment to deployment (Apply this keycloak-admin-client.diff.txt)

  4. Run mvn -pl quarkus/deployment,quarkus/dist -am -DskipTests clean install

I have not tested it, but now you should be able to use the keycloak-admin-client-reactive in your extension.

Can you explain exactly what this does? What is special about this library that requires a custom build of Keycloak? Are there other libraries with the same requirements? Is there any documentation that explains this?

Keycloak provides a couple of dependencies that the extension can use. For example, quarkus-resteasy-reactive is provided by the Quarkus runtime and can be used by the Keycloak extension. Using a dependency that uses the same transitive dependencies as the runtime can result in these errors. A workaround would be to exclude all conflicting dependencies, but this can break if you upgrade Keycloak.

I have a similar problem and the documentation and upgrade guide only mentions that the usage is deprecated and the application should be rewritten. Someone with Quarkus and Keycloak expertise can provide the intended way of including dependencies into the extension.

@xgp
Copy link
Contributor Author

xgp commented Dec 29, 2023

Thanks @koplas . It needed the quarkus-keycloak-admin-client-common as well, but it seems to work. Here is the patch I had to use:

diff --git a/quarkus/deployment/pom.xml b/quarkus/deployment/pom.xml
index 4476986c6d..824fff2267 100644
--- a/quarkus/deployment/pom.xml
    b/quarkus/deployment/pom.xml
@@ -170,6  170,19 @@
             <artifactId>rest-assured</artifactId>
             <scope>test</scope>
         </dependency>
 
         <!-- Dependencies used by keycloak extensions -->
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-keycloak-admin-client-common-deployment</artifactId>
             <version>3.2.9.Final</version>
         </dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-keycloak-admin-client-reactive-deployment</artifactId>
             <version>3.2.9.Final</version>
         </dependency>
 
     </dependencies>
 
     <build>
diff --git a/quarkus/runtime/pom.xml b/quarkus/runtime/pom.xml
index 50a99a9f85..8465d770a4 100644
--- a/quarkus/runtime/pom.xml
    b/quarkus/runtime/pom.xml
@@ -112,6  112,18 @@
             <artifactId>picocli</artifactId>
         </dependency>
 
 	<!-- Dependencies used by keycloak extensions -->
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-keycloak-admin-client-common</artifactId>
             <version>3.2.9.Final</version>
         </dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-keycloak-admin-client-reactive</artifactId>
             <version>3.2.9.Final</version>
         </dependency>
 
         <!-- Keycloak -->
         <dependency>
             <groupId>org.keycloak</groupId>

I appreciate your explanation, but I still don't really understand what is going on or why it requires a custom build. Does it have to do with those -deployment dependencies that end up in /opt/keycloak/lib/lib/deployment/ dir? And that gets used during the build phase to set up some of the quarkus magic?

I've been using the Keycloak Admin Client in extensions since version 9, and there has always been some problem. Between having to build your own module, RESTEasy dependency/version hell, and now this. It really makes the case to stop using it altogether.

@jemonra
Copy link

jemonra commented Jan 12, 2024

I'm also facing the same issue. Will this be fixed in a future version?

Thanks.

@koplas
Copy link

koplas commented Jan 12, 2024

This is more of an issue of how Quarkus handles extensions and not a keycloak specific problem.

@koplas
Copy link

koplas commented Jan 26, 2024

The root cause for this problem seems to be that different ClassLoaders are used.

@mposolda
Copy link
Contributor

I am adding to Backlog as not sure when Keycloak team has capacity to prioritize this. Anyone is welcome to investigate and send PR with fixing this if it can be fixed on Keycloak side in a nice way. See contributions guide for the details how to contribute a fix https://github.com/keycloak/keycloak/blob/main/CONTRIBUTING.md .

The possible workaround is also to not use keycloak-admin-client in your providers. As long as provider is deployed in Keycloak, it might be an option to use model-api directly (for example use something like session.realms().getRealm() to obtain RealmModel in your provider instead of calling keycloak-admin-client to obtain realm).

@xgp
Copy link
Contributor Author

xgp commented Feb 27, 2024

Thanks @mposolda

The diff that I sent solves it, but it causes the admin client to be bundled in Keycloak. Because there is not an external way to solve the use of the admin client, we found this to be the only way. I can PR that diff, but I'm not sure if Keycloak is willing to accept the addition of a library that is only depended on by extensions.

Regarding your workaround suggestion, I agree with using the KeycloakSession for cases where you are working agains the local Keycloak. However, we have a couple of extensions that actually manage remote Keycloaks (e.g. for managing multi-Realm, multi-tenancy) from an extension. I also (a while ago when I first encountered the problem of having to custom build a Wildfly module to import the admin client) did a quick search on GitHub of extensions that use the admin client. I found it to be fairly common. One of the other rationales I found (beyond communicating with remote Keycloaks) is that extension developers had used the admin client in their code so that it could be run both inside and outside of Keycloak, which I considered to be a pretty good argument.

Anyway, LMK if you would consider the diff as a PR, and I'll create a ticket and submit it.

@stianst
Copy link
Contributor

stianst commented Feb 28, 2024

We won't include the admin client in the dist that's for sure, so we need some other solution.

I'd give this a go and see if it works: https://quarkus.io/guides/security-keycloak-admin-client

@xgp
Copy link
Contributor Author

xgp commented Feb 28, 2024

Thanks for the clarification on including the admin client @stianst

I tried the quarkus "security-keycloak-admin-client" and I wasn't able to get it to work from inside Keycloak.

@keycloak-github-bot keycloak-github-bot bot removed this from the Backlog milestone Mar 6, 2024
@keycloak-github-bot
Copy link

Due to the amount of issues reported by the community we are not able to prioritise resolving this issue at the moment.

If you are affected by this issue, upvote it by adding a 👍 to the description. We would also welcome a contribution to fix the issue.

@keycloak-github-bot
Copy link

Due to lack of updates in the last 180 days this issue will be automatically closed.

@keycloak-github-bot keycloak-github-bot bot closed this as not planned Won't fix, can't repro, duplicate, stale Jun 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants