英文:
java.util.Properties doesn't work properly when initializing it with another instance of java.util.Properties
问题
这段代码可以工作:
import org.apache.kafka.clients.consumer.{ConsumerConfig, KafkaConsumer}
import java.util.Properties
object KafkaConsumerWithAuth extends App {
val props = new Properties()
props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "redacted")
props.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer")
props.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer")
props.setProperty("security.protocol", "SASL_SSL")
props.setProperty("sasl.mechanism", "PLAIN")
props.setProperty("sasl.jaas.config", "redacted")
props.setProperty("ssl.endpoint.identification.algorithm", "")
props.setProperty("ssl.truststore.location", "redacted.jks")
props.setProperty("ssl.truststore.password", "redacted")
lazy val consumer = new KafkaConsumer(props)
println(consumer.listTopics())
}
但这段代码不行:
import org.apache.kafka.clients.consumer.{ConsumerConfig, KafkaConsumer}
import java.util.Properties
object KafkaConsumerWithAuth extends App {
val props = new Properties({
val props = new Properties()
props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "redacted")
props.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer")
props.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer")
props.setProperty("security.protocol", "SASL_SSL")
props.setProperty("sasl.mechanism", "PLAIN")
props.setProperty("sasl.jaas.config", "redacted")
props.setProperty("ssl.endpoint.identification.algorithm", "")
props.setProperty("ssl.truststore.location", "redacted.jks")
props.setProperty("ssl.truststore.password", "redacted")
props
})
lazy val consumer = new KafkaConsumer(props)
println(consumer.listTopics())
}
出现问题的原因是第二段代码中的 props
并没有正确地复制第一个 props
的配置,所以导致了错误。要使第二段代码生效,你可以使用 props.clone()
来创建一个副本,确保配置被正确复制。
至于Java版本的代码,它可以工作,因为Java中的 Properties
类的 clone
方法会创建一个副本,正确复制了配置。所以,Java版本的代码没有问题。
英文:
This code works:
import org.apache.kafka.clients.consumer.{ConsumerConfig, KafkaConsumer}
import java.util.Properties
object KafkaConsumerWithAuth extends App {
val props = new Properties()
props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "redacted")
props.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer")
props.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer")
props.setProperty("security.protocol", "SASL_SSL")
props.setProperty("sasl.mechanism", "PLAIN")
props.setProperty("sasl.jaas.config", "redacted")
props.setProperty("ssl.endpoint.identification.algorithm", "")
props.setProperty("ssl.truststore.location", "redacted.jks")
props.setProperty("ssl.truststore.password", "redacted")
lazy val consumer = new KafkaConsumer(props)
println(consumer.listTopics())
}
but this code doesn't:
import org.apache.kafka.clients.consumer.{ConsumerConfig, KafkaConsumer}
import java.util.Properties
object KafkaConsumerWithAuth extends App {
val props = new Properties({
val props = new Properties()
props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "redacted")
props.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer")
props.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer")
props.setProperty("security.protocol", "SASL_SSL")
props.setProperty("sasl.mechanism", "PLAIN")
props.setProperty("sasl.jaas.config", "redacted")
props.setProperty("ssl.endpoint.identification.algorithm", "")
props.setProperty("ssl.truststore.location", "redacted")
props.setProperty("ssl.truststore.password", "redacted")
props
})
lazy val consumer = new KafkaConsumer(props)
println(consumer.listTopics())
}
How come? I wanted to program it this way, because I wanted props
to also be lazy, setProperty
triggers execution if you do it like this:
lazy val props = new Property()
props.setProperty(..., ...) // this triggers execution, so I can't go with this approach
When I run the code that doesn't work, I get this error:
Exception in thread "main" org.apache.kafka.common.config.ConfigException: Invalid value null for configuration key.deserializer: must be non-null.
at org.apache.kafka.clients.consumer.ConsumerConfig.appendDeserializerToConfig(ConsumerConfig.java:630)
at org.apache.kafka.clients.consumer.KafkaConsumer.<init>(KafkaConsumer.java:671)
at org.apache.kafka.clients.consumer.KafkaConsumer.<init>(KafkaConsumer.java:652)
at org.apache.kafka.clients.consumer.KafkaConsumer.<init>(KafkaConsumer.java:632)
at main.KafkaConsumerWithAuth$.consumer$lzycompute(KafkaConsumerWithAuth.scala:23)
at main.KafkaConsumerWithAuth$.consumer(KafkaConsumerWithAuth.scala:23)
at main.KafkaConsumerWithAuth$.delayedEndpoint$main$KafkaConsumerWithAuth$1(KafkaConsumerWithAuth.scala:25)
at main.KafkaConsumerWithAuth$delayedInit$body.apply(KafkaConsumerWithAuth.scala:7)
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.collection.immutable.List.foreach(List.scala:381)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
at scala.App$class.main(App.scala:76)
at main.KafkaConsumerWithAuth$.main(KafkaConsumerWithAuth.scala:7)
at main.KafkaConsumerWithAuth.main(KafkaConsumerWithAuth.scala)
So, it looks like the inner java.util.Properties
object wasn't copied properly.
I tried the same approach with java, when you have 1 java.util.Properties
instance and you create another one with it, it also doesn't work:
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import java.util.Properties;
public class KafkaConsumerJava {
public static void main(String[] args) {
Properties props = new Properties();
props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "redacted");
props.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
props.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
props.setProperty("security.protocol", "SASL_SSL");
props.setProperty("sasl.mechanism", "PLAIN");
props.setProperty("sasl.jaas.config", "redacted");
props.setProperty("ssl.endpoint.identification.algorithm", "");
props.setProperty("ssl.truststore.location", "redacted");
props.setProperty("ssl.truststore.password", "redacted");
Properties props2 = new Properties(props);
KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(props2);
System.out.println(consumer.listTopics());
}
}
答案1
得分: 1
根据文档,构造函数 Properties(Properties)
用于设置一组默认属性值,而不是用于设置属性值。
英文:
Per the documentation, the constructor Properties(Properties)
is used to set a list of default property values, not to set the property values.
答案2
得分: 1
你应该使用props1.putAll(props2)
来合并这两者。
英文:
You should use props1.putAll(props2)
if you want to merge the two.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论