[{"data":1,"prerenderedAt":1336},["ShallowReactive",2],{"Categories":3,"NavIndexCategoriesCountFooter":203,"content-\u002F2019\u002F05\u002F15\u002Fkafka-java-to-scala-akka-streams-kafka\u002F":204},[4,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,70,71,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202],{"category":5},"System Administration",{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":27},"Software Development",{"category":5},{"category":5},{"category":5},{"category":5},{"category":27},{"category":27},{"category":5},{"category":5},{"category":5},{"category":27},{"category":5},{"category":5},{"category":5},{"category":27},{"category":27},{"category":27},{"category":27},{"category":5},{"category":5},{"category":5},{"category":27},{"category":27},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":27},{"category":5},{"category":5},{"category":27},{"category":27},{"category":27},{"category":27},{"category":5},{"category":27},{"category":27},{"category":67},"Drones & RC",{"category":69},"DIY Projects",{"category":67},{"category":72},"Photography",{"category":69},{"category":69},{"category":69},{"category":67},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":67},{"category":69},{"category":69},{"category":67},{"category":67},{"category":72},{"category":72},{"category":72},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":5},{"category":5},{"category":72},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":5},{"category":67},{"category":67},{"category":72},{"category":72},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":72},{"category":67},{"category":138},"3D Printing - Laser Cutting - CNC",{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":5},{"category":138},{"category":27},{"category":27},{"category":138},{"category":138},{"category":72},{"category":158},"Photography,3D Printing - Laser Cutting - CNC",{"category":27},{"category":27},{"category":69},{"category":27},{"category":27},{"category":27},{"category":27},{"category":5},{"category":67},{"category":5},{"category":5},{"category":27},{"category":27},{"category":27},{"category":27},{"category":27},{"category":69},{"category":27},{"category":27},{"category":27},{"category":27},{"category":181},"Home Assistant",{"category":181},{"category":72},{"category":27},{"category":27},{"category":72},{"category":138},{"category":5},{"category":72},{"category":72},{"category":138},{"category":27},{"category":181},{"category":181},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},191,{"id":205,"title":206,"body":207,"category":27,"date":1320,"description":213,"embedImage":1321,"extension":1322,"image":1321,"intro":1323,"meta":1324,"navigation":459,"path":1326,"seo":1327,"series":1328,"sitemap":1329,"stem":1330,"tags":1331,"__hash__":1335},"content\u002F2019\u002F05\u002F15\u002Fkafka-java-to-scala-akka-streams-kafka.md","Kafka - java to scala - akka streams kafka",{"type":208,"value":209,"toc":1307},"minimark",[210,214,223,226,234,242,277,280,283,288,293,303,307,313,316,319,322,335,338,482,485,505,747,750,753,756,912,915,926,1082,1086,1089,1104,1107,1185,1188,1270,1274,1277,1280,1283,1287,1303],[211,212,213],"p",{},"This series goes through conversion of some basic java kafka clients to scala - step by step. It is important to understand that it is written from my viewpoint - someone who has played with scala, likes it, but has never really had time to get into it.",[211,215,216,217,222],{},"In the ",[218,219,221],"a",{"href":220},"\u002F2019\u002F05\u002F08\u002Fkafka-java-to-scala-akka-streams-basics\u002F","previous post"," we took a look at akka streams in general.",[211,224,225],{},"Let's apply that to our producer and consumer.",[211,227,228,229,233],{},"We'll start with the same project setup as we used in ",[218,230,232],{"href":231},"\u002F2019\u002F05\u002F03\u002Fkafka-java-to-scala-scala-v2\u002F","the configuration project",".",[211,235,236,237,241],{},"There are two changes to ",[238,239,240],"code",{},"build.sbt",":",[243,244,245,261],"ul",{},[246,247,248,249,252,253,256,257,260],"li",{},"Set the ",[238,250,251],{},"name"," to ",[238,254,255],{},"AkkaProducer","\u002F",[238,258,259],{},"AkkaConsumer"," as appropriate",[246,262,263,264,273,274],{},"Add the ",[218,265,272],{"href":266,"rel":267,"target":271},"https:\u002F\u002Fdoc.akka.io\u002Fdocs\u002Falpakka-kafka\u002Fcurrent\u002Fhome.html",[268,269,270],"nofollow","noopener","noreferer","_blank","Alpakka Kafka"," dependency ",[238,275,276],{},"\"com.typesafe.akka\" %% \"akka-stream-kafka\" % \"2.0.0\"",[211,278,279],{},"The project directory (build.properties) are the same as before.",[211,281,282],{},"The src\u002Fmain\u002Fresources\u002Fapplication.conf files are very similar. We change the client\u002Fgroup IDs, the topic and we remove the serializer\u002Fdeserializer. The reason for this is that changing the typing of the messages would also require a lot of changes in code to match so doesn't really need to be a configurable.",[284,285,287],"h2",{"id":286},"config","Config",[289,290,292],"h3",{"id":291},"producer","Producer",[294,295,300],"pre",{"className":296,"code":298,"language":299},[297],"language-text","bootstrap-servers = \"localhost:29092\"\ntopic = \"akka-streams-topic\"\n","text",[238,301,298],{"__ignoreMap":302},"",[289,304,306],{"id":305},"consumer","Consumer",[294,308,311],{"className":309,"code":310,"language":299},[297],"client-id = \"akka-streams-consumer\"\ngroup-id = \"akka-streams-consumer\"\nbootstrap-servers = \"localhost:29092\"\ntopic = \"akka-streams-topic\"\nenable-auto-commit = \"true\"\nauto-commit-interval-ms = \"1000\"\nauto-offset-reset = \"earliest\"\n",[238,312,310],{"__ignoreMap":302},[284,314,315],{"id":238},"Code",[211,317,318],{},"OK - so how does the code look now?",[289,320,292],{"id":321},"producer-1",[211,323,324,325,329,330,334],{},"We still have a config case class and we still load the config with pureconfig (note - the kafka libraries for akka-streams can read application.conf themselves if you format it for them - see ",[218,326,291],{"href":327,"rel":328,"target":271},"https:\u002F\u002Fdoc.akka.io\u002Fdocs\u002Falpakka-kafka\u002Fcurrent\u002Fproducer.html#settings",[268,269,270]," and ",[218,331,305],{"href":332,"rel":333,"target":271},"https:\u002F\u002Fdoc.akka.io\u002Fdocs\u002Falpakka-kafka\u002Fcurrent\u002Fconsumer.html#settings",[268,269,270]," documentation).",[211,336,337],{},"However - once we have a configuration - we want to create the producer settings. For the producer that's simple - it takes a system and serializers and then we set the bootstrap server. We have no other options we want to set here - but we could add them if we did have (we'll see this in the consumer shortly).",[294,339,343],{"className":340,"code":341,"language":342,"meta":302,"style":302},"language-scala shiki shiki-themes github-dark","  private def buildProducerSettings(sys: ActorSystem, config: Config) = {\n    val keySerializer = Serdes.String().serializer()\n    val valueSerializer = Serdes.Integer().serializer().asInstanceOf[Serializer[Int]]\n\n    ProducerSettings(sys, keySerializer, valueSerializer)\n      .withBootstrapServers(config.bootstrapServers)\n  }\n","scala",[238,344,345,393,416,454,461,470,476],{"__ignoreMap":302},[346,347,350,354,357,361,365,369,372,375,378,380,382,384,387,390],"span",{"class":348,"line":349},"line",1,[346,351,353],{"class":352},"snl16","  private",[346,355,356],{"class":352}," def",[346,358,360],{"class":359},"svObZ"," buildProducerSettings",[346,362,364],{"class":363},"s95oV","(",[346,366,368],{"class":367},"s9osk","sys",[346,370,371],{"class":363},": ",[346,373,374],{"class":359},"ActorSystem",[346,376,377],{"class":363},", ",[346,379,286],{"class":367},[346,381,371],{"class":363},[346,383,287],{"class":359},[346,385,386],{"class":363},") ",[346,388,389],{"class":352},"=",[346,391,392],{"class":363}," {\n",[346,394,396,399,402,405,408,410,413],{"class":348,"line":395},2,[346,397,398],{"class":352},"    val",[346,400,401],{"class":367}," keySerializer",[346,403,404],{"class":352}," =",[346,406,407],{"class":359}," Serdes",[346,409,233],{"class":363},[346,411,412],{"class":359},"String",[346,414,415],{"class":363},"().serializer()\n",[346,417,419,421,424,426,428,430,433,436,440,443,446,448,451],{"class":348,"line":418},3,[346,420,398],{"class":352},[346,422,423],{"class":367}," valueSerializer",[346,425,404],{"class":352},[346,427,407],{"class":359},[346,429,233],{"class":363},[346,431,432],{"class":359},"Integer",[346,434,435],{"class":363},"().serializer().",[346,437,439],{"class":438},"sDLfK","asInstanceOf",[346,441,442],{"class":363},"[",[346,444,445],{"class":359},"Serializer",[346,447,442],{"class":363},[346,449,450],{"class":359},"Int",[346,452,453],{"class":363},"]]\n",[346,455,457],{"class":348,"line":456},4,[346,458,460],{"emptyLinePlaceholder":459},true,"\n",[346,462,464,467],{"class":348,"line":463},5,[346,465,466],{"class":359},"    ProducerSettings",[346,468,469],{"class":363},"(sys, keySerializer, valueSerializer)\n",[346,471,473],{"class":348,"line":472},6,[346,474,475],{"class":363},"      .withBootstrapServers(config.bootstrapServers)\n",[346,477,479],{"class":348,"line":478},7,[346,480,481],{"class":363},"  }\n",[211,483,484],{},"Finally we set up our akka stream:",[243,486,487,490,493,499,502],{},[246,488,489],{},"Source: an akka streams source that is the sequence of integers from 0 to 10000",[246,491,492],{},"Flow: doubles the value - just for fun",[246,494,495,496],{},"Flow: creates a producer message with a record of ",[346,497,498],{},"String, Int",[246,500,501],{},"Flow: send the message to the producer which sends it to kafka",[246,503,504],{},"Sink: consume each response from kafka and print what was done",[294,506,508],{"className":340,"code":507,"language":342,"meta":302,"style":302},"      println(\"*** Starting Producer ***\")\n\n      implicit val sys = ActorSystem()\n      implicit val mat = ActorMaterializer()\n\n      val producerSettings: ProducerSettings[String, Int] = buildProducerSettings(sys, config)\n\n      Source\n        .fromIterator(() => (0 to 10000).toIterator)\n        .map(i => i * 2)\n        .map { i =>\n          ProducerMessage.Message(new ProducerRecord[String, Int](config.topic, i), i)\n        }\n        .via(Producer.flexiFlow(producerSettings))\n        .runWith {\n          Sink.foreach(res => println(s\"Wrote ${res.passThrough} to ${config.topic}\"))\n        }\n",[238,509,510,522,526,545,561,565,594,598,604,627,646,655,685,691,702,708,742],{"__ignoreMap":302},[346,511,512,515,519],{"class":348,"line":349},[346,513,514],{"class":363},"      println(",[346,516,518],{"class":517},"sU2Wk","\"*** Starting Producer ***\"",[346,520,521],{"class":363},")\n",[346,523,524],{"class":348,"line":395},[346,525,460],{"emptyLinePlaceholder":459},[346,527,528,531,534,537,539,542],{"class":348,"line":418},[346,529,530],{"class":352},"      implicit",[346,532,533],{"class":352}," val",[346,535,536],{"class":367}," sys",[346,538,404],{"class":352},[346,540,541],{"class":359}," ActorSystem",[346,543,544],{"class":363},"()\n",[346,546,547,549,551,554,556,559],{"class":348,"line":456},[346,548,530],{"class":352},[346,550,533],{"class":352},[346,552,553],{"class":367}," mat",[346,555,404],{"class":352},[346,557,558],{"class":359}," ActorMaterializer",[346,560,544],{"class":363},[346,562,563],{"class":348,"line":463},[346,564,460],{"emptyLinePlaceholder":459},[346,566,567,570,573,575,578,580,582,584,586,589,591],{"class":348,"line":472},[346,568,569],{"class":352},"      val",[346,571,572],{"class":367}," producerSettings",[346,574,241],{"class":352},[346,576,577],{"class":359}," ProducerSettings",[346,579,442],{"class":363},[346,581,412],{"class":359},[346,583,377],{"class":363},[346,585,450],{"class":359},[346,587,588],{"class":363},"] ",[346,590,389],{"class":352},[346,592,593],{"class":363}," buildProducerSettings(sys, config)\n",[346,595,596],{"class":348,"line":478},[346,597,460],{"emptyLinePlaceholder":459},[346,599,601],{"class":348,"line":600},8,[346,602,603],{"class":359},"      Source\n",[346,605,607,610,613,616,619,621,624],{"class":348,"line":606},9,[346,608,609],{"class":363},"        .fromIterator(() ",[346,611,612],{"class":352},"=>",[346,614,615],{"class":363}," (",[346,617,618],{"class":438},"0",[346,620,252],{"class":363},[346,622,623],{"class":438},"10000",[346,625,626],{"class":363},").toIterator)\n",[346,628,630,633,635,638,641,644],{"class":348,"line":629},10,[346,631,632],{"class":363},"        .map(i ",[346,634,612],{"class":352},[346,636,637],{"class":363}," i ",[346,639,640],{"class":352},"*",[346,642,643],{"class":438}," 2",[346,645,521],{"class":363},[346,647,649,652],{"class":348,"line":648},11,[346,650,651],{"class":363},"        .map { i ",[346,653,654],{"class":352},"=>\n",[346,656,658,661,663,666,668,671,674,676,678,680,682],{"class":348,"line":657},12,[346,659,660],{"class":359},"          ProducerMessage",[346,662,233],{"class":363},[346,664,665],{"class":359},"Message",[346,667,364],{"class":363},[346,669,670],{"class":352},"new",[346,672,673],{"class":359}," ProducerRecord",[346,675,442],{"class":363},[346,677,412],{"class":359},[346,679,377],{"class":363},[346,681,450],{"class":359},[346,683,684],{"class":363},"](config.topic, i), i)\n",[346,686,688],{"class":348,"line":687},13,[346,689,690],{"class":363},"        }\n",[346,692,694,697,699],{"class":348,"line":693},14,[346,695,696],{"class":363},"        .via(",[346,698,292],{"class":359},[346,700,701],{"class":363},".flexiFlow(producerSettings))\n",[346,703,705],{"class":348,"line":704},15,[346,706,707],{"class":363},"        .runWith {\n",[346,709,711,714,717,719,722,725,728,731,733,736,739],{"class":348,"line":710},16,[346,712,713],{"class":359},"          Sink",[346,715,716],{"class":363},".foreach(res ",[346,718,612],{"class":352},[346,720,721],{"class":363}," println(",[346,723,724],{"class":352},"s",[346,726,727],{"class":517},"\"Wrote ",[346,729,730],{"class":363},"${res.passThrough}",[346,732,252],{"class":517},[346,734,735],{"class":363},"${config.topic}",[346,737,738],{"class":517},"\"",[346,740,741],{"class":363},"))\n",[346,743,745],{"class":348,"line":744},17,[346,746,690],{"class":363},[289,748,306],{"id":749},"consumer-1",[211,751,752],{},"Again - the consumer is very similar up to the point we have successfully loaded a config.",[211,754,755],{},"Building the consumer settings is the same process with more fields:",[294,757,759],{"className":340,"code":758,"language":342,"meta":302,"style":302},"  private def buildConsumerSettings(sys: ActorSystem, config: Config) = {\n    val keyDeserializer = Serdes.String().deserializer()\n    val valueDeserializer = Serdes.Integer().deserializer().asInstanceOf[Deserializer[Int]]\n\n    ConsumerSettings(sys, keyDeserializer, valueDeserializer)\n      .withBootstrapServers(config.bootstrapServers)\n      .withProperties(\n        AUTO_OFFSET_RESET_CONFIG -> config.autoOffsetReset,\n        ENABLE_AUTO_COMMIT_CONFIG -> config.enableAutoCommit,\n        AUTO_COMMIT_INTERVAL_MS_CONFIG -> config.autoCommitIntervalMs\n      )\n      .withGroupId(config.groupId)\n      .withClientId(config.clientId)\n  }\n",[238,760,761,792,810,841,845,853,857,862,873,883,893,898,903,908],{"__ignoreMap":302},[346,762,763,765,767,770,772,774,776,778,780,782,784,786,788,790],{"class":348,"line":349},[346,764,353],{"class":352},[346,766,356],{"class":352},[346,768,769],{"class":359}," buildConsumerSettings",[346,771,364],{"class":363},[346,773,368],{"class":367},[346,775,371],{"class":363},[346,777,374],{"class":359},[346,779,377],{"class":363},[346,781,286],{"class":367},[346,783,371],{"class":363},[346,785,287],{"class":359},[346,787,386],{"class":363},[346,789,389],{"class":352},[346,791,392],{"class":363},[346,793,794,796,799,801,803,805,807],{"class":348,"line":395},[346,795,398],{"class":352},[346,797,798],{"class":367}," keyDeserializer",[346,800,404],{"class":352},[346,802,407],{"class":359},[346,804,233],{"class":363},[346,806,412],{"class":359},[346,808,809],{"class":363},"().deserializer()\n",[346,811,812,814,817,819,821,823,825,828,830,832,835,837,839],{"class":348,"line":418},[346,813,398],{"class":352},[346,815,816],{"class":367}," valueDeserializer",[346,818,404],{"class":352},[346,820,407],{"class":359},[346,822,233],{"class":363},[346,824,432],{"class":359},[346,826,827],{"class":363},"().deserializer().",[346,829,439],{"class":438},[346,831,442],{"class":363},[346,833,834],{"class":359},"Deserializer",[346,836,442],{"class":363},[346,838,450],{"class":359},[346,840,453],{"class":363},[346,842,843],{"class":348,"line":456},[346,844,460],{"emptyLinePlaceholder":459},[346,846,847,850],{"class":348,"line":463},[346,848,849],{"class":359},"    ConsumerSettings",[346,851,852],{"class":363},"(sys, keyDeserializer, valueDeserializer)\n",[346,854,855],{"class":348,"line":472},[346,856,475],{"class":363},[346,858,859],{"class":348,"line":478},[346,860,861],{"class":363},"      .withProperties(\n",[346,863,864,867,870],{"class":348,"line":600},[346,865,866],{"class":359},"        AUTO_OFFSET_RESET_CONFIG",[346,868,869],{"class":352}," ->",[346,871,872],{"class":363}," config.autoOffsetReset,\n",[346,874,875,878,880],{"class":348,"line":606},[346,876,877],{"class":359},"        ENABLE_AUTO_COMMIT_CONFIG",[346,879,869],{"class":352},[346,881,882],{"class":363}," config.enableAutoCommit,\n",[346,884,885,888,890],{"class":348,"line":629},[346,886,887],{"class":359},"        AUTO_COMMIT_INTERVAL_MS_CONFIG",[346,889,869],{"class":352},[346,891,892],{"class":363}," config.autoCommitIntervalMs\n",[346,894,895],{"class":348,"line":648},[346,896,897],{"class":363},"      )\n",[346,899,900],{"class":348,"line":657},[346,901,902],{"class":363},"      .withGroupId(config.groupId)\n",[346,904,905],{"class":348,"line":687},[346,906,907],{"class":363},"      .withClientId(config.clientId)\n",[346,909,910],{"class":348,"line":693},[346,911,481],{"class":363},[211,913,914],{},"Now we can define our subscription then set up the following akka stream:",[243,916,917,920,923],{},[246,918,919],{},"Source: a kafka implementation of an akka stream source that will read the kafka topic messages based on the configuration and subscription definition",[246,921,922],{},"Flow: extracts only the value",[246,924,925],{},"Sink: print what was seen",[294,927,929],{"className":340,"code":928,"language":342,"meta":302,"style":302},"      println(\"*** Starting Consumer ***\")\n\n      implicit val sys = ActorSystem()\n      implicit val mat = ActorMaterializer()\n\n      val consumerSettings: ConsumerSettings[String, Int] = buildConsumerSettings(sys, config)\n\n      val subscription = Subscriptions.topics(Set(config.topic))\n\n      Consumer\n        .plainSource[String, Int](consumerSettings, subscription)\n        .map(msg => msg.value())\n        .runForeach(w => println(s\"Consumed message with value $w\"))\n",[238,930,931,940,944,958,972,976,1003,1007,1028,1032,1037,1051,1061],{"__ignoreMap":302},[346,932,933,935,938],{"class":348,"line":349},[346,934,514],{"class":363},[346,936,937],{"class":517},"\"*** Starting Consumer ***\"",[346,939,521],{"class":363},[346,941,942],{"class":348,"line":395},[346,943,460],{"emptyLinePlaceholder":459},[346,945,946,948,950,952,954,956],{"class":348,"line":418},[346,947,530],{"class":352},[346,949,533],{"class":352},[346,951,536],{"class":367},[346,953,404],{"class":352},[346,955,541],{"class":359},[346,957,544],{"class":363},[346,959,960,962,964,966,968,970],{"class":348,"line":456},[346,961,530],{"class":352},[346,963,533],{"class":352},[346,965,553],{"class":367},[346,967,404],{"class":352},[346,969,558],{"class":359},[346,971,544],{"class":363},[346,973,974],{"class":348,"line":463},[346,975,460],{"emptyLinePlaceholder":459},[346,977,978,980,983,985,988,990,992,994,996,998,1000],{"class":348,"line":472},[346,979,569],{"class":352},[346,981,982],{"class":367}," consumerSettings",[346,984,241],{"class":352},[346,986,987],{"class":359}," ConsumerSettings",[346,989,442],{"class":363},[346,991,412],{"class":359},[346,993,377],{"class":363},[346,995,450],{"class":359},[346,997,588],{"class":363},[346,999,389],{"class":352},[346,1001,1002],{"class":363}," buildConsumerSettings(sys, config)\n",[346,1004,1005],{"class":348,"line":478},[346,1006,460],{"emptyLinePlaceholder":459},[346,1008,1009,1011,1014,1016,1019,1022,1025],{"class":348,"line":600},[346,1010,569],{"class":352},[346,1012,1013],{"class":367}," subscription",[346,1015,404],{"class":352},[346,1017,1018],{"class":359}," Subscriptions",[346,1020,1021],{"class":363},".topics(",[346,1023,1024],{"class":359},"Set",[346,1026,1027],{"class":363},"(config.topic))\n",[346,1029,1030],{"class":348,"line":606},[346,1031,460],{"emptyLinePlaceholder":459},[346,1033,1034],{"class":348,"line":629},[346,1035,1036],{"class":359},"      Consumer\n",[346,1038,1039,1042,1044,1046,1048],{"class":348,"line":648},[346,1040,1041],{"class":363},"        .plainSource[",[346,1043,412],{"class":359},[346,1045,377],{"class":363},[346,1047,450],{"class":359},[346,1049,1050],{"class":363},"](consumerSettings, subscription)\n",[346,1052,1053,1056,1058],{"class":348,"line":657},[346,1054,1055],{"class":363},"        .map(msg ",[346,1057,612],{"class":352},[346,1059,1060],{"class":363}," msg.value())\n",[346,1062,1063,1066,1068,1070,1072,1075,1078,1080],{"class":348,"line":687},[346,1064,1065],{"class":363},"        .runForeach(w ",[346,1067,612],{"class":352},[346,1069,721],{"class":363},[346,1071,724],{"class":352},[346,1073,1074],{"class":517},"\"Consumed message with value ",[346,1076,1077],{"class":363},"$w",[346,1079,738],{"class":517},[346,1081,741],{"class":363},[289,1083,1085],{"id":1084},"build-and-run","Build and Run",[211,1087,1088],{},"We can again use simple sbt commands to compile:",[294,1090,1094],{"className":1091,"code":1092,"language":1093,"meta":302,"style":302},"language-shell shiki shiki-themes github-dark","sbt compile\n","shell",[238,1095,1096],{"__ignoreMap":302},[346,1097,1098,1101],{"class":348,"line":349},[346,1099,1100],{"class":359},"sbt",[346,1102,1103],{"class":517}," compile\n",[211,1105,1106],{},"Run the producer:",[294,1108,1110],{"className":1091,"code":1109,"language":1093,"meta":302,"style":302},"$ sbt run\n*** Starting Producer ***\nWrote 0 to akka-streams-topic\nWrote 2 to akka-streams-topic\n...\nWrote 19998 to akka-streams-topic\nWrote 20000 to akka-streams-topic\n",[238,1111,1112,1123,1134,1148,1158,1163,1174],{"__ignoreMap":302},[346,1113,1114,1117,1120],{"class":348,"line":349},[346,1115,1116],{"class":359},"$",[346,1118,1119],{"class":517}," sbt",[346,1121,1122],{"class":517}," run\n",[346,1124,1125,1128,1131],{"class":348,"line":395},[346,1126,1127],{"class":352},"***",[346,1129,1130],{"class":363}," Starting Producer ",[346,1132,1133],{"class":352},"***\n",[346,1135,1136,1139,1142,1145],{"class":348,"line":418},[346,1137,1138],{"class":359},"Wrote",[346,1140,1141],{"class":438}," 0",[346,1143,1144],{"class":517}," to",[346,1146,1147],{"class":517}," akka-streams-topic\n",[346,1149,1150,1152,1154,1156],{"class":348,"line":456},[346,1151,1138],{"class":359},[346,1153,643],{"class":438},[346,1155,1144],{"class":517},[346,1157,1147],{"class":517},[346,1159,1160],{"class":348,"line":463},[346,1161,1162],{"class":438},"...\n",[346,1164,1165,1167,1170,1172],{"class":348,"line":472},[346,1166,1138],{"class":359},[346,1168,1169],{"class":438}," 19998",[346,1171,1144],{"class":517},[346,1173,1147],{"class":517},[346,1175,1176,1178,1181,1183],{"class":348,"line":478},[346,1177,1138],{"class":359},[346,1179,1180],{"class":438}," 20000",[346,1182,1144],{"class":517},[346,1184,1147],{"class":517},[211,1186,1187],{},"And then the consumer:",[294,1189,1191],{"className":1091,"code":1190,"language":1093,"meta":302,"style":302},"$ sbt run\n*** Starting Basic Consumer ***\nConsumed message with value 0\nConsumed message with value 2\n...\nConsumed message with value 19998\nConsumed message with value 20000\n",[238,1192,1193,1201,1210,1227,1240,1244,1257],{"__ignoreMap":302},[346,1194,1195,1197,1199],{"class":348,"line":349},[346,1196,1116],{"class":359},[346,1198,1119],{"class":517},[346,1200,1122],{"class":517},[346,1202,1203,1205,1208],{"class":348,"line":395},[346,1204,1127],{"class":352},[346,1206,1207],{"class":363}," Starting Basic Consumer ",[346,1209,1133],{"class":352},[346,1211,1212,1215,1218,1221,1224],{"class":348,"line":418},[346,1213,1214],{"class":359},"Consumed",[346,1216,1217],{"class":517}," message",[346,1219,1220],{"class":517}," with",[346,1222,1223],{"class":517}," value",[346,1225,1226],{"class":438}," 0\n",[346,1228,1229,1231,1233,1235,1237],{"class":348,"line":456},[346,1230,1214],{"class":359},[346,1232,1217],{"class":517},[346,1234,1220],{"class":517},[346,1236,1223],{"class":517},[346,1238,1239],{"class":438}," 2\n",[346,1241,1242],{"class":348,"line":463},[346,1243,1162],{"class":438},[346,1245,1246,1248,1250,1252,1254],{"class":348,"line":472},[346,1247,1214],{"class":359},[346,1249,1217],{"class":517},[346,1251,1220],{"class":517},[346,1253,1223],{"class":517},[346,1255,1256],{"class":438}," 19998\n",[346,1258,1259,1261,1263,1265,1267],{"class":348,"line":478},[346,1260,1214],{"class":359},[346,1262,1217],{"class":517},[346,1264,1220],{"class":517},[346,1266,1223],{"class":517},[346,1268,1269],{"class":438}," 20000\n",[284,1271,1273],{"id":1272},"summary","Summary",[211,1275,1276],{},"Moving to akka streams allows us to create our processing almost as a line by line recipe - and also handles the asynchronicity of the calls to the producer\u002Fconsumer in an akka streams context.",[211,1278,1279],{},"In this case - each recipe is simple - but in more complex situations you can use composition to be able to keep the code simple to understand.",[211,1281,1282],{},"The API for the consumer\u002Fproducer code now also looks very similar to the kafka streams API. Something for a future article perhaps?",[284,1284,1286],{"id":1285},"links","Links",[243,1288,1289,1296],{},[246,1290,1291],{},[218,1292,1295],{"href":1293,"rel":1294,"target":271},"https:\u002F\u002Fgithub.com\u002Fchrissearle\u002Fkafka-java-to-scala\u002Ftree\u002Fmaster\u002Fakka-streams-kafka\u002Fproducer",[268,269,270],"Producer project",[246,1297,1298],{},[218,1299,1302],{"href":1300,"rel":1301,"target":271},"https:\u002F\u002Fgithub.com\u002Fchrissearle\u002Fkafka-java-to-scala\u002Ftree\u002Fmaster\u002Fakka-streams-kafka\u002Fconsumer",[268,269,270],"Consumer project",[1304,1305,1306],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}",{"title":302,"searchDepth":395,"depth":395,"links":1308},[1309,1313,1318,1319],{"id":286,"depth":395,"text":287,"children":1310},[1311,1312],{"id":291,"depth":418,"text":292},{"id":305,"depth":418,"text":306},{"id":238,"depth":395,"text":315,"children":1314},[1315,1316,1317],{"id":321,"depth":418,"text":292},{"id":749,"depth":418,"text":306},{"id":1084,"depth":418,"text":1085},{"id":1272,"depth":395,"text":1273},{"id":1285,"depth":395,"text":1286},"2019-05-15 12:10 +0200",null,"md","In the previous post we took a look at akka streams in general. Let's apply that to our producer and consumer.",{"updated":1325},"2020-01-23 00:00","\u002F2019\u002F05\u002F15\u002Fkafka-java-to-scala-akka-streams-kafka",{"title":206,"description":213},"Kafka - java to scala",{"loc":1326},"2019\u002F05\u002F15\u002Fkafka-java-to-scala-akka-streams-kafka",[342,1332,1333,1334,291,305],"akka","akka streams","kafka","c7EJGcbW07CzXtwQKAD7usl7BKoa138jU6b2J1GSJ3c",1775293008924]