找到java.util.concurrent.Future必需的scala.concurrent.Future

时间:2017-09-18 09:28:01

标签: scala apache-kafka akka akka-http reactive-kafka

相关:scala.concurrent.Future wrapper for java.util.concurrent.Future

这来自我的另一个问题:

How to integrate akka streams kafka (reactive-kafka) into akka http application?

我有一个AKKA HTTP应用程序,我想在我的路由中的onComplete函数中向Kafka发送一条消息/ ProducerRecord,如下所示:

val producer : KafkaProducer = new KafkaProducer(producerSettings)

val routes : Route = 
  post {
    entity(as[User]) { user =>
      val createUser = userService.create(user)
      onSuccess(createUser) {
        case Invalid(y: NonEmptyList[Err]) =>  
          complete(BadRequest -> "invalid user")
        case Valid(u: User) => { 
          val producerRecord = 
            new ProducerRecord[Array[Byte], String]("topic1","some message")

          onComplete(producer.send(producerRecord)) { _ =>
            complete(ToResponseMarshallable((StatusCodes.Created, u)))
          }
        }
      }
    }
  }

然而, onComplete(producer send producerRecord)会产生以下类型不匹配错误:

[error] found:Future [org.apache.kafka.clients.producer.RecordMetadata](在java.util.concurrent中) [error] required:Future [org.apache.kafka.clients.producer.RecordMetadata](在scala.concurrent中) [错误] onCompleteRecordMetadata {_ =>

有没有办法解决这个问题,可能是使用Producer作为接收器(http://doc.akka.io/docs/akka-stream-kafka/current/producer.html#producer-as-a-sink)而不是java producer.send 函数?

2 个答案:

答案 0 :(得分:3)

为了回答您的具体问题,scala-java8-compat库提供了java8和Scala期货之间的转换器。

具体来说,您可以使用FutureConverters.toScala(producer.send(producerRecord))form .field.optionset input { float: left; clear: left; margin-top: 5px; } form .field.optionset ul label { padding-left: 24px; } 转换为java.util.concurrent.Future

但是,使用具有Scala友好API本身的客户端库(如上面Stefano所建议的)可能会为您带来最佳结果。

答案 1 :(得分:2)

你可以利用Cake's Scala based Kafka client,它将完成运行Java期货的工作,并为你提供Scala期货。确保创建cakesolutions.kafka.KafkaProducer而不是org.apache.kafka.clients.producer.KafkaProducer后,其余代码应该保持不变。

或者,您可以在保持使用高级Akka HTTP DSL的同时利用Reactive Kafka对其进行排序。您可以通过以下方式将生产者记录运行到Kafka Sink来实现:

val producerSink = Producer.plainSink(producerSettings)

...
        // inside the route
        val producerRecord =
          new ProducerRecord[Array[Byte], String]("topic1", "some message")

        onComplete(Source.single(producerRecord).runWith(producerSink)) { _ =>
          complete(ToResponseMarshallable((StatusCodes.Created, u)))
        }