├── .bookmark ├── project ├── build.properties └── plugins.sbt ├── exercise_001_Implement_actor ├── src │ ├── test │ │ ├── resources │ │ │ ├── application.conf │ │ │ ├── README.md │ │ │ └── logback-test.xml │ │ └── java │ │ │ └── com │ │ │ └── lightbend │ │ │ └── training │ │ │ └── coffeehouse │ │ │ ├── CoffeeHouseTest.java │ │ │ ├── CoffeeHouseAppTest.java │ │ │ ├── TerminalTest.java │ │ │ └── CoffeeTest.java │ └── main │ │ ├── java │ │ └── com │ │ │ └── lightbend │ │ │ └── training │ │ │ └── coffeehouse │ │ │ ├── CoffeeHouse.java │ │ │ └── Terminal.java │ │ └── resources │ │ └── logback.xml └── README.md ├── exercise_004_Use_sender ├── src │ ├── test │ │ ├── resources │ │ │ ├── application.conf │ │ │ ├── README.md │ │ │ └── logback-test.xml │ │ └── java │ │ │ └── com │ │ │ └── lightbend │ │ │ └── training │ │ │ └── coffeehouse │ │ │ ├── CoffeeHouseTest.java │ │ │ ├── CoffeeTest.java │ │ │ └── TerminalTest.java │ └── main │ │ ├── resources │ │ ├── application.conf │ │ └── logback.xml │ │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ ├── CoffeeHouse.java │ │ └── Terminal.java └── README.md ├── exercise_005_Child_actors ├── src │ ├── test │ │ ├── resources │ │ │ ├── application.conf │ │ │ ├── logback-test.xml │ │ │ └── README.md │ │ └── java │ │ │ └── com │ │ │ └── lightbend │ │ │ └── training │ │ │ └── coffeehouse │ │ │ ├── CoffeeHouseTest.java │ │ │ ├── CoffeeTest.java │ │ │ └── TerminalTest.java │ └── main │ │ ├── resources │ │ ├── application.conf │ │ └── logback.xml │ │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ ├── Guest.java │ │ └── Terminal.java └── README.md ├── exercise_006_Actor_state └── src │ ├── test │ ├── resources │ │ ├── application.conf │ │ └── logback-test.xml │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ ├── WaiterTest.java │ │ ├── GuestTest.java │ │ ├── CoffeeHouseTest.java │ │ ├── CoffeeTest.java │ │ └── TerminalTest.java │ └── main │ ├── resources │ ├── application.conf │ └── logback.xml │ └── java │ └── com │ └── lightbend │ └── training │ └── coffeehouse │ └── Terminal.java ├── exercise_002_Top_level_actor ├── src │ ├── test │ │ ├── resources │ │ │ ├── application.conf │ │ │ ├── README.md │ │ │ └── logback-test.xml │ │ └── java │ │ │ └── com │ │ │ └── lightbend │ │ │ └── training │ │ │ └── coffeehouse │ │ │ ├── CoffeeHouseTest.java │ │ │ ├── CoffeeHouseAppTest.java │ │ │ ├── CoffeeTest.java │ │ │ └── TerminalTest.java │ └── main │ │ ├── resources │ │ ├── application.conf │ │ └── logback.xml │ │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ ├── CoffeeHouse.java │ │ └── Terminal.java └── README.md ├── exercise_003_Message_actor ├── src │ ├── test │ │ ├── resources │ │ │ ├── application.conf │ │ │ ├── README.md │ │ │ └── logback-test.xml │ │ └── java │ │ │ └── com │ │ │ └── lightbend │ │ │ └── training │ │ │ └── coffeehouse │ │ │ ├── CoffeeHouseTest.java │ │ │ ├── CoffeeTest.java │ │ │ ├── TerminalTest.java │ │ │ └── CoffeeHouseAppTest.java │ └── main │ │ ├── resources │ │ ├── application.conf │ │ └── logback.xml │ │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ ├── CoffeeHouse.java │ │ └── Terminal.java └── README.md ├── exercise_007_Use_scheduler ├── src │ ├── test │ │ ├── resources │ │ │ ├── application.conf │ │ │ ├── logback-test.xml │ │ │ └── README.md │ │ └── java │ │ │ └── com │ │ │ └── lightbend │ │ │ └── training │ │ │ └── coffeehouse │ │ │ ├── WaiterTest.java │ │ │ ├── CoffeeHouseTest.java │ │ │ ├── CoffeeTest.java │ │ │ └── TerminalTest.java │ └── main │ │ ├── resources │ │ ├── application.conf │ │ └── logback.xml │ │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ └── Terminal.java └── README.md ├── exercise_008_Busy_actor └── src │ ├── test │ ├── resources │ │ ├── application.conf │ │ └── logback-test.xml │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ ├── WaiterTest.java │ │ ├── BaristaTest.java │ │ ├── CoffeeHouseTest.java │ │ ├── CoffeeTest.java │ │ └── TerminalTest.java │ └── main │ ├── resources │ ├── application.conf │ └── logback.xml │ └── java │ └── com │ └── lightbend │ └── training │ └── coffeehouse │ └── Terminal.java ├── exercise_009_Stop_actor └── src │ ├── test │ ├── resources │ │ ├── application.conf │ │ └── logback-test.xml │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ ├── WaiterTest.java │ │ ├── BaristaTest.java │ │ ├── CoffeeTest.java │ │ └── TerminalTest.java │ └── main │ ├── resources │ ├── application.conf │ └── logback.xml │ └── java │ └── com │ └── lightbend │ └── training │ └── coffeehouse │ └── Terminal.java ├── exercise_011_Faulty_guest ├── src │ ├── test │ │ ├── resources │ │ │ ├── application.conf │ │ │ ├── README.md │ │ │ └── logback-test.xml │ │ └── java │ │ │ └── com │ │ │ └── lightbend │ │ │ └── training │ │ │ └── coffeehouse │ │ │ ├── WaiterTest.java │ │ │ ├── BaristaTest.java │ │ │ ├── CoffeeTest.java │ │ │ └── TerminalTest.java │ └── main │ │ ├── resources │ │ ├── application.conf │ │ └── logback.xml │ │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ └── Terminal.java └── README.md ├── exercise_010_Lifecycle_monitoring ├── src │ ├── test │ │ ├── resources │ │ │ ├── application.conf │ │ │ ├── README.md │ │ │ └── logback-test.xml │ │ └── java │ │ │ └── com │ │ │ └── lightbend │ │ │ └── training │ │ │ └── coffeehouse │ │ │ ├── WaiterTest.java │ │ │ ├── BaristaTest.java │ │ │ ├── CoffeeTest.java │ │ │ └── TerminalTest.java │ └── main │ │ ├── resources │ │ ├── application.conf │ │ └── logback.xml │ │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ └── Terminal.java └── README.md ├── exercise_013_Faulty_waiter └── src │ ├── test │ ├── resources │ │ ├── application.conf │ │ └── logback-test.xml │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ ├── TerminalTest.java │ │ ├── CoffeeTest.java │ │ └── WaiterTest.java │ └── main │ ├── resources │ ├── application.conf │ └── logback.xml │ └── java │ └── com │ └── lightbend │ └── training │ └── coffeehouse │ └── Terminal.java ├── exercise_014_Self_healing ├── src │ ├── test │ │ ├── resources │ │ │ ├── application.conf │ │ │ ├── README.md │ │ │ └── logback-test.xml │ │ └── java │ │ │ └── com │ │ │ └── lightbend │ │ │ └── training │ │ │ └── coffeehouse │ │ │ ├── CoffeeTest.java │ │ │ └── TerminalTest.java │ └── main │ │ ├── resources │ │ ├── application.conf │ │ └── logback.xml │ │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ └── Terminal.java └── README.md ├── exercise_012_Custom_supervision ├── src │ ├── test │ │ ├── resources │ │ │ ├── application.conf │ │ │ ├── README.md │ │ │ └── logback-test.xml │ │ └── java │ │ │ └── com │ │ │ └── lightbend │ │ │ └── training │ │ │ └── coffeehouse │ │ │ ├── WaiterTest.java │ │ │ ├── BaristaTest.java │ │ │ ├── CoffeeTest.java │ │ │ └── TerminalTest.java │ └── main │ │ ├── resources │ │ ├── application.conf │ │ └── logback.xml │ │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ └── Terminal.java └── README.md ├── exercise_015_Detect_bottleneck ├── src │ ├── test │ │ ├── resources │ │ │ ├── application.conf │ │ │ ├── README.md │ │ │ └── logback-test.xml │ │ └── java │ │ │ └── com │ │ │ └── lightbend │ │ │ └── training │ │ │ └── coffeehouse │ │ │ ├── TerminalTest.java │ │ │ └── CoffeeTest.java │ └── main │ │ ├── resources │ │ ├── application.conf │ │ └── logback.xml │ │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ └── Terminal.java └── README.md ├── .gitignore ├── exercise_016_Use_router ├── README.md └── src │ ├── test │ ├── resources │ │ ├── README.md │ │ ├── logback-test.xml │ │ └── application.conf │ └── java │ │ └── com │ │ └── lightbend │ │ └── training │ │ └── coffeehouse │ │ ├── CoffeeTest.java │ │ └── TerminalTest.java │ └── main │ ├── resources │ ├── application.conf │ └── logback.xml │ └── java │ └── com │ └── lightbend │ └── training │ └── coffeehouse │ └── Terminal.java ├── shell-prompt.sbt ├── exercise_000_Initial_state └── src │ ├── test │ ├── java │ │ └── com │ │ │ └── lightbend │ │ │ └── training │ │ │ └── coffeehouse │ │ │ ├── CoffeeHouseAppTest.java │ │ │ ├── CoffeeTest.java │ │ │ └── TerminalTest.java │ └── resources │ │ └── logback-test.xml │ └── main │ ├── resources │ └── logback.xml │ └── java │ └── com │ └── lightbend │ └── training │ └── coffeehouse │ └── Terminal.java └── man.sbt /.bookmark: -------------------------------------------------------------------------------- 1 | exercise_016_Use_router -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.2.3 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4") 2 | -------------------------------------------------------------------------------- /exercise_001_Implement_actor/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | -------------------------------------------------------------------------------- /exercise_004_Use_sender/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | akka.logging-filter = "akka.event.DefaultLoggingFilter" 3 | -------------------------------------------------------------------------------- /exercise_005_Child_actors/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | akka.logging-filter = "akka.event.DefaultLoggingFilter" 3 | -------------------------------------------------------------------------------- /exercise_006_Actor_state/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | akka.logging-filter = "akka.event.DefaultLoggingFilter" 3 | -------------------------------------------------------------------------------- /exercise_002_Top_level_actor/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | akka.logging-filter = "akka.event.DefaultLoggingFilter" 3 | -------------------------------------------------------------------------------- /exercise_003_Message_actor/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | akka.logging-filter = "akka.event.DefaultLoggingFilter" 3 | -------------------------------------------------------------------------------- /exercise_007_Use_scheduler/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | akka.logging-filter = "akka.event.DefaultLoggingFilter" 3 | -------------------------------------------------------------------------------- /exercise_008_Busy_actor/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | akka.logging-filter = "akka.event.DefaultLoggingFilter" 3 | 4 | coffee-house { 5 | barista { 6 | prepare-coffee-duration = 100 milliseconds 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /exercise_009_Stop_actor/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | akka.logging-filter = "akka.event.DefaultLoggingFilter" 3 | 4 | coffee-house { 5 | barista { 6 | prepare-coffee-duration = 100 milliseconds 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /exercise_011_Faulty_guest/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | akka.logging-filter = "akka.event.DefaultLoggingFilter" 3 | 4 | coffee-house { 5 | barista { 6 | prepare-coffee-duration = 100 milliseconds 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /exercise_010_Lifecycle_monitoring/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | akka.logging-filter = "akka.event.DefaultLoggingFilter" 3 | 4 | coffee-house { 5 | barista { 6 | prepare-coffee-duration = 100 milliseconds 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /exercise_004_Use_sender/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.event.slf4j.Slf4jLogger] 3 | logger-startup-timeout = 10s 4 | loglevel = DEBUG 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | 7 | actor { 8 | debug { 9 | unhandled = on 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /exercise_003_Message_actor/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.event.slf4j.Slf4jLogger] 3 | logger-startup-timeout = 10s 4 | loglevel = DEBUG 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | 7 | actor { 8 | debug { 9 | unhandled = on 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /exercise_006_Actor_state/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.event.slf4j.Slf4jLogger] 3 | logger-startup-timeout = 10s 4 | loglevel = DEBUG 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | 7 | actor { 8 | debug { 9 | lifecycle = on 10 | unhandled = on 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /exercise_013_Faulty_waiter/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | akka.logging-filter = "akka.event.DefaultLoggingFilter" 3 | 4 | coffee-house { 5 | barista { 6 | prepare-coffee-duration = 100 milliseconds 7 | } 8 | guest { 9 | finish-coffee-duration = 100 milliseconds 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /exercise_014_Self_healing/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | akka.logging-filter = "akka.event.DefaultLoggingFilter" 3 | 4 | coffee-house { 5 | barista { 6 | prepare-coffee-duration = 100 milliseconds 7 | } 8 | guest { 9 | finish-coffee-duration = 100 milliseconds 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /exercise_012_Custom_supervision/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | akka.logging-filter = "akka.event.DefaultLoggingFilter" 3 | 4 | coffee-house { 5 | barista { 6 | prepare-coffee-duration = 100 milliseconds 7 | } 8 | guest { 9 | finish-coffee-duration = 100 milliseconds 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /exercise_015_Detect_bottleneck/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.loggers = [akka.testkit.TestEventListener] 2 | akka.logging-filter = "akka.event.DefaultLoggingFilter" 3 | 4 | coffee-house { 5 | barista { 6 | prepare-coffee-duration = 100 milliseconds 7 | } 8 | guest { 9 | finish-coffee-duration = 100 milliseconds 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.ear 17 | *.zip 18 | *.tar.gz 19 | *.rar 20 | 21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 22 | hs_err_pid* 23 | 24 | # sbt generated directories 25 | project/project/ 26 | project/target/ 27 | target/ 28 | -------------------------------------------------------------------------------- /exercise_008_Busy_actor/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.event.slf4j.Slf4jLogger] 3 | logger-startup-timeout = 10s 4 | loglevel = DEBUG 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | 7 | actor { 8 | debug { 9 | lifecycle = on 10 | unhandled = on 11 | } 12 | } 13 | } 14 | 15 | coffee-house { 16 | barista { 17 | prepare-coffee-duration = 2 seconds 18 | } 19 | guest { 20 | finish-coffee-duration = 2 seconds 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /exercise_009_Stop_actor/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.event.slf4j.Slf4jLogger] 3 | logger-startup-timeout = 10s 4 | loglevel = DEBUG 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | 7 | actor { 8 | debug { 9 | lifecycle = on 10 | unhandled = on 11 | } 12 | } 13 | } 14 | 15 | coffee-house { 16 | caffeine-limit = 5 17 | barista { 18 | prepare-coffee-duration = 2 seconds 19 | } 20 | guest { 21 | finish-coffee-duration = 2 seconds 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /exercise_011_Faulty_guest/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.event.slf4j.Slf4jLogger] 3 | logger-startup-timeout = 10s 4 | loglevel = DEBUG 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | 7 | actor { 8 | debug { 9 | lifecycle = on 10 | unhandled = on 11 | } 12 | } 13 | } 14 | 15 | coffee-house { 16 | caffeine-limit = 5 17 | barista { 18 | prepare-coffee-duration = 2 seconds 19 | } 20 | guest { 21 | finish-coffee-duration = 2 seconds 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /exercise_010_Lifecycle_monitoring/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.event.slf4j.Slf4jLogger] 3 | logger-startup-timeout = 10s 4 | loglevel = DEBUG 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | 7 | actor { 8 | debug { 9 | lifecycle = on 10 | unhandled = on 11 | } 12 | } 13 | } 14 | 15 | coffee-house { 16 | caffeine-limit = 5 17 | barista { 18 | prepare-coffee-duration = 2 seconds 19 | } 20 | guest { 21 | finish-coffee-duration = 2 seconds 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /exercise_012_Custom_supervision/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.event.slf4j.Slf4jLogger] 3 | logger-startup-timeout = 10s 4 | loglevel = DEBUG 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | 7 | actor { 8 | debug { 9 | lifecycle = on 10 | unhandled = on 11 | } 12 | } 13 | } 14 | 15 | coffee-house { 16 | caffeine-limit = 5 17 | barista { 18 | prepare-coffee-duration = 2 seconds 19 | } 20 | guest { 21 | finish-coffee-duration = 2 seconds 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /exercise_003_Message_actor/README.md: -------------------------------------------------------------------------------- 1 | message-actor 2 | 3 | # Exercise 3 > Message Actor 4 | 5 | In this exercise, we will send a message to our `CoffeeHouse`. 6 | 7 | - In `CoffeeHouseApp` send `CoffeeHouse` the "Brew Coffee" message. 8 | - Use `ActorRef.noSender()` as sender of the message. 9 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 10 | - `CoffeeHouse Open` is logged to `coffee-house.log`. 11 | - `Coffee Brewing` is logged to `coffee-house.log`. 12 | - Use the `test` command to verify the solution works as expected. 13 | - Use the `next` command to move to the next exercise. -------------------------------------------------------------------------------- /exercise_002_Top_level_actor/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | logger-startup-timeout = 10s 3 | } 4 | 5 | // ========================================== 6 | // ANSWER 7 | // ========================================== 8 | //akka { 9 | //// todo setup loglevel DEBUG and use slf4j 10 | // loggers = [akka.event.slf4j.Slf4jLogger] 11 | // logger-startup-timeout = 10s 12 | // loglevel = DEBUG 13 | // logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 14 | // 15 | ////todo turn on unhandled message tracking 16 | // actor { 17 | // debug { 18 | // unhandled = on 19 | // } 20 | // } 21 | //} 22 | -------------------------------------------------------------------------------- /exercise_013_Faulty_waiter/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.event.slf4j.Slf4jLogger] 3 | logger-startup-timeout = 10s 4 | loglevel = DEBUG 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | 7 | actor { 8 | debug { 9 | lifecycle = on 10 | unhandled = on 11 | } 12 | } 13 | } 14 | 15 | coffee-house { 16 | caffeine-limit = 5 17 | barista { 18 | prepare-coffee-duration = 2 seconds 19 | accuracy = 33 20 | } 21 | waiter { 22 | max-complaint-count = 2 23 | } 24 | guest { 25 | finish-coffee-duration = 2 seconds 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /exercise_014_Self_healing/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.event.slf4j.Slf4jLogger] 3 | logger-startup-timeout = 10s 4 | loglevel = DEBUG 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | 7 | actor { 8 | debug { 9 | lifecycle = on 10 | unhandled = on 11 | } 12 | } 13 | } 14 | 15 | coffee-house { 16 | caffeine-limit = 5 17 | barista { 18 | prepare-coffee-duration = 2 seconds 19 | accuracy = 33 20 | } 21 | waiter { 22 | max-complaint-count = 2 23 | } 24 | guest { 25 | finish-coffee-duration = 2 seconds 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /exercise_003_Message_actor/src/test/resources/README.md: -------------------------------------------------------------------------------- 1 | message-actor 2 | 3 | # Exercise 3 > Message Actor 4 | 5 | In this exercise, we will send a message to our `CoffeeHouse`. 6 | 7 | - In `CoffeeHouseApp` send `CoffeeHouse` the "Brew Coffee" message. 8 | - Use `ActorRef.noSender()` as sender of the message. 9 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 10 | - `CoffeeHouse Open` is logged to `coffee-house.log`. 11 | - `Coffee Brewing` is logged to `coffee-house.log`. 12 | - Use the `test` command to verify the solution works as expected. 13 | - Use the `koan next` command to move to the next exercise. 14 | -------------------------------------------------------------------------------- /exercise_016_Use_router/README.md: -------------------------------------------------------------------------------- 1 | use-router 2 | 3 | # Exercise 16 > Use Router 4 | 5 | In this exercise, we will introduce parallelism through the use of routers. 6 | 7 | - Get rid of the bottleneck by using a router for the `Barista`. 8 | - Use an externally configured `round-robin` pool router. 9 | - Run the `run` command to boot the `CoffeeHouseApp` with different router configuration options; watch the throughput. 10 | - Use the `run` command to boot the `CoffeeHouseApp` and verify everything works as expected. 11 | - Use the `test` command to verify the solution works as expected. 12 | - Use the `next` command to move to the next exercise. -------------------------------------------------------------------------------- /shell-prompt.sbt: -------------------------------------------------------------------------------- 1 | import scala.Console 2 | import scala.util.matching._ 3 | 4 | shellPrompt in ThisBuild := { state => 5 | val manRmnd = Console.RED + "[run the man command]" + Console.RESET 6 | val prjNbrNme = Project.extract(state).get(name) 7 | prjNbrNme match { 8 | case ("base") => 9 | s"$manRmnd $prjNbrNme > " 10 | case _ => 11 | val prjNmeRx: Regex = """(?<=[a-zA-z]\d\d\d_).*""".r 12 | val prjNbrRx: Regex = """(\d\d\d)""".r 13 | val prjNme: String = prjNmeRx findAllIn prjNbrNme mkString 14 | val prjNbr: Option[String] = prjNbrRx findFirstIn prjNbrNme 15 | s"$manRmnd [${prjNbr.get}] $prjNme > " 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /exercise_016_Use_router/src/test/resources/README.md: -------------------------------------------------------------------------------- 1 | implement-router 2 | 3 | # Exercise 16 > Implement Router 4 | 5 | In this exercise, we will introduce parallelism through the use of routers. 6 | 7 | - Get rid of the bottleneck by using a router for the `Barista`. 8 | - Use an externally configured `round-robin` pool router. 9 | - Run the `run` command to boot the `CoffeeHouseApp` with different router configuration options; watch the throughput. 10 | - Use the `run` command to boot the `CoffeeHouseApp` and verify everything works as expected. 11 | - Use the `test` command to verify the solution works as expected. 12 | - Use the `koan next` command to move to the next exercise. 13 | -------------------------------------------------------------------------------- /exercise_006_Actor_state/src/test/java/com/lightbend/training/coffeehouse/WaiterTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.testkit.JavaTestKit; 5 | import org.junit.Test; 6 | 7 | public class WaiterTest extends BaseAkkaTestCase { 8 | 9 | @Test 10 | public void sendingServeCoffeeShouldResultInCoffeeServedResponse() { 11 | new JavaTestKit(system) {{ 12 | ActorRef waiter = system.actorOf(Waiter.props()); 13 | waiter.tell(new Waiter.ServeCoffee(new Coffee.Akkaccino()), getRef()); 14 | expectMsgEquals(new Waiter.CoffeeServed(new Coffee.Akkaccino())); 15 | }}; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /exercise_007_Use_scheduler/src/test/java/com/lightbend/training/coffeehouse/WaiterTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.testkit.JavaTestKit; 5 | import org.junit.Test; 6 | 7 | public class WaiterTest extends BaseAkkaTestCase { 8 | 9 | @Test 10 | public void sendingServeCoffeeShouldResultInCoffeeServedResponse() { 11 | new JavaTestKit(system) {{ 12 | ActorRef waiter = system.actorOf(Waiter.props()); 13 | waiter.tell(new Waiter.ServeCoffee(new Coffee.Akkaccino()), getRef()); 14 | expectMsgEquals(new Waiter.CoffeeServed(new Coffee.Akkaccino())); 15 | }}; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /exercise_001_Implement_actor/src/test/resources/README.md: -------------------------------------------------------------------------------- 1 | implement-actor 2 | 3 | # Exercise 1 > Implement Actor 4 | 5 | In this exercise, we create the `CoffeeHouse` actor with logging. 6 | 7 | - Create the `CoffeeHouse` actor in the `com.typesafe.training.coffeehouse` package as follows: 8 | - Extend with `AbstractLoggingActor` abstract class. 9 | - Use `receiveBuilder()` and define the initial behavior to handle any message by logging `Coffee Brewing` at `info` level. 10 | - Use the `run` command to verify the main class `CoffeeHouseApp` boots up as expected. 11 | - Use the `test` command to verify the solution works as expected. 12 | - Use the `koan next` command to move to the next exercise. 13 | -------------------------------------------------------------------------------- /exercise_001_Implement_actor/src/test/java/com/lightbend/training/coffeehouse/CoffeeHouseTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.Props; 5 | import akka.testkit.JavaTestKit; 6 | import org.junit.Test; 7 | 8 | public class CoffeeHouseTest extends BaseAkkaTestCase { 9 | 10 | @Test 11 | public void onReceiveOfMessageCoffeeHouseShouldLogMessage() { 12 | new JavaTestKit(system) {{ 13 | ActorRef coffeeHouse = system.actorOf(Props.create(CoffeeHouse.class)); 14 | interceptInfoLogMessage(this, ".*[Cc]offee.*", 1, () -> coffeeHouse.tell("Brew Coffee", ActorRef.noSender())); 15 | }}; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /exercise_007_Use_scheduler/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.event.slf4j.Slf4jLogger] 3 | logger-startup-timeout = 10s 4 | loglevel = DEBUG 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | 7 | actor { 8 | debug { 9 | lifecycle = on 10 | unhandled = on 11 | } 12 | } 13 | } 14 | 15 | // =========================================================================== 16 | // ANSWER 17 | // =========================================================================== 18 | // todo Add a section for `coffee-house` with `guest` that has the `finish-coffee-duration` property. 19 | coffee-house { 20 | guest { 21 | finish-coffee-duration = 2 seconds 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /exercise_001_Implement_actor/README.md: -------------------------------------------------------------------------------- 1 | implement-actor 2 | 3 | # Exercise 1 > Implement Actor 4 | 5 | In this exercise, we create the `CoffeeHouse` actor with logging. 6 | 7 | - Create the `CoffeeHouse` actor in the `com.lightbend.training.coffeehouse` package as follows: 8 | - Extend with `AbstractLoggingActor` abstract class. 9 | - Implement the `createReceive()` method. 10 | - Use `receiveBuilder()` and define the initial behavior to handle any message by logging `Coffee Brewing` at `info` level. 11 | - Use the `run` command to verify the main class `CoffeeHouseApp` boots up as expected. 12 | - Use the `test` command to verify the solution works as expected. 13 | - Use the `next` command to move to the next exercise. 14 | -------------------------------------------------------------------------------- /exercise_003_Message_actor/src/main/java/com/lightbend/training/coffeehouse/CoffeeHouse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | 5 | package com.lightbend.training.coffeehouse; 6 | 7 | import akka.actor.AbstractLoggingActor; 8 | import akka.actor.Props; 9 | 10 | public class CoffeeHouse extends AbstractLoggingActor { 11 | 12 | public CoffeeHouse() { 13 | log().debug("CoffeeHouse Open"); 14 | } 15 | 16 | @Override 17 | public Receive createReceive() { 18 | return receiveBuilder(). 19 | matchAny(o -> log().info("Coffee Brewing")).build(); 20 | } 21 | 22 | public static Props props() { 23 | return Props.create(CoffeeHouse.class, CoffeeHouse::new); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /exercise_008_Busy_actor/src/test/java/com/lightbend/training/coffeehouse/WaiterTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.testkit.JavaTestKit; 5 | import akka.testkit.TestProbe; 6 | import org.junit.Test; 7 | 8 | public class WaiterTest extends BaseAkkaTestCase { 9 | 10 | @Test 11 | public void sendingServeCoffeeShouldResultInPrepareCoffeeToBarista() { 12 | new JavaTestKit(system) {{ 13 | ActorRef barista = getRef(); 14 | TestProbe guest = new TestProbe(system); 15 | ActorRef waiter = system.actorOf(Waiter.props(barista)); 16 | waiter.tell(new Waiter.ServeCoffee(new Coffee.Akkaccino()), guest.ref()); 17 | expectMsgEquals(new Barista.PrepareCoffee(new Coffee.Akkaccino(), guest.ref())); 18 | }}; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /exercise_009_Stop_actor/src/test/java/com/lightbend/training/coffeehouse/WaiterTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.testkit.JavaTestKit; 5 | import akka.testkit.TestProbe; 6 | import org.junit.Test; 7 | 8 | public class WaiterTest extends BaseAkkaTestCase { 9 | 10 | @Test 11 | public void sendingServeCoffeeShouldResultInApproveCoffeeToCoffeeHouse() { 12 | new JavaTestKit(system) {{ 13 | ActorRef coffeeHouse = getRef(); 14 | TestProbe guest = new TestProbe(system); 15 | ActorRef waiter = system.actorOf(Waiter.props(coffeeHouse)); 16 | waiter.tell(new Waiter.ServeCoffee(new Coffee.Akkaccino()), guest.ref()); 17 | expectMsgEquals(new CoffeeHouse.ApproveCoffee(new Coffee.Akkaccino(), guest.ref())); 18 | }}; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /exercise_011_Faulty_guest/src/test/java/com/lightbend/training/coffeehouse/WaiterTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.testkit.JavaTestKit; 5 | import akka.testkit.TestProbe; 6 | import org.junit.Test; 7 | 8 | public class WaiterTest extends BaseAkkaTestCase { 9 | 10 | @Test 11 | public void sendingServeCoffeeShouldResultInApproveCoffeeToCoffeeHouse() { 12 | new JavaTestKit(system) {{ 13 | ActorRef coffeeHouse = getRef(); 14 | TestProbe guest = new TestProbe(system); 15 | ActorRef waiter = system.actorOf(Waiter.props(coffeeHouse)); 16 | waiter.tell(new Waiter.ServeCoffee(new Coffee.Akkaccino()), guest.ref()); 17 | expectMsgEquals(new CoffeeHouse.ApproveCoffee(new Coffee.Akkaccino(), guest.ref())); 18 | }}; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /exercise_005_Child_actors/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.event.slf4j.Slf4jLogger] 3 | logger-startup-timeout = 10s 4 | loglevel = DEBUG 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | 7 | actor { 8 | debug { 9 | unhandled = on 10 | } 11 | } 12 | } 13 | 14 | //// =========================================================================== 15 | //// ANSWER 16 | //// =========================================================================== 17 | //akka { 18 | // loggers = [akka.event.slf4j.Slf4jLogger] 19 | // logger-startup-timeout = 10s 20 | // loglevel = DEBUG 21 | // logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 22 | // 23 | // actor { 24 | // debug { 25 | // // todo Turn on `lifecycle` debugging. 26 | // lifecycle = on 27 | // unhandled = on 28 | // } 29 | // } 30 | //} 31 | -------------------------------------------------------------------------------- /exercise_012_Custom_supervision/src/test/java/com/lightbend/training/coffeehouse/WaiterTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.testkit.JavaTestKit; 5 | import akka.testkit.TestProbe; 6 | import org.junit.Test; 7 | 8 | public class WaiterTest extends BaseAkkaTestCase { 9 | 10 | @Test 11 | public void sendingServeCoffeeShouldResultInApproveCoffeeToCoffeeHouse() { 12 | new JavaTestKit(system) {{ 13 | ActorRef coffeeHouse = getRef(); 14 | TestProbe guest = new TestProbe(system); 15 | ActorRef waiter = system.actorOf(Waiter.props(coffeeHouse)); 16 | waiter.tell(new Waiter.ServeCoffee(new Coffee.Akkaccino()), guest.ref()); 17 | expectMsgEquals(new CoffeeHouse.ApproveCoffee(new Coffee.Akkaccino(), guest.ref())); 18 | }}; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /exercise_010_Lifecycle_monitoring/src/test/java/com/lightbend/training/coffeehouse/WaiterTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.testkit.JavaTestKit; 5 | import akka.testkit.TestProbe; 6 | import org.junit.Test; 7 | 8 | public class WaiterTest extends BaseAkkaTestCase { 9 | 10 | @Test 11 | public void sendingServeCoffeeShouldResultInApproveCoffeeToCoffeeHouse() { 12 | new JavaTestKit(system) {{ 13 | ActorRef coffeeHouse = getRef(); 14 | TestProbe guest = new TestProbe(system); 15 | ActorRef waiter = system.actorOf(Waiter.props(coffeeHouse)); 16 | waiter.tell(new Waiter.ServeCoffee(new Coffee.Akkaccino()), guest.ref()); 17 | expectMsgEquals(new CoffeeHouse.ApproveCoffee(new Coffee.Akkaccino(), guest.ref())); 18 | }}; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /exercise_015_Detect_bottleneck/README.md: -------------------------------------------------------------------------------- 1 | detect-bottleneck 2 | 3 | # Exercise 15 > Detect Bottleneck 4 | 5 | In this exercise, we will change our configuration settings to see if we can detect a bottleneck. 6 | 7 | 1. Make the following changes to the configuration files: 8 | - Set `caffeine-limit` to 1000 (no more caffeinated guests). 9 | - Set `prepare-coffee-duration` to 2 seconds. 10 | - Set `accuracy` to 100 (no more frustrated waiters). 11 | - Set `finish-coffee-duration` to 2 seconds. 12 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 13 | - Create one `Guest`, then another, then some more and watch the throughput per `Guest`. 14 | - QUIZ: Why does the application not scale? 15 | - QUIZ: Where is the bottleneck? 16 | - Use the `test` command to verify the solution works as expected. 17 | - Use the `next` command to move to the next exercise. -------------------------------------------------------------------------------- /exercise_002_Top_level_actor/README.md: -------------------------------------------------------------------------------- 1 | top-level-actor 2 | 3 | # Exercise 2 > Top Level Actor 4 | 5 | In this exercise, we will make `CoffeeHouse` a top-level actor and implement some configuration properties. 6 | 7 | - In the `CoffeeHouse` actor: 8 | - Implement a `Props` factory method. 9 | - Log "CoffeeHouse Open" at `debug` when the `CoffeeHouse` actor is created. 10 | - In `CoffeeHouseApp` create a top-level actor named `coffee-house`. 11 | - Create a configuration file that does the following: 12 | - Set the Akka logging level to `debug`. 13 | - Turn on logging of `unhandled` messages. 14 | - Use the `Slf4jLogger`. 15 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 16 | - `CoffeeHouse Open` is logged to `coffee-house.log`. 17 | - Use the `test` command to verify the solution works as expected. 18 | - Use the `next` command to move to the next exercise. 19 | -------------------------------------------------------------------------------- /exercise_015_Detect_bottleneck/src/test/resources/README.md: -------------------------------------------------------------------------------- 1 | detect-bottleneck 2 | 3 | # Exercise 15 > Detect Bottleneck 4 | 5 | In this exercise, we will change our configuration settings to see if we can detect a bottleneck. 6 | 7 | 1. Make the following changes to the configuration files: 8 | - Set `caffeine-limit` to 1000 (no more caffeinated guests). 9 | - Set `prepare-coffee-duration` to 2 seconds. 10 | - Set `accuracy` to 100 (no more frustrated waiters). 11 | - Set `finish-coffee-duration` to 2 seconds. 12 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 13 | - Create one `Guest`, then another, then some more and watch the throughput per `Guest`. 14 | - QUIZ: Why does the application not scale? 15 | - QUIZ: Where is the bottleneck? 16 | - Use the `test` command to verify the solution works as expected. 17 | - Use the `koan next` command to move to the next exercise. 18 | -------------------------------------------------------------------------------- /exercise_002_Top_level_actor/src/test/resources/README.md: -------------------------------------------------------------------------------- 1 | top-level-actor 2 | 3 | # Exercise 2 > Top Level Actor 4 | 5 | In this exercise, we will make `CoffeeHouse` a top-level actor and implement some configuration properties. 6 | 7 | - In the `CoffeeHouse` actor: 8 | - Implement a `Props` factory method. 9 | - Log "CoffeeHouse Open" at `debug` when the `CoffeeHouse` actor is created. 10 | - In `CoffeeHouseApp` create a top-level actor named `coffee-house`. 11 | - Create a configuration file that does the following: 12 | - Set the Akka logging level to `debug`. 13 | - Turn on logging of `unhandled` messages. 14 | - Use the `Slf4jLogger`. 15 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 16 | - `CoffeeHouse Open` is logged to `coffee-house.log`. 17 | - Use the `test` command to verify the solution works as expected. 18 | - Use the `koan next` command to move to the next exercise. 19 | -------------------------------------------------------------------------------- /exercise_005_Child_actors/src/main/java/com/lightbend/training/coffeehouse/Guest.java: -------------------------------------------------------------------------------- 1 | // //=========================================================================== 2 | // // ANSWER 3 | // //=========================================================================== 4 | // 5 | // package com.lightbend.training.coffeehouse; 6 | // 7 | // import akka.actor.AbstractLoggingActor; 8 | // import akka.actor.Props; 9 | // 10 | // // @todo create guest class 11 | // public class Guest extends AbstractLoggingActor { 12 | // 13 | // public Guest() { 14 | // } 15 | // 16 | // // @todo Implement the behavior as `empty` 17 | // @Override 18 | // public Receive createReceive() { 19 | // return receiveBuilder().matchAny(this::unhandled).build(); 20 | // } 21 | // 22 | // // @todo Create a `Props` factory for `Guest` 23 | // public static Props props() { 24 | // return Props.create(Guest.class, Guest::new); 25 | // } 26 | // } 27 | -------------------------------------------------------------------------------- /exercise_002_Top_level_actor/src/test/java/com/lightbend/training/coffeehouse/CoffeeHouseTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.Props; 5 | import akka.testkit.JavaTestKit; 6 | import org.junit.Test; 7 | 8 | public class CoffeeHouseTest extends BaseAkkaTestCase { 9 | 10 | @Test 11 | public void onReceiveOfMessageCoffeeHouseShouldLogMessage() { 12 | new JavaTestKit(system) {{ 13 | ActorRef coffeeHouse = system.actorOf(Props.create(CoffeeHouse.class)); 14 | interceptInfoLogMessage(this, ".*[Cc]offee.*", 1, () -> coffeeHouse.tell("Brew Coffee", ActorRef.noSender())); 15 | }}; 16 | } 17 | 18 | @Test 19 | public void shouldLogMessageWhenCreated() { 20 | new JavaTestKit(system) {{ 21 | interceptDebugLogMessage(this, ".*[Oo]pen.*", 1, () -> system.actorOf(CoffeeHouse.props())); 22 | }}; 23 | } 24 | } 25 | 26 | 27 | -------------------------------------------------------------------------------- /exercise_003_Message_actor/src/test/java/com/lightbend/training/coffeehouse/CoffeeHouseTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.Props; 5 | import akka.testkit.JavaTestKit; 6 | import org.junit.Test; 7 | 8 | public class CoffeeHouseTest extends BaseAkkaTestCase { 9 | 10 | @Test 11 | public void onReceiveOfMessageCoffeeHouseShouldLogMessage() { 12 | new JavaTestKit(system) {{ 13 | ActorRef coffeeHouse = system.actorOf(Props.create(CoffeeHouse.class)); 14 | interceptInfoLogMessage(this, ".*[Cc]offee.*", 1, () -> coffeeHouse.tell("Brew Coffee", ActorRef.noSender())); 15 | }}; 16 | } 17 | 18 | @Test 19 | public void shouldLogMessageWhenCreated() { 20 | new JavaTestKit(system) {{ 21 | interceptDebugLogMessage(this, ".*[Oo]pen.*", 1, () -> system.actorOf(CoffeeHouse.props())); 22 | }}; 23 | } 24 | } 25 | 26 | 27 | -------------------------------------------------------------------------------- /exercise_008_Busy_actor/src/test/java/com/lightbend/training/coffeehouse/BaristaTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.testkit.JavaTestKit; 5 | import org.junit.Test; 6 | 7 | public class BaristaTest extends BaseAkkaTestCase { 8 | 9 | @Test 10 | public void sendingPrepareCoffeeShouldResultInCoffeePreparedResponse() { 11 | new JavaTestKit(system) {{ 12 | ActorRef barista = system.actorOf(Barista.props(duration("100 milliseconds"))); 13 | new Within(duration("50 milliseconds"), duration("1000 milliseconds")) { 14 | @Override 15 | protected void run() { 16 | barista.tell(new Barista.PrepareCoffee(new Coffee.Akkaccino(), system.deadLetters()), getRef()); 17 | expectMsgEquals(new Barista.CoffeePrepared(new Coffee.Akkaccino(), system.deadLetters())); 18 | } 19 | }; 20 | }}; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /exercise_009_Stop_actor/src/test/java/com/lightbend/training/coffeehouse/BaristaTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.testkit.JavaTestKit; 5 | import org.junit.Test; 6 | 7 | public class BaristaTest extends BaseAkkaTestCase { 8 | 9 | @Test 10 | public void sendingPrepareCoffeeShouldResultInCoffeePreparedResponse() { 11 | new JavaTestKit(system) {{ 12 | ActorRef barista = system.actorOf(Barista.props(duration("100 milliseconds"))); 13 | new Within(duration("50 milliseconds"), duration("1000 milliseconds")) { 14 | @Override 15 | protected void run() { 16 | barista.tell(new Barista.PrepareCoffee(new Coffee.Akkaccino(), system.deadLetters()), getRef()); 17 | expectMsgEquals(new Barista.CoffeePrepared(new Coffee.Akkaccino(), system.deadLetters())); 18 | } 19 | }; 20 | }}; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /exercise_011_Faulty_guest/src/test/java/com/lightbend/training/coffeehouse/BaristaTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.testkit.JavaTestKit; 5 | import org.junit.Test; 6 | 7 | public class BaristaTest extends BaseAkkaTestCase { 8 | 9 | @Test 10 | public void sendingPrepareCoffeeShouldResultInCoffeePreparedResponse() { 11 | new JavaTestKit(system) {{ 12 | ActorRef barista = system.actorOf(Barista.props(duration("100 milliseconds"))); 13 | new Within(duration("50 milliseconds"), duration("1000 milliseconds")) { 14 | @Override 15 | protected void run() { 16 | barista.tell(new Barista.PrepareCoffee(new Coffee.Akkaccino(), system.deadLetters()), getRef()); 17 | expectMsgEquals(new Barista.CoffeePrepared(new Coffee.Akkaccino(), system.deadLetters())); 18 | } 19 | }; 20 | }}; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /exercise_005_Child_actors/src/test/java/com/lightbend/training/coffeehouse/CoffeeHouseTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.Props; 5 | import akka.testkit.JavaTestKit; 6 | import org.junit.Test; 7 | 8 | public class CoffeeHouseTest extends BaseAkkaTestCase { 9 | 10 | @Test 11 | public void shouldLogMessageWhenCreated() { 12 | new JavaTestKit(system) {{ 13 | interceptDebugLogMessage(this, ".*[Oo]pen.*", 1, () -> system.actorOf(CoffeeHouse.props())); 14 | }}; 15 | } 16 | 17 | @Test 18 | public void shouldCreateGuestActorsWhenCreateGuestMessageSent() { 19 | new JavaTestKit(system) {{ 20 | ActorRef coffeeHouse = system.actorOf(Props.create(CoffeeHouse.class), "create-guest"); 21 | coffeeHouse.tell(CoffeeHouse.CreateGuest.Instance, ActorRef.noSender()); 22 | expectActor(this, "/user/create-guest/$*"); 23 | }}; 24 | } 25 | } 26 | 27 | 28 | -------------------------------------------------------------------------------- /exercise_010_Lifecycle_monitoring/src/test/java/com/lightbend/training/coffeehouse/BaristaTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.testkit.JavaTestKit; 5 | import org.junit.Test; 6 | 7 | public class BaristaTest extends BaseAkkaTestCase { 8 | 9 | @Test 10 | public void sendingPrepareCoffeeShouldResultInCoffeePreparedResponse() { 11 | new JavaTestKit(system) {{ 12 | ActorRef barista = system.actorOf(Barista.props(duration("100 milliseconds"))); 13 | new Within(duration("50 milliseconds"), duration("1000 milliseconds")) { 14 | @Override 15 | protected void run() { 16 | barista.tell(new Barista.PrepareCoffee(new Coffee.Akkaccino(), system.deadLetters()), getRef()); 17 | expectMsgEquals(new Barista.CoffeePrepared(new Coffee.Akkaccino(), system.deadLetters())); 18 | } 19 | }; 20 | }}; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /exercise_012_Custom_supervision/src/test/java/com/lightbend/training/coffeehouse/BaristaTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.testkit.JavaTestKit; 5 | import org.junit.Test; 6 | 7 | public class BaristaTest extends BaseAkkaTestCase { 8 | 9 | @Test 10 | public void sendingPrepareCoffeeShouldResultInCoffeePreparedResponse() { 11 | new JavaTestKit(system) {{ 12 | ActorRef barista = system.actorOf(Barista.props(duration("100 milliseconds"))); 13 | new Within(duration("50 milliseconds"), duration("1000 milliseconds")) { 14 | @Override 15 | protected void run() { 16 | barista.tell(new Barista.PrepareCoffee(new Coffee.Akkaccino(), system.deadLetters()), getRef()); 17 | expectMsgEquals(new Barista.CoffeePrepared(new Coffee.Akkaccino(), system.deadLetters())); 18 | } 19 | }; 20 | }}; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /exercise_001_Implement_actor/src/main/java/com/lightbend/training/coffeehouse/CoffeeHouse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | 5 | package com.lightbend.training.coffeehouse; 6 | 7 | public class CoffeeHouse { 8 | 9 | public CoffeeHouse() { 10 | } 11 | } 12 | 13 | //=========================================================================== 14 | // ANSWER 15 | //=========================================================================== 16 | //import akka.actor.AbstractLoggingActor; 17 | 18 | // @todo extend with AbstractLoggingActor 19 | // public class CoffeeHouse extends AbstractLoggingActor { 20 | 21 | // public CoffeeHouse() { 22 | // } 23 | 24 | // @todo implement createReceive and use receiveBuilder 25 | // @Override 26 | // public Receive createReceive() { 27 | // return receiveBuilder(). 28 | // matchAny(o -> log().info("Coffee Brewing")).build(); 29 | // } 30 | // } 31 | -------------------------------------------------------------------------------- /exercise_014_Self_healing/README.md: -------------------------------------------------------------------------------- 1 | self-healing 2 | 3 | # Exercise 14 > Self Healing 4 | 5 | In this exercise, we will correct a problem introduced in the last exercise by implement self-healing. 6 | 7 | - QUIZ: Why does the message flow in exercise 013 get interrupted? 8 | - Change the message flow by: 9 | - Providing the `Waiter` actors supervisor with all the necessary information. 10 | - Attention: Think supervision strategy! 11 | - Run the `run` command to boot the `CoffeeHouseApp` and verify that `Guest` actors are served even after the `Waiter` gets frustrated. 12 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 13 | - Create a `Guest` and make sure the `Waiter` gets frustrated. 14 | - That `Guest` actors are served even after the `Waiter` gets frustrated. 15 | - Attention: 16 | - You might need to use small `accuracy` and `maxComplainCount` values. 17 | - Use the `test` command to verify the solution works as expected. 18 | - Use the `next` command to move to the next exercise. -------------------------------------------------------------------------------- /exercise_016_Use_router/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.event.slf4j.Slf4jLogger] 3 | logger-startup-timeout = 10s 4 | loglevel = DEBUG 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | 7 | actor { 8 | debug { 9 | lifecycle = on 10 | unhandled = on 11 | } 12 | # =========================================================================== 13 | # ANSWER 14 | # =========================================================================== 15 | # todo Use an externally configured `round-robin` pool router. 16 | deployment { 17 | /coffee-house/barista { 18 | router = round-robin-pool 19 | nr-of-instances = 4 20 | } 21 | } 22 | } 23 | } 24 | 25 | coffee-house { 26 | caffeine-limit = 1000 27 | barista { 28 | prepare-coffee-duration = 2 seconds 29 | accuracy = 100 30 | } 31 | waiter { 32 | max-complaint-count = 2 33 | } 34 | guest { 35 | finish-coffee-duration = 2 seconds 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /exercise_015_Detect_bottleneck/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.event.slf4j.Slf4jLogger] 3 | logger-startup-timeout = 10s 4 | loglevel = DEBUG 5 | logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" 6 | 7 | actor { 8 | debug { 9 | lifecycle = on 10 | unhandled = on 11 | } 12 | } 13 | } 14 | 15 | # =========================================================================== 16 | # ANSWER 17 | # =========================================================================== 18 | # todo Set `caffeine-limit` to 1000 (no more caffeinated guests). 19 | # todo Set `prepare-coffee-duration` to 2 seconds. 20 | # todo Set `accuracy` to 100 (no more frustrated waiters). 21 | # todo Set `finish-coffee-duration` to 2 seconds. 22 | coffee-house { 23 | caffeine-limit = 1000 24 | barista { 25 | prepare-coffee-duration = 2 seconds 26 | accuracy = 100 27 | } 28 | waiter { 29 | max-complaint-count = 2 30 | } 31 | guest { 32 | finish-coffee-duration = 2 seconds 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /exercise_014_Self_healing/src/test/resources/README.md: -------------------------------------------------------------------------------- 1 | self-healing 2 | 3 | # Exercise 14 > Self Healing 4 | 5 | In this exercise, we will correct a problem introduced in the last exercise by implement self-healing. 6 | 7 | - QUIZ: Why does the message flow in exercise 013 get interrupted? 8 | - Change the message flow by: 9 | - Providing the `Waiter` actors supervisor with all the necessary information. 10 | - Attention: Think supervision strategy! 11 | 3. Run the `run` command to boot the `CoffeeHouseApp` and verify that `Guest` actors are served even after the `Waiter` gets frustrated. 12 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 13 | - Create a `Guest` and make sure the `Waiter` gets frustrated. 14 | - That `Guest` actors are served even after the `Waiter` gets frustrated. 15 | - Attention: 16 | - You might need to use small `accuracy` and `maxComplainCount` values. 17 | - Use the `test` command to verify the solution works as expected. 18 | - Use the `koan next` command to move to the next exercise. 19 | -------------------------------------------------------------------------------- /exercise_012_Custom_supervision/README.md: -------------------------------------------------------------------------------- 1 | custom-supervision 2 | 3 | # Exercise 12 > Custom Supervision 4 | 5 | In this exercise, we will further explore resilience by implementing custom supervision. 6 | 7 | - Look up the default supervisor strategy in the `Akka` documentation. 8 | - Change `CoffeeHouse` as follows: 9 | - Caffeinated `Guest` actors should not restart. 10 | - Apply a custom supervision strategy that stops them instead. 11 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 12 | - Create a `Guest` with an individual `caffeineLimit` less than the global one and watch its lifecycle. 13 | - Make sure the `Guest` actor throws `CaffeineException`. 14 | - Verify that the caffeinated `Guest` does not restart. 15 | - Attention: 16 | - Enter g (a/c/m) 2 or guest (a/c/m) 2 to create a `Guest` with a `caffeineLimit` of 2. 17 | - If you omit the limit, `Integer.MAX_VALUE` will be used by default. 18 | - Use the `test` command to verify the solution works as expected. 19 | - Use the `next` command to move to the next exercise. -------------------------------------------------------------------------------- /exercise_012_Custom_supervision/src/test/resources/README.md: -------------------------------------------------------------------------------- 1 | custom-supervision 2 | 3 | # Exercise 12 > Custom Supervision 4 | 5 | In this exercise, we will further explore resilience by implementing custom supervision. 6 | 7 | - Look up the default supervisor strategy in the `Akka` documentation. 8 | - Change `CoffeeHouse` as follows: 9 | - Caffeinated `Guest` actors should not restart. 10 | - Apply a custom supervision strategy that stops them instead. 11 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 12 | - Create a `Guest` with an individual `caffeineLimit` less than the global one and watch its lifecycle. 13 | - Make sure the `Guest` actor throws `CaffeineException`. 14 | - Verify that the caffeinated `Guest` does not restart. 15 | - Attention: 16 | - Enter g 2 or guest 2 to create a `Guest` with a `caffeineLimit` of 2. 17 | - If you omit the limit, `Integer.MAX_VALUE` will be used by default. 18 | - Use the `test` command to verify the solution works as expected. 19 | - Use the `koan next` command to move to the next exercise. 20 | -------------------------------------------------------------------------------- /exercise_000_Initial_state/src/test/java/com/lightbend/training/coffeehouse/CoffeeHouseAppTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | 4 | import org.assertj.core.data.MapEntry; 5 | import org.junit.Test; 6 | 7 | import java.util.Arrays; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | public class CoffeeHouseAppTest { 14 | 15 | @Test 16 | public void argsToOptsShouldConvertArgsToOpts() { 17 | final Map result = CoffeeHouseApp.argsToOpts(Arrays.asList("a=1", "b", "-Dc=2")); 18 | assertThat(result).contains(MapEntry.entry("a", "1"), MapEntry.entry("-Dc", "2")); 19 | } 20 | 21 | 22 | @Test 23 | public void applySystemPropertiesShouldConvertOptsToSystemProps() { 24 | System.setProperty("c", ""); 25 | Map opts = new HashMap<>(); 26 | opts.put("a", "1"); 27 | opts.put("-Dc", "2"); 28 | CoffeeHouseApp.applySystemProperties(opts); 29 | assertThat(System.getProperty("c")).isEqualTo("2"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /exercise_001_Implement_actor/src/test/java/com/lightbend/training/coffeehouse/CoffeeHouseAppTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | 4 | import org.assertj.core.data.MapEntry; 5 | import org.junit.Test; 6 | 7 | import java.util.Arrays; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | public class CoffeeHouseAppTest { 14 | 15 | @Test 16 | public void argsToOptsShouldConvertArgsToOpts() { 17 | final Map result = CoffeeHouseApp.argsToOpts(Arrays.asList("a=1", "b", "-Dc=2")); 18 | assertThat(result).contains(MapEntry.entry("a", "1"), MapEntry.entry("-Dc", "2")); 19 | } 20 | 21 | 22 | @Test 23 | public void applySystemPropertiesShouldConvertOptsToSystemProps() { 24 | System.setProperty("c", ""); 25 | Map opts = new HashMap<>(); 26 | opts.put("a", "1"); 27 | opts.put("-Dc", "2"); 28 | CoffeeHouseApp.applySystemProperties(opts); 29 | assertThat(System.getProperty("c")).isEqualTo("2"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /man.sbt: -------------------------------------------------------------------------------- 1 | import scala.Console 2 | 3 | val mkdRx = """((?:`[\[\]\$> \(\)\w.,-]+`)|(?:\*["\{\}\! \(\)\w.,-]+\*))""".r 4 | val mkdMatch = ".*" + mkdRx.toString + ".*" 5 | val mkdSplit = """(`)|(\*)""" 6 | 7 | def man: Command = Command.command("man") { state => 8 | val prjBase: File = Project.extract(state).get(baseDirectory) 9 | IO.readLines(new sbt.File(prjBase + "/README.md")) foreach { 10 | case ln if ln.length > 0 && ln(0).equals('#') => 11 | Console.println(Console.RED + ln + Console.RESET) 12 | case ln if ln.matches(mkdMatch) => 13 | val mkdSet: Set[String] = mkdRx.findAllIn(ln).matchData.map(m => m.toString()).toSet 14 | ln.split(mkdSplit).foreach { s => 15 | if (mkdSet.contains("`" + s + "`")) 16 | Console.print(Console.BLUE + s + Console.RESET) 17 | else if (mkdSet.contains("*" + s + "*")) 18 | Console.print(Console.GREEN + s + Console.RESET) 19 | else Console.print(s) 20 | } 21 | Console.print("\n") 22 | case ln => Console.println(ln) 23 | } 24 | Console.print("\n") 25 | state 26 | } 27 | 28 | commands in Global ++= Seq(man) -------------------------------------------------------------------------------- /exercise_004_Use_sender/README.md: -------------------------------------------------------------------------------- 1 | use-sender 2 | 3 | # Exercise 4 > Use Sender 4 | 5 | In this exercise, we will use the sender to respond from `CoffeeHouse`. 6 | 7 | - Change `CoffeeHouse` as follows: 8 | - Instead of logging "Coffee Brewing", respond to the `getSender()`. 9 | - In `CoffeeHouseApp` create an anonymous actor that does the following: 10 | - In the constructor send `CoffeeHouse` a "Brew Coffee" message. 11 | - Pass `getSelf()` as a sender 12 | - Log the message received at `info`. 13 | - **HINT**: Creating anonymous actor: 14 | 15 | ```java 16 | Props.create(AbstractLoggingActor.class, () -> new AbstractLoggingActor(){ 17 | { 18 | coffeeHouse.tell(...) 19 | receive(ReceiveBuilder.matchAny(...)).build()); 20 | } 21 | }); 22 | ``` 23 | 24 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 25 | - `CoffeeHouse Open` is logged to `coffee-house.log`. 26 | - `Coffee Brewing` is logged to `coffee-house.log`. 27 | - Use the `test` command to verify the solution works as expected. 28 | - Use the `next` command to move to the next exercise. -------------------------------------------------------------------------------- /exercise_004_Use_sender/src/test/resources/README.md: -------------------------------------------------------------------------------- 1 | use-sender 2 | 3 | # Exercise 4 > Use Sender 4 | 5 | In this exercise, we will use the sender to respond from `CoffeeHouse`. 6 | 7 | - Change `CoffeeHouse` as follows: 8 | - Instead of logging "Coffee Brewing", respond to the `sender()`. 9 | - In `CoffeeHouseApp` create an anonymous actor that does the following: 10 | - In the constructor send `CoffeeHouse` a "Brew Coffee" message. 11 | - Pass `self()` as a sender 12 | - Log the message received at `info`. 13 | - **HINT**: Creating anonymous actor: 14 | 15 | ```scala 16 | Props.create(AbstractLoggingActor.class, () -> new AbstractLoggingActor(){ 17 | { 18 | coffeeHouse.tell(...) 19 | receive(ReceiveBuilder.matchAny(...)).build()); 20 | } 21 | }); 22 | ``` 23 | 24 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 25 | - `CoffeeHouse Open` is logged to `coffee-house.log`. 26 | - `Coffee Brewing` is logged to `coffee-house.log`. 27 | - Use the `test` command to verify the solution works as expected. 28 | - Use the `koan next` command to move to the next exercise. 29 | -------------------------------------------------------------------------------- /exercise_006_Actor_state/src/test/java/com/lightbend/training/coffeehouse/GuestTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.testkit.JavaTestKit; 5 | import org.junit.Test; 6 | 7 | public class GuestTest extends BaseAkkaTestCase { 8 | 9 | @Test 10 | public void sendingCoffeeServedShouldIncreaseCoffeeCount() { 11 | new JavaTestKit(system) {{ 12 | ActorRef guest = system.actorOf(Guest.props(system.deadLetters(), new Coffee.Akkaccino())); 13 | interceptInfoLogMessage(this, ".*[Ee]njoy.*1\\.*", 1, () -> { 14 | guest.tell(new Waiter.CoffeeServed(new Coffee.Akkaccino()), ActorRef.noSender()); 15 | }); 16 | }}; 17 | } 18 | 19 | @Test 20 | public void sendingCoffeeFinishedShouldResultInServeCoffeeMessageToWaiter() { 21 | new JavaTestKit(system) {{ 22 | ActorRef guest = system.actorOf(Guest.props(getRef(), new Coffee.Akkaccino())); 23 | guest.tell(Guest.CoffeeFinished.Instance, ActorRef.noSender()); 24 | expectMsgEquals(new Waiter.ServeCoffee(new Coffee.Akkaccino())); 25 | }}; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /exercise_010_Lifecycle_monitoring/README.md: -------------------------------------------------------------------------------- 1 | lifecycle-monitoring 2 | 3 | # Exercise 10 > Lifecycle Monitoring 4 | 5 | Sometimes we need to perform certain tasks before stopping an actor. In this exercise, we will explore this idea by watching for the `Termination` message. 6 | 7 | - Change `CoffeeHouse` to monitor each `Guest` as follows: 8 | - When the `Guest` terminates, remove the `Guest` from caffeineLimit bookkeeping. 9 | - Log "Thanks {guest}, for being our guest!" at `info`. 10 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 11 | - `CoffeeHouse Open` is logged to `coffee-house.log`. 12 | - Lifecycle debug messages are logged to `coffee-house.log`. 13 | - Make sure the correct number of `Guest` creations were logged. 14 | - Make sure the correct number of `Guest` actors were added to the guest book. 15 | - Make sure the `Guest` actors caffeine count is incremented. 16 | - Make sure the guests are enjoying their `yummy` coffee. 17 | - Make sure your `Guest` actors are stopped as expected. 18 | - Make sure your `Guest` actors were removed from the guest book. 19 | - Use the `test` command to verify the solution works as expected. 20 | - Use the `next` command to move to the next exercise. -------------------------------------------------------------------------------- /exercise_010_Lifecycle_monitoring/src/test/resources/README.md: -------------------------------------------------------------------------------- 1 | lifecycle-monitoring 2 | 3 | # Exercise 10 > Lifecycle Monitoring 4 | 5 | Sometimes we need to perform certain tasks before stopping an actor. In this exercise, we will explore this idea by watching for the `Termination` message. 6 | 7 | - Change `CoffeeHouse` to monitor each `Guest` as follows: 8 | - When the `Guest` terminates, remove the `Guest` from caffeineLimit bookkeeping. 9 | - Log "Thanks {guest}, for being our guest!" at `info`. 10 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 11 | - `CoffeeHouse Open` is logged to `coffee-house.log`. 12 | - Lifecycle debug messages are logged to `coffee-house.log`. 13 | - Make sure the correct number of `Guest` creations were logged. 14 | - Make sure the correct number of `Guest` actors were added to the guest book. 15 | - Make sure the `Guest` actors caffeine count is incremented. 16 | - Make sure the guests are enjoying their `yummy` coffee. 17 | - Make sure your `Guest` actors are stopped as expected. 18 | - Make sure your `Guest` actors were removed from the guest book. 19 | - Use the `test` command to verify the solution works as expected. 20 | - Use the `koan next` command to move to the next exercise. -------------------------------------------------------------------------------- /exercise_004_Use_sender/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_005_Child_actors/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_006_Actor_state/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_008_Busy_actor/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_009_Stop_actor/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_011_Faulty_guest/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_014_Self_healing/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_016_Use_router/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_000_Initial_state/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_001_Implement_actor/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_002_Top_level_actor/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_003_Message_actor/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_007_Use_scheduler/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_013_Faulty_waiter/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_015_Detect_bottleneck/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_010_Lifecycle_monitoring/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_012_Custom_supervision/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /exercise_011_Faulty_guest/README.md: -------------------------------------------------------------------------------- 1 | faulty-guest 2 | 3 | # Exercise 11 > Faulty Guest 4 | 5 | In this exercise, we will explore resilience by managing a faulty actor. 6 | 7 | - Change `Guest` as follows: 8 | - Add a `caffeineLimit` parameter. 9 | - Create new exception called `CaffeineException` by extending `IllegalStateException`. 10 | - Upon receiving `CoffeeFinished` throw the `CaffeineException` if `coffeeCount` exceeds `caffeineLimit`. 11 | - Change `CoffeeHouse` as follows: 12 | - So that a `Guest` can be created with a `caffeineLimit`. 13 | - Log the `Guest` path name instead of just the `Guest`. 14 | - Change `CoffeeHouseApp` as follows: 15 | - So that a `Guest` can be created with a `caffeineLimit`. 16 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 17 | - Create a `Guest` with an individual `caffeineLimit` less than the global one and watch its lifecycle. 18 | - Make sure the `Guest` actor throws `CaffeineException`. 19 | - Attention: 20 | - Enter g (a/c/m) 2 or guest (a/c/m) 2 to create a `Guest` with a `caffeineLimit` of 2. 21 | - If you omit the limit, `Integer.MAX_VALUE` will be used by default. 22 | - Use the `test` command to verify the solution works as expected. 23 | - Use the `next` command to move to the next exercise. -------------------------------------------------------------------------------- /exercise_004_Use_sender/src/test/java/com/lightbend/training/coffeehouse/CoffeeHouseTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.Props; 5 | import akka.testkit.JavaTestKit; 6 | import org.junit.Test; 7 | 8 | public class CoffeeHouseTest extends BaseAkkaTestCase { 9 | 10 | @Test 11 | public void onReceiveOfMessageCoffeeHouseShouldLogMessage() { 12 | new JavaTestKit(system) {{ 13 | ActorRef coffeeHouse = system.actorOf(Props.create(CoffeeHouse.class)); 14 | coffeeHouse.tell("Brew Coffee", getRef()); 15 | new ExpectMsg("Some [Cc]offee response") { 16 | @Override 17 | protected String match(Object msg) { 18 | if (msg.toString().matches(".*[Cc]offee.*")) { 19 | return "match"; 20 | } else { 21 | throw noMatch(); 22 | } 23 | } 24 | }.get(); 25 | }}; 26 | } 27 | 28 | @Test 29 | public void shouldLogMessageWhenCreated() { 30 | new JavaTestKit(system) {{ 31 | interceptDebugLogMessage(this, ".*[Oo]pen.*", 1, () -> system.actorOf(CoffeeHouse.props())); 32 | }}; 33 | } 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_011_Faulty_guest/src/test/resources/README.md: -------------------------------------------------------------------------------- 1 | faulty-guest 2 | 3 | # Exercise 11 > Faulty Guest 4 | 5 | In this exercise, we will explore resilience by managing a faulty actor. 6 | 7 | - Change `Guest` as follows: 8 | - Add a `caffeineLimit` parameter. 9 | - Create new exception called `CaffeineException` by extending `IllegalStateException`. 10 | - Upon receiving `CoffeeFinished` throw the `CaffeineException` if `coffeeCount` exceeds `caffeineLimit`. 11 | - Change `CoffeeHouse` as follows: 12 | - So that a `Guest` can be created with a `caffeineLimit`. 13 | - Log the `Guest` path name instead of just the `Guest`. 14 | - Change `CoffeeHouseApp` as follows: 15 | - So that a `Guest` can be created with a `caffeineLimit`. 16 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 17 | - Create a `Guest` with an individual `caffeineLimit` less than the global one and watch its lifecycle. 18 | - Make sure the `Guest` actor throws `CaffeineException`. 19 | - Attention: 20 | - Enter g 2 or guest 2 to create a `Guest` with a `caffeineLimit` of 2. 21 | - If you omit the limit, `Integer.MAX_VALUE` will be used by default. 22 | - Use the `test` command to verify the solution works as expected. 23 | - Use the `koan next` command to move to the next exercise. 24 | -------------------------------------------------------------------------------- /exercise_006_Actor_state/src/test/java/com/lightbend/training/coffeehouse/CoffeeHouseTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.Props; 5 | import akka.testkit.JavaTestKit; 6 | import org.junit.Test; 7 | 8 | public class CoffeeHouseTest extends BaseAkkaTestCase { 9 | 10 | @Test 11 | public void shouldLogMessageWhenCreated() { 12 | new JavaTestKit(system) {{ 13 | interceptDebugLogMessage(this, ".*[Oo]pen.*", 1, () -> system.actorOf(CoffeeHouse.props())); 14 | }}; 15 | } 16 | 17 | @Test 18 | public void shouldCreateChildActorCalledWaiterWhenCreated() { 19 | new JavaTestKit(system) {{ 20 | system.actorOf(Props.create(CoffeeHouse.class), "create-waiter"); 21 | expectActor(this, "/user/create-waiter/waiter"); 22 | }}; 23 | } 24 | 25 | @Test 26 | public void shouldCreateGuestActorsWhenCreateGuestMessageSent() { 27 | new JavaTestKit(system) {{ 28 | ActorRef coffeeHouse = system.actorOf(Props.create(CoffeeHouse.class), "create-guest"); 29 | coffeeHouse.tell(new CoffeeHouse.CreateGuest(new Coffee.Akkaccino()), ActorRef.noSender()); 30 | expectActor(this, "/user/create-guest/$*"); 31 | }}; 32 | } 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /exercise_007_Use_scheduler/src/test/java/com/lightbend/training/coffeehouse/CoffeeHouseTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.Props; 5 | import akka.testkit.JavaTestKit; 6 | import org.junit.Test; 7 | 8 | public class CoffeeHouseTest extends BaseAkkaTestCase { 9 | 10 | @Test 11 | public void shouldLogMessageWhenCreated() { 12 | new JavaTestKit(system) {{ 13 | interceptDebugLogMessage(this, ".*[Oo]pen.*", 1, () -> system.actorOf(CoffeeHouse.props())); 14 | }}; 15 | } 16 | 17 | @Test 18 | public void shouldCreateChildActorCalledWaiterWhenCreated() { 19 | new JavaTestKit(system) {{ 20 | system.actorOf(Props.create(CoffeeHouse.class), "create-waiter"); 21 | expectActor(this, "/user/create-waiter/waiter"); 22 | }}; 23 | } 24 | 25 | @Test 26 | public void shouldCreateGuestActorsWhenCreateGuestMessageSent() { 27 | new JavaTestKit(system) {{ 28 | ActorRef coffeeHouse = system.actorOf(Props.create(CoffeeHouse.class), "create-guest"); 29 | coffeeHouse.tell(new CoffeeHouse.CreateGuest(new Coffee.Akkaccino()), ActorRef.noSender()); 30 | expectActor(this, "/user/create-guest/$*"); 31 | }}; 32 | } 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /exercise_000_Initial_state/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_003_Message_actor/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_004_Use_sender/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_005_Child_actors/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_006_Actor_state/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_007_Use_scheduler/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_008_Busy_actor/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_009_Stop_actor/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_011_Faulty_guest/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_013_Faulty_waiter/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_014_Self_healing/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_016_Use_router/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_001_Implement_actor/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_002_Top_level_actor/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_012_Custom_supervision/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_015_Detect_bottleneck/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_010_Lifecycle_monitoring/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | warn 6 | 7 | 8 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 9 | 10 | 11 | 12 | 13 | ${coffee-house.log-file:-coffee-house.log} 14 | 15 | %date{HH:mm:ss} %-5level [%X{akkaSource}] - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /exercise_016_Use_router/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loggers = [akka.testkit.TestEventListener] 3 | logging-filter = "akka.event.DefaultLoggingFilter" 4 | 5 | actor { 6 | debug { 7 | lifecycle = on 8 | unhandled = on 9 | } 10 | deployment { 11 | /create-barista/barista { 12 | router = round-robin-pool 13 | nr-of-instances = 4 14 | } 15 | /create-waiter/barista { 16 | router = round-robin-pool 17 | nr-of-instances = 4 18 | } 19 | /create-guest/barista { 20 | router = round-robin-pool 21 | nr-of-instances = 4 22 | } 23 | /caffeine-limit/barista { 24 | router = round-robin-pool 25 | nr-of-instances = 4 26 | } 27 | /guest-terminated/barista { 28 | router = round-robin-pool 29 | nr-of-instances = 4 30 | } 31 | /guest-removed/barista { 32 | router = round-robin-pool 33 | nr-of-instances = 4 34 | } 35 | /guest-stopped/barista { 36 | router = round-robin-pool 37 | nr-of-instances = 4 38 | } 39 | /resend-prepare-coffee/barista { 40 | router = round-robin-pool 41 | nr-of-instances = 4 42 | } 43 | } 44 | } 45 | } 46 | 47 | coffee-house { 48 | barista { 49 | prepare-coffee-duration = 100 milliseconds 50 | } 51 | guest { 52 | finish-coffee-duration = 100 milliseconds 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /exercise_002_Top_level_actor/src/test/java/com/lightbend/training/coffeehouse/CoffeeHouseAppTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | 4 | import akka.testkit.JavaTestKit; 5 | import org.assertj.core.data.MapEntry; 6 | import org.junit.Test; 7 | 8 | import java.util.Arrays; 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | 14 | public class CoffeeHouseAppTest extends BaseAkkaTestCase { 15 | 16 | @Test 17 | public void argsToOptsShouldConvertArgsToOpts() { 18 | final Map result = CoffeeHouseApp.argsToOpts(Arrays.asList("a=1", "b", "-Dc=2")); 19 | assertThat(result).contains(MapEntry.entry("a", "1"), MapEntry.entry("-Dc", "2")); 20 | } 21 | 22 | 23 | @Test 24 | public void applySystemPropertiesShouldConvertOptsToSystemProps() { 25 | System.setProperty("c", ""); 26 | Map opts = new HashMap<>(); 27 | opts.put("a", "1"); 28 | opts.put("-Dc", "2"); 29 | CoffeeHouseApp.applySystemProperties(opts); 30 | assertThat(System.getProperty("c")).isEqualTo("2"); 31 | } 32 | 33 | @Test 34 | public void shouldCreateATopLevelActorCalledCoffeeHouse() { 35 | new JavaTestKit(system) {{ 36 | new CoffeeHouseApp(system); 37 | String path = "/user/coffee-house"; 38 | expectActor(this, path); 39 | }}; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /exercise_002_Top_level_actor/src/main/java/com/lightbend/training/coffeehouse/CoffeeHouse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | 5 | package com.lightbend.training.coffeehouse; 6 | 7 | import akka.actor.AbstractLoggingActor; 8 | 9 | public class CoffeeHouse extends AbstractLoggingActor { 10 | 11 | @Override 12 | public Receive createReceive() { 13 | return receiveBuilder(). 14 | matchAny(o -> log().info("Coffee Brewing")).build(); 15 | } 16 | 17 | public CoffeeHouse() { 18 | } 19 | } 20 | 21 | //=========================================================================== 22 | // ANSWER 23 | //=========================================================================== 24 | //import akka.actor.AbstractLoggingActor; 25 | //import akka.actor.Props; 26 | // 27 | // public class CoffeeHouse extends AbstractLoggingActor { 28 | // 29 | // @Override 30 | // public Receive createReceive() { 31 | // return receiveBuilder(). 32 | // matchAny(o -> log().info("Coffee Brewing")).build(); 33 | // } 34 | // 35 | // // @todo log @ debug "CoffeeHouse Open" 36 | // public CoffeeHouse() { 37 | // log().debug("CoffeeHouse Open"); 38 | // } 39 | // 40 | // // @todo implement props factory method 41 | // public static Props props() { 42 | // return Props.create(CoffeeHouse.class, CoffeeHouse::new); 43 | // } 44 | // } -------------------------------------------------------------------------------- /exercise_005_Child_actors/README.md: -------------------------------------------------------------------------------- 1 | child-actors 2 | 3 | # Exercise 5 > Child Actors 4 | 5 | In this exercise, we will use `CoffeeHouse` to create `Guest` as a child actor. 6 | 7 | - Create the `Guest` actor in the `com.lightbend.training.coffeehouse` package as follows: 8 | - Create a `Props` factory for `Guest`. 9 | - Implement the behavior as `empty`. 10 | - Attention: See `Actor.unhandled`. 11 | - Change `CoffeeHouse` as follows: 12 | - Add `CreateGuest` message. Make it a singleton object. 13 | - Use a `createGuest` factory method that creates a child `Guest` actor without `name`. 14 | - Upon receiving the `CreateGuest` message call the factory method. 15 | - Change `CoffeeHouseApp` as follows: 16 | - Remove the `anonymous` actor. 17 | - When handling `TerminalCommand.Guest`, send `CreateGuest` to `CoffeeHouse`. 18 | - Make sure you account for the creating of 1 or more `Guest` actors. 19 | - Change the `src/main/resource/application.conf` as follows: 20 | - Turn on `lifecycle` debugging. 21 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 22 | - Attention: 23 | - Enter `5 g` or `5 guest` to create five `Guest` actors. 24 | - If you omit the count, `1` is used by default. 25 | - `CoffeeHouse Open` is logged to `coffee-house.log`. 26 | - Lifecycle debug messages are logged to `coffee-house.log`. 27 | - Make sure the correct number of `Guest` creations were logged. 28 | - Use the `test` command to verify the solution works as expected. 29 | - Use the `next` command to move to the next exercise. -------------------------------------------------------------------------------- /exercise_005_Child_actors/src/test/resources/README.md: -------------------------------------------------------------------------------- 1 | child-actors 2 | 3 | # Exercise 5 > Child Actors 4 | 5 | In this exercise, we will use `CoffeeHouse` to create `Guest` as a child actor. 6 | 7 | - Create the `Guest` actor in the `com.typesafe.training.coffeehouse` package as follows: 8 | - Create a `Props` factory for `Guest`. 9 | - Implement the behavior as `empty`. 10 | - Attention: See `Actor.unhandled`. 11 | - Change `CoffeeHouse` as follows: 12 | - Add `CreateGuest` message. Make it a singleton object. 13 | - Use a `createGuest` factory method that creates a child `Guest` actor without `name`. 14 | - Upon receiving the `CreateGuest` message call the factory method. 15 | - Change `CoffeeHouseApp` as follows: 16 | - Remove the `anonymous` actor. 17 | - When handling `TerminalCommand.Guest`, send `CreateGuest` to `CoffeeHouse`. 18 | - Make sure you account for the creating of 1 or more `Guest` actors. 19 | - Change the `src/main/resource/application.conf` as follows: 20 | - Turn on `lifecycle` debugging. 21 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 22 | - Attention: 23 | - Enter `5 g` or `5 guest` to create five `Guest` actors. 24 | - If you omit the count, `1` is used by default. 25 | - `CoffeeHouse Open` is logged to `coffee-house.log`. 26 | - Lifecycle debug messages are logged to `coffee-house.log`. 27 | - Make sure the correct number of `Guest` creations were logged. 28 | - Use the `test` command to verify the solution works as expected. 29 | - Use the `koan next` command to move to the next exercise. 30 | -------------------------------------------------------------------------------- /exercise_008_Busy_actor/src/test/java/com/lightbend/training/coffeehouse/CoffeeHouseTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.Props; 5 | import akka.testkit.JavaTestKit; 6 | import org.junit.Test; 7 | 8 | public class CoffeeHouseTest extends BaseAkkaTestCase { 9 | 10 | @Test 11 | public void shouldLogMessageWhenCreated() { 12 | new JavaTestKit(system) {{ 13 | interceptDebugLogMessage(this, ".*[Oo]pen.*", 1, () -> system.actorOf(CoffeeHouse.props())); 14 | }}; 15 | } 16 | 17 | @Test 18 | public void shouldCreateChildActorCalledBaristaWhenCreated() { 19 | new JavaTestKit(system) {{ 20 | system.actorOf(Props.create(CoffeeHouse.class), "create-barista"); 21 | expectActor(this, "/user/create-barista/waiter"); 22 | }}; 23 | } 24 | 25 | @Test 26 | public void shouldCreateChildActorCalledWaiterWhenCreated() { 27 | new JavaTestKit(system) {{ 28 | system.actorOf(Props.create(CoffeeHouse.class), "create-waiter"); 29 | expectActor(this, "/user/create-waiter/waiter"); 30 | }}; 31 | } 32 | 33 | @Test 34 | public void shouldCreateGuestActorsWhenCreateGuestMessageSent() { 35 | new JavaTestKit(system) {{ 36 | ActorRef coffeeHouse = system.actorOf(Props.create(CoffeeHouse.class), "create-guest"); 37 | coffeeHouse.tell(new CoffeeHouse.CreateGuest(new Coffee.Akkaccino()), ActorRef.noSender()); 38 | expectActor(this, "/user/create-guest/$*"); 39 | }}; 40 | } 41 | } 42 | 43 | 44 | -------------------------------------------------------------------------------- /exercise_000_Initial_state/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | public interface Terminal { 10 | 11 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 12 | Pattern getStatusPattern = Pattern.compile("status|s"); 13 | Pattern quitPattern = Pattern.compile("quit|q"); 14 | 15 | static TerminalCommand create(final String s) { 16 | 17 | final Matcher guestMatcher = createGuestPattern.matcher(s); 18 | if (guestMatcher.matches()) { 19 | 20 | final String countGroup = guestMatcher.group(1); 21 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 22 | 23 | final String coffeeGroup = guestMatcher.group(2); 24 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 25 | 26 | final String maxCoffeeCountGroup = guestMatcher.group(3); 27 | final int maxCoffeeCount = 28 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 29 | 30 | return new TerminalCommand.Guest(count, coffee, maxCoffeeCount); 31 | } 32 | if (getStatusPattern.matcher(s).matches()) return TerminalCommand.Status.Instance; 33 | if (quitPattern.matcher(s).matches()) return TerminalCommand.Quit.Instance; 34 | return new TerminalCommand.Unknown(s); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /exercise_003_Message_actor/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | public interface Terminal { 10 | 11 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 12 | Pattern getStatusPattern = Pattern.compile("status|s"); 13 | Pattern quitPattern = Pattern.compile("quit|q"); 14 | 15 | static TerminalCommand create(final String s) { 16 | 17 | final Matcher guestMatcher = createGuestPattern.matcher(s); 18 | if (guestMatcher.matches()) { 19 | 20 | final String countGroup = guestMatcher.group(1); 21 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 22 | 23 | final String coffeeGroup = guestMatcher.group(2); 24 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 25 | 26 | final String maxCoffeeCountGroup = guestMatcher.group(3); 27 | final int maxCoffeeCount = 28 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 29 | 30 | return new TerminalCommand.Guest(count, coffee, maxCoffeeCount); 31 | } 32 | if (getStatusPattern.matcher(s).matches()) return TerminalCommand.Status.Instance; 33 | if (quitPattern.matcher(s).matches()) return TerminalCommand.Quit.Instance; 34 | return new TerminalCommand.Unknown(s); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /exercise_005_Child_actors/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | public interface Terminal { 10 | 11 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 12 | Pattern getStatusPattern = Pattern.compile("status|s"); 13 | Pattern quitPattern = Pattern.compile("quit|q"); 14 | 15 | static TerminalCommand create(final String s) { 16 | 17 | final Matcher guestMatcher = createGuestPattern.matcher(s); 18 | if (guestMatcher.matches()) { 19 | 20 | final String countGroup = guestMatcher.group(1); 21 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 22 | 23 | final String coffeeGroup = guestMatcher.group(2); 24 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 25 | 26 | final String maxCoffeeCountGroup = guestMatcher.group(3); 27 | final int maxCoffeeCount = 28 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 29 | 30 | return new TerminalCommand.Guest(count, coffee, maxCoffeeCount); 31 | } 32 | if (getStatusPattern.matcher(s).matches()) return TerminalCommand.Status.Instance; 33 | if (quitPattern.matcher(s).matches()) return TerminalCommand.Quit.Instance; 34 | return new TerminalCommand.Unknown(s); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /exercise_007_Use_scheduler/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | public interface Terminal { 10 | 11 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 12 | Pattern getStatusPattern = Pattern.compile("status|s"); 13 | Pattern quitPattern = Pattern.compile("quit|q"); 14 | 15 | static TerminalCommand create(final String s) { 16 | 17 | final Matcher guestMatcher = createGuestPattern.matcher(s); 18 | if (guestMatcher.matches()) { 19 | 20 | final String countGroup = guestMatcher.group(1); 21 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 22 | 23 | final String coffeeGroup = guestMatcher.group(2); 24 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 25 | 26 | final String maxCoffeeCountGroup = guestMatcher.group(3); 27 | final int maxCoffeeCount = 28 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 29 | 30 | return new TerminalCommand.Guest(count, coffee, maxCoffeeCount); 31 | } 32 | if (getStatusPattern.matcher(s).matches()) return TerminalCommand.Status.Instance; 33 | if (quitPattern.matcher(s).matches()) return TerminalCommand.Quit.Instance; 34 | return new TerminalCommand.Unknown(s); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /exercise_008_Busy_actor/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | public interface Terminal { 10 | 11 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 12 | Pattern getStatusPattern = Pattern.compile("status|s"); 13 | Pattern quitPattern = Pattern.compile("quit|q"); 14 | 15 | static TerminalCommand create(final String s) { 16 | 17 | final Matcher guestMatcher = createGuestPattern.matcher(s); 18 | if (guestMatcher.matches()) { 19 | 20 | final String countGroup = guestMatcher.group(1); 21 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 22 | 23 | final String coffeeGroup = guestMatcher.group(2); 24 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 25 | 26 | final String maxCoffeeCountGroup = guestMatcher.group(3); 27 | final int maxCoffeeCount = 28 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 29 | 30 | return new TerminalCommand.Guest(count, coffee, maxCoffeeCount); 31 | } 32 | if (getStatusPattern.matcher(s).matches()) return TerminalCommand.Status.Instance; 33 | if (quitPattern.matcher(s).matches()) return TerminalCommand.Quit.Instance; 34 | return new TerminalCommand.Unknown(s); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /exercise_013_Faulty_waiter/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | public interface Terminal { 10 | 11 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 12 | Pattern getStatusPattern = Pattern.compile("status|s"); 13 | Pattern quitPattern = Pattern.compile("quit|q"); 14 | 15 | static TerminalCommand create(final String s) { 16 | 17 | final Matcher guestMatcher = createGuestPattern.matcher(s); 18 | if (guestMatcher.matches()) { 19 | 20 | final String countGroup = guestMatcher.group(1); 21 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 22 | 23 | final String coffeeGroup = guestMatcher.group(2); 24 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 25 | 26 | final String maxCoffeeCountGroup = guestMatcher.group(3); 27 | final int maxCoffeeCount = 28 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 29 | 30 | return new TerminalCommand.Guest(count, coffee, maxCoffeeCount); 31 | } 32 | if (getStatusPattern.matcher(s).matches()) return TerminalCommand.Status.Instance; 33 | if (quitPattern.matcher(s).matches()) return TerminalCommand.Quit.Instance; 34 | return new TerminalCommand.Unknown(s); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /exercise_016_Use_router/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | public interface Terminal { 10 | 11 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 12 | Pattern getStatusPattern = Pattern.compile("status|s"); 13 | Pattern quitPattern = Pattern.compile("quit|q"); 14 | 15 | static TerminalCommand create(final String s) { 16 | 17 | final Matcher guestMatcher = createGuestPattern.matcher(s); 18 | if (guestMatcher.matches()) { 19 | 20 | final String countGroup = guestMatcher.group(1); 21 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 22 | 23 | final String coffeeGroup = guestMatcher.group(2); 24 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 25 | 26 | final String maxCoffeeCountGroup = guestMatcher.group(3); 27 | final int maxCoffeeCount = 28 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 29 | 30 | return new TerminalCommand.Guest(count, coffee, maxCoffeeCount); 31 | } 32 | if (getStatusPattern.matcher(s).matches()) return TerminalCommand.Status.Instance; 33 | if (quitPattern.matcher(s).matches()) return TerminalCommand.Quit.Instance; 34 | return new TerminalCommand.Unknown(s); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /exercise_000_Initial_state/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_000_Initial_state/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_003_Message_actor/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_003_Message_actor/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_004_Use_sender/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_004_Use_sender/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_005_Child_actors/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_005_Child_actors/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_006_Actor_state/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_006_Actor_state/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_007_Use_scheduler/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_007_Use_scheduler/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_008_Busy_actor/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_008_Busy_actor/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_009_Stop_actor/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_009_Stop_actor/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_011_Faulty_guest/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_011_Faulty_guest/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_013_Faulty_waiter/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_014_Self_healing/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_014_Self_healing/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_016_Use_router/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_016_Use_router/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_001_Implement_actor/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_002_Top_level_actor/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_002_Top_level_actor/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_012_Custom_supervision/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_012_Custom_supervision/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_004_Use_sender/src/main/java/com/lightbend/training/coffeehouse/CoffeeHouse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | 5 | package com.lightbend.training.coffeehouse; 6 | 7 | import akka.actor.AbstractLoggingActor; 8 | import akka.actor.Props; 9 | 10 | public class CoffeeHouse extends AbstractLoggingActor { 11 | 12 | public CoffeeHouse() { 13 | log().debug("CoffeeHouse Open"); 14 | } 15 | 16 | @Override 17 | public Receive createReceive() { 18 | return receiveBuilder(). 19 | matchAny(o -> log().info("Coffee Brewing")).build(); 20 | } 21 | 22 | public static Props props() { 23 | return Props.create(CoffeeHouse.class, CoffeeHouse::new); 24 | } 25 | } 26 | 27 | ////=========================================================================== 28 | //// ANSWER 29 | ////=========================================================================== 30 | //import akka.actor.AbstractLoggingActor; 31 | //import akka.actor.Props; 32 | // 33 | // public class CoffeeHouse extends AbstractLoggingActor { 34 | // 35 | // public CoffeeHouse() { 36 | // log().debug("CoffeeHouse Open"); 37 | // } 38 | // 39 | // // @todo Instead of logging "Coffee Brewing", respond to the getSender() 40 | // @Override 41 | // public Receive createReceive() { 42 | // return receiveBuilder(). 43 | // matchAny(o -> getSender().tell("Coffee is really really Brewing and it is hot", getSelf())).build(); 44 | // } 45 | // 46 | // public static Props props() { 47 | // return Props.create(CoffeeHouse.class, CoffeeHouse::new); 48 | // } 49 | // } 50 | -------------------------------------------------------------------------------- /exercise_010_Lifecycle_monitoring/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_010_Lifecycle_monitoring/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | public class TerminalTest { 8 | 9 | @Test 10 | public void shouldCreateCorrectGuestFromCommand() { 11 | assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 12 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 15 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 16 | } 17 | 18 | @Test 19 | public void shouldCreateGetStatusFromCommand() { 20 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 21 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 22 | 23 | } 24 | 25 | @Test 26 | public void shouldCreateQuitFromCommand() { 27 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 28 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 29 | } 30 | 31 | @Test 32 | public void shouldCreateUnknownFromCommand() { 33 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /exercise_013_Faulty_waiter/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.junit.Test; 5 | 6 | import static com.lightbend.training.coffeehouse.Coffee.*; 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Coffee.Akkaccino(), new CaffeJava(), new Coffee.MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | assertThat(order("A")).isEqualTo(new Akkaccino()); 21 | assertThat(order("a")).isEqualTo(new Akkaccino()); 22 | assertThat(order("C")).isEqualTo(new CaffeJava()); 23 | assertThat(order("c")).isEqualTo(new CaffeJava()); 24 | assertThat(order("M")).isEqualTo(new MochaPlay()); 25 | assertThat(order("m")).isEqualTo(new MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_015_Detect_bottleneck/src/test/java/com/lightbend/training/coffeehouse/TerminalTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import org.assertj.core.api.Assertions; 4 | import org.junit.Test; 5 | 6 | import static org.assertj.core.api.Assertions.assertThat; 7 | 8 | public class TerminalTest { 9 | 10 | @Test 11 | public void shouldCreateCorrectGuestFromCommand() { 12 | Assertions.assertThat(Terminal.create("guest")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 13 | assertThat(Terminal.create("2 g")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.Akkaccino(), Integer.MAX_VALUE)); 14 | assertThat(Terminal.create("g m")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.MochaPlay(), Integer.MAX_VALUE)); 15 | assertThat(Terminal.create("g 1")).isEqualTo(new TerminalCommand.Guest(1, new Coffee.Akkaccino(), 1)); 16 | assertThat(Terminal.create("2 g m 1")).isEqualTo(new TerminalCommand.Guest(2, new Coffee.MochaPlay(), 1)); 17 | } 18 | 19 | @Test 20 | public void shouldCreateGetStatusFromCommand() { 21 | assertThat(Terminal.create("status")).isEqualTo(TerminalCommand.Status.Instance); 22 | assertThat(Terminal.create("s")).isEqualTo(TerminalCommand.Status.Instance); 23 | 24 | } 25 | 26 | @Test 27 | public void shouldCreateQuitFromCommand() { 28 | assertThat(Terminal.create("quit")).isEqualTo(TerminalCommand.Quit.Instance); 29 | assertThat(Terminal.create("q")).isEqualTo(TerminalCommand.Quit.Instance); 30 | } 31 | 32 | @Test 33 | public void shouldCreateUnknownFromCommand() { 34 | assertThat(Terminal.create("foo")).isEqualTo(new TerminalCommand.Unknown("foo")); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /exercise_015_Detect_bottleneck/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import com.lightbend.training.coffeehouse.Coffee.*; 5 | import org.assertj.core.api.Assertions; 6 | import org.junit.Test; 7 | 8 | import static com.lightbend.training.coffeehouse.Coffee.*; 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | import static org.assertj.core.api.Assertions.fail; 11 | 12 | public class CoffeeTest { 13 | 14 | @Test 15 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 16 | Assertions.assertThat(COFFEES).isEqualTo(ImmutableSet.of( 17 | new Akkaccino(), new CaffeJava(), new MochaPlay())); 18 | } 19 | 20 | @Test 21 | public void orderShouldCreateCorrectBeverageForGivenCode() { 22 | assertThat(order("A")).isEqualTo(new Akkaccino()); 23 | assertThat(order("a")).isEqualTo(new Akkaccino()); 24 | assertThat(order("C")).isEqualTo(new CaffeJava()); 25 | assertThat(order("c")).isEqualTo(new CaffeJava()); 26 | assertThat(order("M")).isEqualTo(new MochaPlay()); 27 | assertThat(order("m")).isEqualTo(new MochaPlay()); 28 | } 29 | 30 | @Test 31 | public void orderShouldThrowExceptionForWrongBeverageCode() { 32 | try { 33 | order("1"); 34 | fail("Should have raised exception for invalid order code"); 35 | } catch (Exception e) { 36 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 37 | } 38 | } 39 | 40 | @Test 41 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 42 | COFFEES.forEach(c -> assertThat(orderOther(c)).isNotEqualTo(c)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /exercise_007_Use_scheduler/README.md: -------------------------------------------------------------------------------- 1 | use-scheduler 2 | 3 | # Exercise 7 > Use Scheduler 4 | 5 | In this exercise, we will implement the Akka `Scheduler` to simulate the `Guest` ordering more `Coffee`. 6 | 7 | - Change `Guest` as follows: 8 | - Add a `finishCoffeeDuration` parameter of type `scala.concurrent.duration.FiniteDuration`. 9 | - Change the behavior on receiving `CoffeeServed` to schedule the sending of `CoffeeFinished` to the `Guest`. 10 | - QUIZ: What other changes are needed for the guest to enjoy their coffee? 11 | - Change `CoffeeHouse` as follows: 12 | - Adjust the code for creating a new `Guest`. 13 | - For `finishCoffeeDuration`, use a configuration value with key `coffee-house.guest.finish-coffee-duration`. 14 | - To get the configuration value, use the `getDuration` method on `context().system().settings().config()`. 15 | - **HINT**: Use `scala.concurrent.duration.Duration.create(long, TimeUnit)` to create `FiniteDuration`. 16 | - Change the `src/main/resource/application.conf` as follows: 17 | - Add a section for `coffee-house` with `guest` that has the `finish-coffee-duration` property. 18 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 19 | - Attention: 20 | - Enter `g {coffee}` or `guest {coffee}` where {coffee} must be one of the defined coffees (`a`, `m`, or `c`). 21 | - If you omit {coffee}, `Akkaccino` will be used by default. 22 | - `CoffeeHouse Open` is logged to `coffee-house.log`. 23 | - Lifecycle debug messages are logged to `coffee-house.log`. 24 | - Make sure the correct number of `Guest` creations were logged. 25 | - Make sure the guests are enjoying their `yummy` coffee. 26 | - Use the `test` command to verify the solution works as expected. 27 | - Use the `next` command to move to the next exercise. -------------------------------------------------------------------------------- /exercise_007_Use_scheduler/src/test/resources/README.md: -------------------------------------------------------------------------------- 1 | use-scheduler 2 | 3 | # Exercise 6 > Use Scheduler 4 | 5 | In this exercise, we will implement the Akka `Scheduler` to simulate the `Guest` ordering more `Coffee`. 6 | 7 | - Change `Guest` as follows: 8 | - Add a `finishCoffeeDuration` parameter of type `scala.concurrent.duration.FiniteDuration`. 9 | - Change the behavior on receiving `CoffeeServed` to schedule the sending of `CoffeeFinished` to the `Guest`. 10 | - QUIZ: What other changes are needed for the guest to enjoy their coffee? 11 | - Change `CoffeeHouse` as follows: 12 | - Adjust the code for creating a new `Guest`. 13 | - For `finishCoffeeDuration`, use a configuration value with key `coffee-house.guest.finish-coffee-duration`. 14 | - To get the configuration value, use the `getDuration` method on `context().system().settings().config()`. 15 | - **HINT**: Use `scala.concurrent.duration.Duration.create(long, TimeUnit)` to create `FiniteDuration`. 16 | - Change the `src/main/resource/application.conf` as follows: 17 | - Add a section for `coffee-house` with `guest` that has the `finish-coffee-duration` property. 18 | - Use the `run` command to boot the `CoffeeHouseApp` and verify: 19 | - Attention: 20 | - Enter `g {coffee}` or `guest {coffee}` where {coffee} must be one of the defined coffees (`a`, `m`, or `c`). 21 | - If you omit {coffee}, `Akkaccino` will be used by default. 22 | - `CoffeeHouse Open` is logged to `coffee-house.log`. 23 | - Lifecycle debug messages are logged to `coffee-house.log`. 24 | - Make sure the correct number of `Guest` creations were logged. 25 | - Make sure the guests are enjoying their `yummy` coffee. 26 | - Use the `test` command to verify the solution works as expected. 27 | - Use the `koan next` command to move to the next exercise. 28 | -------------------------------------------------------------------------------- /exercise_001_Implement_actor/src/test/java/com/lightbend/training/coffeehouse/CoffeeTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import org.assertj.core.api.Assertions; 5 | import org.junit.Test; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.assertj.core.api.Assertions.fail; 9 | 10 | public class CoffeeTest { 11 | 12 | @Test 13 | public void coffeesShouldContains_AkkaccinoCaffeJavaAndMochaPlay() { 14 | assertThat(Coffee.COFFEES).isEqualTo(ImmutableSet.of( 15 | new Coffee.Akkaccino(), new Coffee.CaffeJava(), new Coffee.MochaPlay())); 16 | } 17 | 18 | @Test 19 | public void orderShouldCreateCorrectBeverageForGivenCode() { 20 | Assertions.assertThat(Coffee.order("A")).isEqualTo(new Coffee.Akkaccino()); 21 | Assertions.assertThat(Coffee.order("a")).isEqualTo(new Coffee.Akkaccino()); 22 | Assertions.assertThat(Coffee.order("C")).isEqualTo(new Coffee.CaffeJava()); 23 | Assertions.assertThat(Coffee.order("c")).isEqualTo(new Coffee.CaffeJava()); 24 | Assertions.assertThat(Coffee.order("M")).isEqualTo(new Coffee.MochaPlay()); 25 | Assertions.assertThat(Coffee.order("m")).isEqualTo(new Coffee.MochaPlay()); 26 | } 27 | 28 | @Test 29 | public void orderShouldThrowExceptionForWrongBeverageCode() { 30 | try { 31 | Coffee.order("1"); 32 | fail("Should have raised exception for invalid order code"); 33 | } catch (Exception e) { 34 | assertThat(e).isExactlyInstanceOf(IllegalArgumentException.class); 35 | } 36 | } 37 | 38 | @Test 39 | public void otherDrinkShouldReturnDrinkDifferentFromGivenCode() { 40 | Coffee.COFFEES.forEach(c -> Assertions.assertThat(Coffee.orderOther(c)).isNotEqualTo(c)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /exercise_004_Use_sender/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import com.lightbend.training.coffeehouse.TerminalCommand.Guest; 7 | import com.lightbend.training.coffeehouse.TerminalCommand.Quit; 8 | import com.lightbend.training.coffeehouse.TerminalCommand.Status; 9 | import com.lightbend.training.coffeehouse.TerminalCommand.Unknown; 10 | 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | 14 | public interface Terminal { 15 | 16 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 17 | Pattern getStatusPattern = Pattern.compile("status|s"); 18 | Pattern quitPattern = Pattern.compile("quit|q"); 19 | 20 | static TerminalCommand create(final String s) { 21 | 22 | final Matcher guestMatcher = createGuestPattern.matcher(s); 23 | if (guestMatcher.matches()) { 24 | 25 | final String countGroup = guestMatcher.group(1); 26 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 27 | 28 | final String coffeeGroup = guestMatcher.group(2); 29 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 30 | 31 | final String maxCoffeeCountGroup = guestMatcher.group(3); 32 | final int maxCoffeeCount = 33 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 34 | 35 | return new Guest(count, coffee, maxCoffeeCount); 36 | } 37 | if (getStatusPattern.matcher(s).matches()) return Status.Instance; 38 | if (quitPattern.matcher(s).matches()) return Quit.Instance; 39 | return new Unknown(s); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /exercise_006_Actor_state/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import com.lightbend.training.coffeehouse.TerminalCommand.Guest; 7 | import com.lightbend.training.coffeehouse.TerminalCommand.Quit; 8 | import com.lightbend.training.coffeehouse.TerminalCommand.Status; 9 | import com.lightbend.training.coffeehouse.TerminalCommand.Unknown; 10 | 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | 14 | public interface Terminal { 15 | 16 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 17 | Pattern getStatusPattern = Pattern.compile("status|s"); 18 | Pattern quitPattern = Pattern.compile("quit|q"); 19 | 20 | static TerminalCommand create(final String s) { 21 | 22 | final Matcher guestMatcher = createGuestPattern.matcher(s); 23 | if (guestMatcher.matches()) { 24 | 25 | final String countGroup = guestMatcher.group(1); 26 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 27 | 28 | final String coffeeGroup = guestMatcher.group(2); 29 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 30 | 31 | final String maxCoffeeCountGroup = guestMatcher.group(3); 32 | final int maxCoffeeCount = 33 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 34 | 35 | return new Guest(count, coffee, maxCoffeeCount); 36 | } 37 | if (getStatusPattern.matcher(s).matches()) return Status.Instance; 38 | if (quitPattern.matcher(s).matches()) return Quit.Instance; 39 | return new Unknown(s); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /exercise_009_Stop_actor/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import com.lightbend.training.coffeehouse.TerminalCommand.Guest; 7 | import com.lightbend.training.coffeehouse.TerminalCommand.Quit; 8 | import com.lightbend.training.coffeehouse.TerminalCommand.Status; 9 | import com.lightbend.training.coffeehouse.TerminalCommand.Unknown; 10 | 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | 14 | public interface Terminal { 15 | 16 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 17 | Pattern getStatusPattern = Pattern.compile("status|s"); 18 | Pattern quitPattern = Pattern.compile("quit|q"); 19 | 20 | static TerminalCommand create(final String s) { 21 | 22 | final Matcher guestMatcher = createGuestPattern.matcher(s); 23 | if (guestMatcher.matches()) { 24 | 25 | final String countGroup = guestMatcher.group(1); 26 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 27 | 28 | final String coffeeGroup = guestMatcher.group(2); 29 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 30 | 31 | final String maxCoffeeCountGroup = guestMatcher.group(3); 32 | final int maxCoffeeCount = 33 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 34 | 35 | return new Guest(count, coffee, maxCoffeeCount); 36 | } 37 | if (getStatusPattern.matcher(s).matches()) return Status.Instance; 38 | if (quitPattern.matcher(s).matches()) return Quit.Instance; 39 | return new Unknown(s); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /exercise_011_Faulty_guest/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import com.lightbend.training.coffeehouse.TerminalCommand.Guest; 7 | import com.lightbend.training.coffeehouse.TerminalCommand.Quit; 8 | import com.lightbend.training.coffeehouse.TerminalCommand.Status; 9 | import com.lightbend.training.coffeehouse.TerminalCommand.Unknown; 10 | 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | 14 | public interface Terminal { 15 | 16 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 17 | Pattern getStatusPattern = Pattern.compile("status|s"); 18 | Pattern quitPattern = Pattern.compile("quit|q"); 19 | 20 | static TerminalCommand create(final String s) { 21 | 22 | final Matcher guestMatcher = createGuestPattern.matcher(s); 23 | if (guestMatcher.matches()) { 24 | 25 | final String countGroup = guestMatcher.group(1); 26 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 27 | 28 | final String coffeeGroup = guestMatcher.group(2); 29 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 30 | 31 | final String maxCoffeeCountGroup = guestMatcher.group(3); 32 | final int maxCoffeeCount = 33 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 34 | 35 | return new Guest(count, coffee, maxCoffeeCount); 36 | } 37 | if (getStatusPattern.matcher(s).matches()) return Status.Instance; 38 | if (quitPattern.matcher(s).matches()) return Quit.Instance; 39 | return new Unknown(s); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /exercise_014_Self_healing/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import com.lightbend.training.coffeehouse.TerminalCommand.Guest; 7 | import com.lightbend.training.coffeehouse.TerminalCommand.Quit; 8 | import com.lightbend.training.coffeehouse.TerminalCommand.Status; 9 | import com.lightbend.training.coffeehouse.TerminalCommand.Unknown; 10 | 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | 14 | public interface Terminal { 15 | 16 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 17 | Pattern getStatusPattern = Pattern.compile("status|s"); 18 | Pattern quitPattern = Pattern.compile("quit|q"); 19 | 20 | static TerminalCommand create(final String s) { 21 | 22 | final Matcher guestMatcher = createGuestPattern.matcher(s); 23 | if (guestMatcher.matches()) { 24 | 25 | final String countGroup = guestMatcher.group(1); 26 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 27 | 28 | final String coffeeGroup = guestMatcher.group(2); 29 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 30 | 31 | final String maxCoffeeCountGroup = guestMatcher.group(3); 32 | final int maxCoffeeCount = 33 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 34 | 35 | return new Guest(count, coffee, maxCoffeeCount); 36 | } 37 | if (getStatusPattern.matcher(s).matches()) return Status.Instance; 38 | if (quitPattern.matcher(s).matches()) return Quit.Instance; 39 | return new Unknown(s); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /exercise_001_Implement_actor/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import com.lightbend.training.coffeehouse.TerminalCommand.Guest; 7 | import com.lightbend.training.coffeehouse.TerminalCommand.Quit; 8 | import com.lightbend.training.coffeehouse.TerminalCommand.Status; 9 | import com.lightbend.training.coffeehouse.TerminalCommand.Unknown; 10 | 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | 14 | public interface Terminal { 15 | 16 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 17 | Pattern getStatusPattern = Pattern.compile("status|s"); 18 | Pattern quitPattern = Pattern.compile("quit|q"); 19 | 20 | static TerminalCommand create(final String s) { 21 | 22 | final Matcher guestMatcher = createGuestPattern.matcher(s); 23 | if (guestMatcher.matches()) { 24 | 25 | final String countGroup = guestMatcher.group(1); 26 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 27 | 28 | final String coffeeGroup = guestMatcher.group(2); 29 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 30 | 31 | final String maxCoffeeCountGroup = guestMatcher.group(3); 32 | final int maxCoffeeCount = 33 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 34 | 35 | return new Guest(count, coffee, maxCoffeeCount); 36 | } 37 | if (getStatusPattern.matcher(s).matches()) return Status.Instance; 38 | if (quitPattern.matcher(s).matches()) return Quit.Instance; 39 | return new Unknown(s); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /exercise_002_Top_level_actor/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import com.lightbend.training.coffeehouse.TerminalCommand.Guest; 7 | import com.lightbend.training.coffeehouse.TerminalCommand.Quit; 8 | import com.lightbend.training.coffeehouse.TerminalCommand.Status; 9 | import com.lightbend.training.coffeehouse.TerminalCommand.Unknown; 10 | 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | 14 | public interface Terminal { 15 | 16 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 17 | Pattern getStatusPattern = Pattern.compile("status|s"); 18 | Pattern quitPattern = Pattern.compile("quit|q"); 19 | 20 | static TerminalCommand create(final String s) { 21 | 22 | final Matcher guestMatcher = createGuestPattern.matcher(s); 23 | if (guestMatcher.matches()) { 24 | 25 | final String countGroup = guestMatcher.group(1); 26 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 27 | 28 | final String coffeeGroup = guestMatcher.group(2); 29 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 30 | 31 | final String maxCoffeeCountGroup = guestMatcher.group(3); 32 | final int maxCoffeeCount = 33 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 34 | 35 | return new Guest(count, coffee, maxCoffeeCount); 36 | } 37 | if (getStatusPattern.matcher(s).matches()) return Status.Instance; 38 | if (quitPattern.matcher(s).matches()) return Quit.Instance; 39 | return new Unknown(s); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /exercise_012_Custom_supervision/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import com.lightbend.training.coffeehouse.TerminalCommand.Guest; 7 | import com.lightbend.training.coffeehouse.TerminalCommand.Quit; 8 | import com.lightbend.training.coffeehouse.TerminalCommand.Status; 9 | import com.lightbend.training.coffeehouse.TerminalCommand.Unknown; 10 | 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | 14 | public interface Terminal { 15 | 16 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 17 | Pattern getStatusPattern = Pattern.compile("status|s"); 18 | Pattern quitPattern = Pattern.compile("quit|q"); 19 | 20 | static TerminalCommand create(final String s) { 21 | 22 | final Matcher guestMatcher = createGuestPattern.matcher(s); 23 | if (guestMatcher.matches()) { 24 | 25 | final String countGroup = guestMatcher.group(1); 26 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 27 | 28 | final String coffeeGroup = guestMatcher.group(2); 29 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 30 | 31 | final String maxCoffeeCountGroup = guestMatcher.group(3); 32 | final int maxCoffeeCount = 33 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 34 | 35 | return new Guest(count, coffee, maxCoffeeCount); 36 | } 37 | if (getStatusPattern.matcher(s).matches()) return Status.Instance; 38 | if (quitPattern.matcher(s).matches()) return Quit.Instance; 39 | return new Unknown(s); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /exercise_015_Detect_bottleneck/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import com.lightbend.training.coffeehouse.TerminalCommand.Guest; 7 | import com.lightbend.training.coffeehouse.TerminalCommand.Quit; 8 | import com.lightbend.training.coffeehouse.TerminalCommand.Status; 9 | import com.lightbend.training.coffeehouse.TerminalCommand.Unknown; 10 | 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | 14 | public interface Terminal { 15 | 16 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 17 | Pattern getStatusPattern = Pattern.compile("status|s"); 18 | Pattern quitPattern = Pattern.compile("quit|q"); 19 | 20 | static TerminalCommand create(final String s) { 21 | 22 | final Matcher guestMatcher = createGuestPattern.matcher(s); 23 | if (guestMatcher.matches()) { 24 | 25 | final String countGroup = guestMatcher.group(1); 26 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 27 | 28 | final String coffeeGroup = guestMatcher.group(2); 29 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 30 | 31 | final String maxCoffeeCountGroup = guestMatcher.group(3); 32 | final int maxCoffeeCount = 33 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 34 | 35 | return new Guest(count, coffee, maxCoffeeCount); 36 | } 37 | if (getStatusPattern.matcher(s).matches()) return Status.Instance; 38 | if (quitPattern.matcher(s).matches()) return Quit.Instance; 39 | return new Unknown(s); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /exercise_003_Message_actor/src/test/java/com/lightbend/training/coffeehouse/CoffeeHouseAppTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | 4 | import akka.actor.ActorRef; 5 | import akka.testkit.JavaTestKit; 6 | import org.assertj.core.data.MapEntry; 7 | import org.junit.Test; 8 | 9 | import java.util.Arrays; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | 15 | public class CoffeeHouseAppTest extends BaseAkkaTestCase { 16 | 17 | @Test 18 | public void argsToOptsShouldConvertArgsToOpts() { 19 | final Map result = CoffeeHouseApp.argsToOpts(Arrays.asList("a=1", "b", "-Dc=2")); 20 | assertThat(result).contains(MapEntry.entry("a", "1"), MapEntry.entry("-Dc", "2")); 21 | } 22 | 23 | 24 | @Test 25 | public void applySystemPropertiesShouldConvertOptsToSystemProps() { 26 | System.setProperty("c", ""); 27 | Map opts = new HashMap<>(); 28 | opts.put("a", "1"); 29 | opts.put("-Dc", "2"); 30 | CoffeeHouseApp.applySystemProperties(opts); 31 | assertThat(System.getProperty("c")).isEqualTo("2"); 32 | } 33 | 34 | @Test 35 | public void shouldCreateATopLevelActorCalledCoffeeHouse() { 36 | new JavaTestKit(system) {{ 37 | new CoffeeHouseApp(system); 38 | String path = "/user/coffee-house"; 39 | expectActor(this, path); 40 | }}; 41 | } 42 | 43 | @Test 44 | public void shouldSendMessageToCoffeeHouseAfterCreation() { 45 | new JavaTestKit(system) {{ 46 | new CoffeeHouseApp(system) { 47 | @Override 48 | protected ActorRef createCoffeeHouse() { 49 | return getRef(); 50 | } 51 | }; 52 | expectMsgClass(Object.class); 53 | }}; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /exercise_010_Lifecycle_monitoring/src/main/java/com/lightbend/training/coffeehouse/Terminal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014, 2015 Typesafe, Inc. All rights reserved. [http://www.typesafe.com] 3 | */ 4 | package com.lightbend.training.coffeehouse; 5 | 6 | import com.lightbend.training.coffeehouse.TerminalCommand.Guest; 7 | import com.lightbend.training.coffeehouse.TerminalCommand.Quit; 8 | import com.lightbend.training.coffeehouse.TerminalCommand.Status; 9 | import com.lightbend.training.coffeehouse.TerminalCommand.Unknown; 10 | 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | 14 | public interface Terminal { 15 | 16 | Pattern createGuestPattern = Pattern.compile("(\\d+)?\\s*(?:guest|g)\\s*(A|a|M|m|C|c)?\\s*(\\d+)?"); 17 | Pattern getStatusPattern = Pattern.compile("status|s"); 18 | Pattern quitPattern = Pattern.compile("quit|q"); 19 | 20 | static TerminalCommand create(final String s) { 21 | 22 | final Matcher guestMatcher = createGuestPattern.matcher(s); 23 | if (guestMatcher.matches()) { 24 | 25 | final String countGroup = guestMatcher.group(1); 26 | final int count = countGroup != null ? Integer.parseInt(countGroup) : 1; 27 | 28 | final String coffeeGroup = guestMatcher.group(2); 29 | final Coffee coffee = coffeeGroup != null ? Coffee.order(coffeeGroup) : new Coffee.Akkaccino(); 30 | 31 | final String maxCoffeeCountGroup = guestMatcher.group(3); 32 | final int maxCoffeeCount = 33 | maxCoffeeCountGroup != null ? Integer.parseInt(maxCoffeeCountGroup) : Integer.MAX_VALUE; 34 | 35 | return new Guest(count, coffee, maxCoffeeCount); 36 | } 37 | if (getStatusPattern.matcher(s).matches()) return Status.Instance; 38 | if (quitPattern.matcher(s).matches()) return Quit.Instance; 39 | return new Unknown(s); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /exercise_013_Faulty_waiter/src/test/java/com/lightbend/training/coffeehouse/WaiterTest.java: -------------------------------------------------------------------------------- 1 | package com.lightbend.training.coffeehouse; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.testkit.JavaTestKit; 5 | import akka.testkit.TestProbe; 6 | import org.junit.Test; 7 | 8 | public class WaiterTest extends BaseAkkaTestCase { 9 | 10 | @Test 11 | public void sendingServeCoffeeShouldResultInApproveCoffeeToCoffeeHouse() { 12 | new JavaTestKit(system) {{ 13 | ActorRef coffeeHouse = getRef(); 14 | TestProbe guest = new TestProbe(system); 15 | ActorRef waiter = system.actorOf(Waiter.props(coffeeHouse, system.deadLetters(), Integer.MAX_VALUE)); 16 | waiter.tell(new Waiter.ServeCoffee(new Coffee.Akkaccino()), guest.ref()); 17 | expectMsgEquals(new CoffeeHouse.ApproveCoffee(new Coffee.Akkaccino(), guest.ref())); 18 | }}; 19 | } 20 | 21 | @Test 22 | public void sendingComplaintShouldResultInPrepareCoffeeToBarista() { 23 | new JavaTestKit(system) {{ 24 | ActorRef barista = getRef(); 25 | TestProbe guest = new TestProbe(system); 26 | ActorRef waiter = system.actorOf(Waiter.props(system.deadLetters(), barista, 1)); 27 | 28 | waiter.tell(new Waiter.Complaint(new Coffee.Akkaccino()), guest.ref()); 29 | expectMsgEquals(new Barista.PrepareCoffee(new Coffee.Akkaccino(), guest.ref())); 30 | }}; 31 | } 32 | 33 | @Test 34 | public void shouldThrowFrustratedExceptionWhenMaxComplaintReached() { 35 | new JavaTestKit(system) {{ 36 | ActorRef waiter = system.actorOf(Waiter.props(system.deadLetters(), system.deadLetters(), 0)); 37 | eventFilter(this, Waiter.FrustratedException.class, "", 1, () -> { 38 | waiter.tell(new Waiter.Complaint(new Coffee.Akkaccino()), ActorRef.noSender()); 39 | }); 40 | }}; 41 | } 42 | } 43 | --------------------------------------------------------------------------------