On 5/21/2015 4:56 PM, Marko Strukelj wrote:
We package examples with jboss-deployment-structure.xml that looks
like this:
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.apache.httpcomponents"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
If we drop a .war containing this into Wildfly 9 (distribution/server-dist - ATM
distribution/demo-dist, and distribution/adapters/wildfly-adapter-zip look buggy as they
still use slot=4.3), things are fine.
However, if we dropped this into Wildfly 8 with keycloak adapter modules using
org.apache.httpcomponents slot=4.3, we get a java.lang.LinkageError as soon as some
Keycloak logic is triggered by user app.
The question: how come jboss modules isolation doesn’t kick in and allow keycloak adapter
modules to use slot=4.3 while at the same time user app (our examples) uses slot=main?
The answer is that org.keycloak.adapters.HttpClientBuilder which seems to be our helper
class for org.apache.httpcomponents inevitably leaks the version of HttpClient its module
refers to - can’t be any other way (unless we change the code to use client app’s
classloader - opening a can of worms). Any user app using HttpClientBuilder.build() method
receives an instance of HttpClient loaded through org.keycloak.keycloak-adapter-core
module, and transitively through org.apache.httpcomponents referred to therein.
Any attempt of an application (.war) to package its own httpcomponents jars, or to refer
to a different jboss module than the exact one referred to by
org.keycloak.keycloak-adapter-core will result in ‘catastrophic failure’. Example:
HttpClient client = new HttpClientBuilder().disableTrustManager().build();
HttpClient on the left is loaded by app’s classloader. The one returned by build() on the
right is loaded by org.keycloak.keycloak-adapter-core module’s version of httpcomponents.
If it’s not the same classloader (jboss module) on both sides loading HttpClient you get a
LinkageError.
In light of this I wonder if it wasn’t the best solution to reexport
org.apache.httpcomponents to .wars by default, thereby removing the necessity to package
jboss-deployment-structure.xml at all, and ensuring that user application always uses the
proper module.
Currently jboss-deployment-structure.xml is required for wildfly / as7, and is a
nuisance, especially as it has to be different (refer to slot=4.3) for Wildfly 8.
If using HttpClientBuilder is supposed to be completely optional, we could maybe add
configuration to keycloak subsystem to control exposing it to all or specific secure
deployments.
We could simply add another common attribute that can be used in <realm> and
<secure-deployment>. We could expose it by default and have something like:
<expose-httpcomponents>false</expose-httpcomponents>
to inhibit exposing it if a situation calls for it.
WDYT?
What do I think? I think that classloading questions always make my
head hurt!
The best solution would be to find a way to detect the problem and fix
it at deploy time. Using a DependencyProcessor, it should be possible
to detect that the deployment contains the same module from two
different slots. Then pick the best slot and spit out a warning message
that you are removing the undesirable module.
It should be possible, but I don't know if it actually _IS_ possible. A
version mismatch between modules is like a cancer. I think you should
speak to an oncologist or David Lloyd. Since Red Hat doesn't employ any
oncologists, go with David. :-)
_______________________________________________
keycloak-dev mailing list
keycloak-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/keycloak-dev