Phase II¶
Lottery Domain Module¶
‘Create Lottery’ Command¶
- Add a domain module in Lottery.ksmile
Lottery.ksmile
domain-module LotteryDomain at com.metastay.lotterydomain
- $smile
- Refresh Eclipse to see LotteryDomain.kdomain
- Add Lottery.create Command
LotteryDomain.kdomain
domain Lottery {
function lotteryNameExists(lotteryName:String):Boolean
}
aggregate Lottery {
domain-ref lottery:Lottery
command create {
input(lotteryName:String, amount:Int)
pre {
require NewLotteryName => !(lottery.lotteryNameExists(input.lotteryName)) failing "Lottery name already exists!"
}
}
}
- $compile
- Open LotteryAggregateCode to save it to implement.
Warning
LotteryWriter and other mongo related files not available to implement because LotteryDomain is not dependent on LotteryMongo.
- Add the LotteryMongo dependency in LotteryDomain in Lottery.ksmile file
Lottery.ksmile
group Lottery {
mongo-module LotteryMongo at com.metastay.lotterymongo
domain-module LotteryDomain(LotteryMongo) at com.metastay.lotterydomain
play-module LotteryPlay(LotteryMongo) at lotteryplay
}
- $smile
- Open LotteryAggregateCode to implement create command as below.
LotteryAggregateCode.scala
override def create = CreateCommand {
import CreateCommand._;
input: Input =>
LotteryWriter().save(LotteryRow(lotteryName = input.lotteryName, amount = input.amount, open = false))
}
* Open LotteryDomainCode to implement lotteryNameExists method as below
.. code-block:: scala
LotteryDomainCode
override def lotteryNameExists (lotteryName:String):Boolean = LotteryQuery().lotteryName.is(lotteryName).exists
- $compile
- Write test in LotteryDomainTestSuite as below.
LotteryDomainTestSuite
test("create", Tag("create")) {
val lotteryAggregate = grab[LotteryAggregate]
lotteryAggregate.create("WBLoto", 20000).println;
}
- $project LotteryDomain
- $test-only com.metastay.lotterydomain.LotteryDomainTestSuite – -n create
- Check in DB if the WBLoto Lottery has been created
‘Add Participant’ And ‘Run’Command¶
Adding two more commands.
LotteryDomain.kdomain
domain Lottery {
function lotteryNameExists(lotteryName:String):Boolean
function participantExist(lotteryName:String, participantName:String):Boolean
function participantCount(lotteryName:String):Int
}
aggregate Lottery {
domain-ref lottery:Lottery
command create {
input(lotteryName:String, amount:Int)
pre {
require NewLotteryName => !(lottery.lotteryNameExists(input.lotteryName)) failing "Lottery name already exists!"
}
}
command addParticipant {
input(lotteryName:String, participantName:String)
pre {
require lotteryMustExists "Lottery must exist" => lottery.lotteryNameExists(input.lotteryName)
require particpantNotYetAdded "Participant Not yet added" => !lottery.participantExist(input.lotteryName, input.participantName)
}
}
command run {
input(lotteryName:String)
pre {
require ExistingLotteryName => lottery.lotteryNameExists(input.lotteryName) failing "Lottery name does not exists"
require atLeastTwoParticipants => ExistingLotteryName -> `domainRef.lottery.participantCount(input.lotteryName) > 1` failing "The lottery does not have any participant!"
}
output(winner:String)
}
}
- $compile
- Implementing addParticipant() and run() in LotteryAggregateCode
LotteryAggregateCode.scala
class LotteryAggregateCode(domainRef: DomainRef) extends LotteryAggregateCommands {
override def create = CreateCommand {
import CreateCommand._;
input: Input =>
LotteryWriter().save(LotteryRow(lotteryName = input.lotteryName, amount = input.amount))
}
override def addParticipant = AddParticipantCommand {
import AddParticipantCommand._;
input: Input =>
val q = LotteryQuery().lotteryName.is(input.lotteryName)
val u = LotteryUpdate().participantList.addToSet(input.participantName)
LotteryWriter().updateOne(q, u)
}
override def run = RunCommand {
import RunCommand._;
input: Input =>
val q = LotteryQuery().lotteryName.is(input.lotteryName)
val participantList = q.findOne.get.participantList //To find the participantList
val winnerIndex = scala.util.Random.nextInt(participantList.size) //To find a winner Index
val winner = participantList(winnerIndex)
val u = LotteryUpdate().winner.set(Some(winner)).open.set(false)
LotteryWriter().updateOne(q, u)
Output(winner)
}
}
- Implementing participantExist() and participantCount() in LotteryDomainCode
LotteryDomainCode.scala
override def lotteryNameExists (lotteryName:String):Boolean = LotteryQuery().lotteryName.equalsIgnoreCase(lotteryName).exists
override def participantExist(lotteryName: String, participantName: String): Boolean = LotteryQuery().lotteryName.is(lotteryName).participantList.contains(participantName).exists
override def participantCount(lotteryName: String): Int = LotteryQuery().lotteryName.is(lotteryName).findOne.get.participantList.size
def lotteryOpen (lotteryName:String):Boolean = (LotteryQuery().lotteryName.is(lotteryName).findOne.get.open)
- Add test for addParticipant and run in RunCommandTestSuite
- $project LoteryDomain
- $test-only com.metastay.lotterydomain.aggregate.lottery.RunCommandTestSuite – -n run
Integrate Play and Domain¶
- Adding all the validations and checks which are available in domain to the rest api.
- Add LotteryDomain as a dependency to LotteryPlay Module rather than LotteryMongo in Lottery.ksmile
Lottery.ksmile
group Lottery {
mongo-module LotteryMongo at com.metastay.lotterymongo
domain-module LotteryDomain(LotteryMongo) at com.metastay.lotterydomain
play-module LotteryPlay(LotteryDomain) at lotteryplay
}
- $smile
- Add the command-action in place of action to link it to command in LotteryPlay.kplay
LotteryPlay.kplay
web-writer Lottery {
command-action createLottery(POST) LotteryDomain::Lottery.create
command-action addParticipant(POST) LotteryDomain::Lottery.addParticipant
command-action run(POST) LotteryDomain::Lottery.run
}
- $compile
- Delete the LotteryWebWriterCode.scala as its not more needed.
- $compile
- test through curl
- curl -H “Content-Type: application/json” -X POST -d ‘{“lotteryName”:”Loto”,”amount”:1000}’ http://localhost:9000/api/lottery/create-lottery
- curl -H “Content-Type: application/json” -X POST -d ‘{“lotteryName”:”Loto”,”participantName”:”John”}’ http://localhost:9000/api/lottery/add-participant
- curl -H “Content-Type: application/json” -X POST -d ‘{“lotteryName”:”Loto”,”participantName”:”Jim”}’ http://localhost:9000/api/lottery/add-participant
- curl -H “Content-Type: application/json” -X POST -d ‘{“lotteryName”:”Loto”,”participantName”:”Joe”}’ http://localhost:9000/api/lottery/add-participant
- curl -H “Content-Type: application/json” -X POST -d ‘{“lotteryName”:”Loto”}’ http://localhost:9000/api/lottery/run
Lottery Vue Module¶
- To create visual access of apis created in play module
- Open Lottery.ksmile
- Edit Lottery.ksmile and insert the below content to create a LotteryVue module Lottery.ksmile
group lottery {
vue-module/0.2 LotteryVue(LotteryPlay) at com.metastay.lotteryvue
}
- $smile
- In Eclipse refresh to see the LotteryVue.kvue
- Edit LotteryVue.kvue to create html files LotteryVue.kvue
route "lottery"
html-fragment Header
html-fragment Footer
html-fragment Home
html-fragment LotteryList
html-fragment CreateLottery
html-fragment LotteryDetails
- $compile
- open html-fragment Header.html under “/LotteryVue/src/com/metastay/lotteryvue/fragment/header.html” headerhtml
- Edit footer.html footerhtml
- Edit home.html homehtml
- Edit lottery-list.html lotterylisthtml
- Edit create_lottery.html,lottery_details.html
- Edit lotteryvue-main.html mainhtml
- Edit lotteryvue-router.js
var routes = [
{ path : '/', redirect: '/home'},
{ path : '/home', name : 'home', component: LotteryVue.Components.Home},
{ path : '/lottery-list', name : 'lotteryList', component: LotteryVue.Components.LotteryList},
{ path : '/create-lottery', name : 'createLottery', component: LotteryVue.Components.CreateLottery},
{ path : '/lottery-details/:lotteryName', name : 'lotteryDetails', component: LotteryVue.Components.LotteryDetails}
]
- Edit lotteryvue-shell.html, add the title as Lottery
- $run and access http://localhost:9000/lottery, go through all the links and they should be access right pages
- Connect with Play (Web Writer and Web Reader) edit LotteryVue.kvue
data LotteryForm (lotteryName:String, amount:Int)
data LotteryDetails (lotteryName:String"{\"link\" : \"lottery-details/:lotteryName\"}", amount:Int, participantList:String* "{\"visible\" :false}", winner:String?, status:String)
bus Lottery {
lotteryListAvailable(lotteryList:LotteryDetails*)
LotteryDetailsAvailable(lotteryDetails:LotteryDetails)
}
actions Lottery{
loadLotteryList
createLottery
loadLotteryDetails
addParticipant
runLottery
}
backend-writer Lottery LotteryPlay::Lottery
backend-reader Lottery LotteryPlay:: Lottery
- $compile
- Edit LotteryActionsCode.scala lotteryActions
- To get a better display of lottery list we need to add buter component to the project
- add-component buter-release-0.1,in ksmile file and follow the guided steps(if any)
- Edit Lottery.ksmile
import-component buter-release-0.1(ButerVue)
vue-module/0.2 LotteryVue(LotteryPlay, ButerVue) at com.metastay.lotteryvue
- $smile
- Edit LotteryVue.kvue and group-ref ButerVue::Buter (next to route)
- $compile
- Edit lottery-list.html improvedLotteryList
- $run
- http://localhost:9000/lottery#/lottery-list will display list of available lotteries.
- edit create-lottery.html improvedCreateLottery
- access the create lottery link and test by creating one lottery
- Edit lottery-details.html improvedLotteryDetails