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

  1. many-core CPUs are here
  2. everything is distributed
  3. IoT around the corner
  4. 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