Let's
all day

Anton Sarov
Spartakiade 2015
About me
Java and Eclipse RCP developer by day
Play Framework developer by night
@duxanton

Workshop PREREQUIREMENTs
- JDK 8
- Play Framework 2.3.x
- IDE (IntelliJ preferred)
it is 2015
- many-core CPUs are here
- everything is distributed
- IoT around the corner
- our traditional approach does not work here
thanks to @elmanu for the slide
and the solution?

functional programming
the actor model
evented server model
(Train station vs. Restaurant)
stateless architecture
functional programming
the actor model
evented server model
stateless architecture



object-oriented and functional programming

interoperability with java

ideas from Erlang and the Actor Model
toolkit and runtime for building highly concurrent, distributed and resilient message-driven applications on the JVM

non-blocking i/o
MVC
everything is compiled
Anatomy
- app
- conf
- project
- public
- test
OUr goal for today
Create a really cool web app GAME
But with some limitations (due to time pressure, like in real life)
rules of the game
- Every 10 seconds the server sends a name of a random city to every connected client
- Clients reply with GPS coordinates of the city (latitude & longitude)
- Score is based on the distance (think Pythagorean Theorem)
- Clients see the answers of the other clients for the current challenge
models, views, CONtrollers
+
Actions & Routes
The ROUTES FILE
# Homepage
GET / controllers.Application.index()
# Display a person
GET /persons/:id controllers.Persons.show(id: Long)task: define the index page (route, action, view)

hint: the action renders the view
views & templates
- Scala-based template engine
- plain HTML(5)
- the magic '@' character
task: define the STArT-game REQUest (route, action)

hints: no view needed, results.todo
"server sends [...] to connected clients and clients reply"
two-way http connection
task: define A Websocket-endpoint (route, action)

who handles the Websocket connection?
an akka actor!
main task: define actors for different tasks ...

task: define an actor for handling the websocket connection

task: define an actor serving the game

task: define an actor for checking the answers

task: define an actor for handling the score counting

task: Start the actors at the appropriate time

let's rest
task: create a REst api for the scores
hints:
define request patterns in the routes file
implement the logic in the controller (and elsewhere, if needed)

task: update index view to include game controls


task: update main view with angularjs, bootstrap and leaflet

angularjs
-
data binding
-
directives
-
backend
let us be javascript ninjas!
angularjs
var app = angular.module('app', ['leaflet-directive']);
app.factory('MyService', function($rootScope) {
var mService = {};
mService.connection = {};
mService.connect = function() {
$rootScope.wsUri = "ws://localhost:9000/ws";
var ws = new WebSocket ( $rootScope.wsUri ) ;
ws.onopen = function ( ) {
mService.connection = ws;
}
ws.onmessage = function ( event ) {
$rootScope.$apply(function() {
if (JSON.parse(event.data).action!=null) {
mService.messages.push ( JSON.parse(event.data) ) ;
} else {
mService.city = JSON.parse(event.data);
mService.messages = [];
}
});
}
};
mService.postMsg = function(data) {
mService.connection.send(data);
};
mService.messages = [];
mService.city = "";
return mService;
});application.js:
angularjs
app.controller('MainCtrl', function($scope, MyService, $rootScope) {
$scope.lat;
$scope.long;
$scope.player = "";
$scope.city = MyService.city;
$scope.nameSet = false;
$scope.markers = MyService.messages.map(function(msg) {
return {
lng: msg.long,
lat: msg.lat,
message: msg.player,
focus: msg
}
});
...
});application.js (controller state):
angularjs
app.controller('MainCtrl', function($scope, MyService, $rootScope) {
...
$rootScope.$watch(
function() {
return MyService.city;
}, function (newValue) {
$scope.city = newValue;
$scope.lat = 0;
$scope.long = 0;
$scope.markers = [];
});
$rootScope.$watchCollection(
function() {
return MyService.messages;
}, function(newValue) {
$scope.markers = newValue.map(function(moveMessage) {
return {
lng: moveMessage.long,
lat: moveMessage.lat,
message: moveMessage.player,
focus: false
}
});
});
...
});application.js (watch functions):
angularjs
app.controller('MainCtrl', function($scope, MyService, $rootScope) {
...
$scope.doSend = function() {
var data = {
action: "answer",
lat: $scope.lat,
long: $scope.long,
city: $scope.city,
player: $scope.player
};
MyService.postMsg(JSON.stringify(data));
};
$scope.join = function() {
MyService.connect();
$scope.nameSet = true;
};
...
});application.js (controller functions):
angularjs
app.controller('MainCtrl', function($scope, MyService, $rootScope) {
...
$scope.$on('leafletDirectiveMap.click', function(event, args){
var latlng = args.leafletEvent.latlng;
$scope.lat = latlng.lat;
$scope.long = latlng.lng;
});
angular.extend($scope, {
defaults: {
maxZoom: 2,
minZoom: 2
},
events: {
map: {
enable: ['click'],
logic: 'emit'
}
}
});
});application.js (leaflet configuration):
live badass demo

Play Framework
next steps:
-
visit www.playframework.com
-
Work further on this demo project
-
Help translate the documentation: see github.com/antonsarov/translation-project
Thank you
Now ask all the questions :)
Play Framework Workshop at Spartakiade
By duxanton
Play Framework Workshop at Spartakiade
Presentation for the Play Framework workshop at the Spartakiade conference
- 825