@@ -2,25 +2,34 @@ package net.manub.embeddedkafka
22
33import java .net .InetSocketAddress
44import java .util .Properties
5+ import java .util .concurrent .Executors
56
7+ import kafka .consumer .{Consumer , ConsumerConfig , Whitelist }
8+ import kafka .serializer .StringDecoder
69import kafka .server .{KafkaConfig , KafkaServer }
710import org .apache .kafka .clients .producer .{KafkaProducer , ProducerRecord }
811import org .apache .kafka .common .serialization .StringSerializer
912import org .apache .zookeeper .server .{ServerCnxnFactory , ZooKeeperServer }
1013import org .scalatest .Suite
11- import scala .collection .JavaConversions .mapAsJavaMap
1214
15+ import scala .collection .JavaConversions .mapAsJavaMap
16+ import scala .concurrent .duration ._
17+ import scala .concurrent .{Await , ExecutionContext , Future }
18+ import scala .language .postfixOps
1319import scala .reflect .io .Directory
1420
1521trait EmbeddedKafka {
1622
1723 this : Suite =>
1824
25+ val executorService = Executors .newFixedThreadPool(2 )
26+ implicit val executionContext = ExecutionContext .fromExecutorService(executorService)
27+
1928 /**
2029 * Starts a ZooKeeper instance and a Kafka broker, then executes the body passed as a parameter.
2130 *
2231 * @param body the function to execute
23- * @param config an implicit { @see EmbeddedKafkaConfig}
32+ * @param config an implicit [[ EmbeddedKafkaConfig ]]
2433 */
2534 def withRunningKafka (body : => Unit )(implicit config : EmbeddedKafkaConfig ) = {
2635
@@ -40,9 +49,9 @@ trait EmbeddedKafka {
4049 *
4150 * @param topic the topic to which publish the message (it will be auto-created)
4251 * @param message the message to publish
43- * @param config an implicit { @see EmbeddedKafkaConfig}
52+ * @param config an implicit [[ EmbeddedKafkaConfig ]]
4453 */
45- def publishToKafka (topic : String , message : String )(implicit config : EmbeddedKafkaConfig ) = {
54+ def publishToKafka (topic : String , message : String )(implicit config : EmbeddedKafkaConfig ): Unit = {
4655
4756 val producerProps = Map (
4857 " bootstrap.servers" -> s " localhost: ${config.kafkaPort}" ,
@@ -56,6 +65,37 @@ trait EmbeddedKafka {
5665 kafkaProducer.close()
5766 }
5867
68+
69+ /**
70+ * Consumes the first message available in a given topic, deserializing it as a String.
71+ * Throws a [[java.util.concurrent.TimeoutException ]] if a message is not available in 3 seconds.
72+ *
73+ * @param topic the topic to consume a message from
74+ * @param config an implicit [[EmbeddedKafkaConfig ]]
75+ * @return the first message consumed from the given topic
76+ */
77+ def consumeFirstMessageFrom (topic : String )(implicit config : EmbeddedKafkaConfig ): String = {
78+ val props = new Properties ()
79+ props.put(" group.id" , " scalatest-embedded-kafka-spec" )
80+ props.put(" zookeeper.connect" , s " localhost: ${config.zooKeeperPort}" )
81+ props.put(" auto.offset.reset" , " smallest" )
82+
83+ val consumer = Consumer .create(new ConsumerConfig (props))
84+
85+ val filter = Whitelist (topic)
86+ val messageStreams =
87+ consumer.createMessageStreamsByFilter(filter, keyDecoder = new StringDecoder , valueDecoder = new StringDecoder )
88+
89+ val messageFuture = Future { messageStreams.head.iterator().next().message() }
90+
91+ try {
92+ Await .result(messageFuture, 3 seconds)
93+ } finally {
94+ consumer.shutdown()
95+ }
96+ }
97+
98+
5999 private def startZooKeeper (zooKeeperPort : Int ): ServerCnxnFactory = {
60100 val zkLogsDir = Directory .makeTemp(" zookeeper-logs" )
61101 val tickTime = 2000
0 commit comments