Building an SPI to push events into Kafka, to get deployed as an EAR inside Keycloak 6.0.1, which uses the WildFly Server, packaged in a Docker image based on jboss/keycloak:6.0.1
.
I ran into: Kafka Producer - org.apache.kafka.common.serialization.StringSerializer could not be found
So I applied the suggested solution of setting Thread.currentThread().setContextClassLoader(null);
.
This seems to work fine for my local Kafka on port 9092, without authentication. As soon as I authenticate as described here:
String jaasTemplate = "org.apache.kafka.common.security.scram.ScramLoginModule required username=\"%s\" password=\"%s\";";
String jaasCfg = String.format(jaasTemplate, username, password);
Properties props = new Properties();
props.put("sasl.jaas.config", jaasCfg);
// ...
Thread.currentThread().setContextClassLoader(null);
KafkaProducer<String, String> producer = new KafkaProducer<>(props);
I run into the error:
org.apache.kafka.common.KafkaException: javax.security.auth.login.LoginException: unable to find LoginModule class: org.apache.kafka.common.security.scram.ScramLoginModule
at org.apache.kafka.common.network.SaslChannelBuilder.configure(SaslChannelBuilder.java:160)
at org.apache.kafka.common.network.ChannelBuilders.create(ChannelBuilders.java:146)
at org.apache.kafka.common.network.ChannelBuilders.clientChannelBuilder(ChannelBuilders.java:67)
at org.apache.kafka.clients.ClientUtils.createChannelBuilder(ClientUtils.java:99)
at org.apache.kafka.clients.producer.KafkaProducer.newSender(KafkaProducer.java:441)
at org.apache.kafka.clients.producer.KafkaProducer.<init>(KafkaProducer.java:422)
I suspect that this is caused by setting the ClassLoader to null
, but I'm not certain.
The JAAS string mentions this org.apache.kafka.common.security.scram.ScramLoginModule
. I tried not using JAAS but instead plain username + password like so:
Properties props = new Properties();
props.put("sasl.username", username);
props.put("sasl.password", password);
// ...
Thread.currentThread().setContextClassLoader(null);
KafkaProducer<String, String> producer = new KafkaProducer<>(props);
But that also resulted in an Exception, just mentioning a different Class could not be located:
org.apache.kafka.common.KafkaException: javax.security.auth.login.LoginException: unable to find LoginModule class: org.jboss.as.security.remoting.RemotingLoginModule
at org.apache.kafka.common.network.SaslChannelBuilder.configure(SaslChannelBuilder.java:160)
at org.apache.kafka.common.network.ChannelBuilders.create(ChannelBuilders.java:146)
at org.apache.kafka.common.network.ChannelBuilders.clientChannelBuilder(ChannelBuilders.java:67)
at org.apache.kafka.clients.ClientUtils.createChannelBuilder(ClientUtils.java:99)
at org.apache.kafka.clients.producer.KafkaProducer.newSender(KafkaProducer.java:441)
at org.apache.kafka.clients.producer.KafkaProducer.<init>(KafkaProducer.java:422)
How can I make it, that the org.apache.kafka.common.security.scram.ScramLoginModule
is found? Thanks!
Warning: ugly hack!
Just before you create the KafkaProducer, set the context classloader shown bellow:
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());