0
votes

I have kafkaProducer actor:

class KafkaProducerActor @Inject()(
  avroProducer: MyKafkaProducerAvro,
  jsonProducer: MyKafkaProducerJson,
  metrics: PrometheusMetricsService
)
  extends Actor
{
  def handleErrs(block: => Unit): Unit = {
    try {
      block
    } catch {
      case e: Exception =>
        Logger.error(s"failed to produce kafka message, error: ${e.getMessage}, cause: ${ExceptionUtils.getRootCause(e)}, stacktrace: ${ExceptionUtils.getStackTrace(e)}")
        metrics.incKafkaErrorCounter(e.getClass.getName)
    }
  }

  override def receive: Receive = {
    case rec: ProducerRecord[GenericRecord, GenericRecord] =>
      handleErrs(avroProducer.produce(rec))

    case ProducerRecordJson(topic, key, content) =>
      handleErrs(jsonProducer.produce(new ProducerRecord[String, String](topic, key, content)))
  }
}

Also, i'm trying to use actorSystem to get the actorRef:

  val kafka: ActorRef = actorSystem.actorOf(KafkaProducerActor.props, name = "kafkaProducerActor")

For that i defined in KafkaProducerActor:

object KafkaProducerActor {
  def props: Props = Props(classOf[KafkaProducerActor])
}

which Warns the following:

Appropriate actor constructor not found Dynamic invocation could be replaced with a constructor invocation

when replacing dynamic invocation with a constructor invocation (as compiler suggest) i.e:

object KafkaProducerActor {
  def props: Props = Props(new KafkaProducerActor())
}

I get compilation error:

Unspecified value parameters: avroProducer: MyKafkaProducerAvro, jsonProducer: MyKafkaProducerJson, metrics: PrometheusMetricsService

what is the right way to initiate the Props in this situation?

1

1 Answers

0
votes

You should inject your services in the context where you call KafkaProducerActor.props and just pass it as parameters.

Or just inject it manually into the constructor but you will need a static global injection for that. You can achieve it with helpers like that:

object InjectHelper {
    lazy val injector: Injector = {
        val moduleInstance: com.google.inject.Module = ??? // somehow get  your guice module
        Guice.createInjector(moduleInstance)
    }

    def inject[T](implicit mf: Manifest[T]): T =
        InjectHelper.injector.getInstance(mf.runtimeClass).asInstanceOf[T]
}

object KafkaProducerActor {
  def props: Props = Props(
    new KafkaProducerActor(
      InjectHelper.inject[MyKafkaProducerAvro],
      InjectHelper.inject[MyKafkaProducerJson],
      InjectHelper.inject[PrometheusMetricsService]
    )
  )
}