java.util.Properties doesn't work properly when initializing it with another instance of java.util.Properties

huangapple go评论89阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年6月29日 05:02:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76576682.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定