@@ -5,22 +5,22 @@ import java.util.Properties
5
5
import java .util .concurrent .Executors
6
6
7
7
import kafka .admin .AdminUtils
8
- import kafka .consumer .{Consumer , ConsumerConfig , Whitelist }
9
- import kafka .serializer .{Decoder , StringDecoder }
10
8
import kafka .server .{KafkaConfig , KafkaServer }
11
9
import kafka .utils .ZkUtils
10
+ import org .apache .kafka .clients .consumer .KafkaConsumer
12
11
import org .apache .kafka .clients .producer .{KafkaProducer , ProducerConfig , ProducerRecord }
13
- import org .apache .kafka .common .serialization .{Serializer , StringSerializer }
12
+ import org .apache .kafka .common .KafkaException
13
+ import org .apache .kafka .common .serialization .{Deserializer , Serializer , StringDeserializer , StringSerializer }
14
14
import org .apache .zookeeper .server .{ServerCnxnFactory , ZooKeeperServer }
15
15
import org .scalatest .Suite
16
16
17
+ import scala .collection .JavaConversions
17
18
import scala .collection .JavaConversions .mapAsJavaMap
18
- import scala .concurrent ._
19
19
import scala .concurrent .duration ._
20
+ import scala .concurrent .{ExecutionContext , TimeoutException }
20
21
import scala .language .{higherKinds , postfixOps }
21
22
import scala .reflect .io .Directory
22
23
import scala .util .Try
23
- import scala .util .control .NonFatal
24
24
25
25
trait EmbeddedKafka extends EmbeddedKafkaSupport {
26
26
this : Suite =>
@@ -77,14 +77,14 @@ sealed trait EmbeddedKafkaSupport {
77
77
val executorService = Executors .newFixedThreadPool(2 )
78
78
implicit val executionContext = ExecutionContext .fromExecutorService(executorService)
79
79
80
- val zkSessionTimeoutMs = 10000
80
+ val zkSessionTimeoutMs = 10000
81
81
val zkConnectionTimeoutMs = 10000
82
82
val zkSecurityEnabled = false
83
83
84
84
/**
85
85
* Starts a ZooKeeper instance and a Kafka broker, then executes the body passed as a parameter.
86
86
*
87
- * @param body the function to execute
87
+ * @param body the function to execute
88
88
* @param config an implicit [[EmbeddedKafkaConfig ]]
89
89
*/
90
90
def withRunningKafka (body : => Unit )(implicit config : EmbeddedKafkaConfig ) = {
@@ -104,9 +104,9 @@ sealed trait EmbeddedKafkaSupport {
104
104
* Publishes synchronously a message of type [[String ]] to the running Kafka broker.
105
105
*
106
106
* @see [[EmbeddedKafka#publishToKafka ]]
107
- * @param topic the topic to which publish the message (it will be auto-created)
107
+ * @param topic the topic to which publish the message (it will be auto-created)
108
108
* @param message the [[String ]] message to publish
109
- * @param config an implicit [[EmbeddedKafkaConfig ]]
109
+ * @param config an implicit [[EmbeddedKafkaConfig ]]
110
110
* @throws KafkaUnavailableException if unable to connect to Kafka
111
111
*/
112
112
def publishStringMessageToKafka (topic : String , message : String )(implicit config : EmbeddedKafkaConfig ): Unit =
@@ -115,9 +115,9 @@ sealed trait EmbeddedKafkaSupport {
115
115
/**
116
116
* Publishes synchronously a message to the running Kafka broker.
117
117
*
118
- * @param topic the topic to which publish the message (it will be auto-created)
119
- * @param message the message of type [[T ]] to publish
120
- * @param config an implicit [[EmbeddedKafkaConfig ]]
118
+ * @param topic the topic to which publish the message (it will be auto-created)
119
+ * @param message the message of type [[T ]] to publish
120
+ * @param config an implicit [[EmbeddedKafkaConfig ]]
121
121
* @param serializer an implicit [[Serializer ]] for the type [[T ]]
122
122
* @throws KafkaUnavailableException if unable to connect to Kafka
123
123
*/
@@ -144,48 +144,46 @@ sealed trait EmbeddedKafkaSupport {
144
144
}
145
145
146
146
def consumeFirstStringMessageFrom (topic : String )(implicit config : EmbeddedKafkaConfig ): String =
147
- consumeFirstMessageFrom(topic)(config, new StringDecoder ())
147
+ consumeFirstMessageFrom(topic)(config, new StringDeserializer ())
148
148
149
149
150
150
/**
151
151
* Consumes the first message available in a given topic, deserializing it as a String.
152
152
*
153
- * @param topic the topic to consume a message from
154
- * @param config an implicit [[EmbeddedKafkaConfig ]]
155
- * @param decoder an implicit [[Decoder ]] for the type [[T ]]
153
+ * @param topic the topic to consume a message from
154
+ * @param config an implicit [[EmbeddedKafkaConfig ]]
155
+ * @param deserializer an implicit [[org.apache.kafka.common.serialization.Deserializer ]] for the type [[T ]]
156
156
* @return the first message consumed from the given topic, with a type [[T ]]
157
157
* @throws TimeoutException if unable to consume a message within 5 seconds
158
158
* @throws KafkaUnavailableException if unable to connect to Kafka
159
159
*/
160
160
@ throws(classOf [TimeoutException ])
161
161
@ throws(classOf [KafkaUnavailableException ])
162
- def consumeFirstMessageFrom [T ](topic : String )(implicit config : EmbeddedKafkaConfig , decoder : Decoder [T ]): T = {
162
+ def consumeFirstMessageFrom [T ](topic : String )(implicit config : EmbeddedKafkaConfig , deserializer : Deserializer [T ]): T = {
163
+
164
+ import scala .collection .JavaConversions ._
165
+
163
166
val props = new Properties ()
164
167
props.put(" group.id" , s " embedded-kafka-spec " )
165
- props.put(" zookeeper.connect" , s " localhost: ${config.zooKeeperPort}" )
166
- props.put(" auto.offset.reset" , " smallest" )
167
- props.put(" zookeeper.connection.timeout.ms" , " 6000" )
168
-
169
- val consumer =
170
- try Consumer .create(new ConsumerConfig (props))
171
- catch {
172
- case NonFatal (e) =>
173
- throw new KafkaUnavailableException (e)
174
- }
168
+ props.put(" bootstrap.servers" , s " localhost: ${config.kafkaPort}" )
169
+ props.put(" auto.offset.reset" , " earliest" )
175
170
176
- val messageStreams =
177
- consumer.createMessageStreamsByFilter(Whitelist (topic), keyDecoder = new StringDecoder , valueDecoder = decoder)
171
+ val consumer = new KafkaConsumer [String , T ](props, new StringDeserializer , deserializer)
178
172
179
- val messageFuture = Future {
180
- messageStreams.headOption
181
- .getOrElse(throw new KafkaSpecException (" Unable to find a message stream" )).iterator().next().message()
173
+ val message = Try {
174
+ consumer.subscribe(List (topic))
175
+ consumer.partitionsFor(topic) // as poll doesn't honour the timeout, forcing the consumer to fail here.
176
+ val records = consumer.poll(5000 )
177
+ if (records.isEmpty) {
178
+ throw new TimeoutException (" Unable to retrieve a message from Kafka in 5000ms" )
179
+ }
180
+ records.iterator().next().value()
182
181
}
183
182
184
- try {
185
- Await .result(messageFuture, 5 seconds)
186
- } finally {
187
- consumer.shutdown()
188
- }
183
+ consumer.close()
184
+ message.recover {
185
+ case ex : KafkaException => throw new KafkaUnavailableException (ex)
186
+ }.get
189
187
}
190
188
191
189
object aKafkaProducer {
0 commit comments