SlideShare a Scribd company logo
Full Stack Scala
Scala in the backend and frontend!
Ramnivas Laddad
Founder, Paya Labs
@ramnivas
@ramnivas
• Spring framework and Cloud Foundry
contributor
• Main interests
• Scala and functional programming
• Cloud computing
• Author of books and articles
• AspectJ in Action (1st and 2nd edition)
• Speaker at many professional conferences
• JavaOne, ScalaDays, JavaPolis, SpringOne, Software
Development, No Fluff Just Stuff, OSCON etc.
A Quick Demo
High-level Architecture
API Server Static Page Server
html, js, css,
…
GET, PUT, POST,
DELETE
{
"name" : ...
}
Backend Stack
API Server
API Server Static Page Server
html, js, css,
…
GET, PUT, POST,
DELETE
{
"name" : ...
}
API Server
API Server Static Page Server
html, js, css,
…
GET, PUT, POST,
DELETE
{
"name" : ...
}
Backend Structure
Backend Structure
Database
Backend Structure
DatabaseSendgrid
Backend Structure
DatabaseSendgridS3
Backend Structure
DatabaseSendgridS3
Backend Structure
DatabaseSendgridS3
Backend Structure
DatabaseSendgridS3
Backend Structure
Database
Data Access Layer
SendgridS3
Backend Structure
Database
Data Access Layer
SendgridS3
Talk by Rob Norris
Programs asValues: JDBC Programming with Doobie
Backend Structure
Database
Data Access Layer
SendgridS3
Backend Structure
Database
Data Access Layer
SendgridS3
Apache
Commons
Backend Structure
Database
Data Access Layer
SendgridS3
Apache
Commons
AWS
SDK
Backend Structure
Database
Data Access Layer
Service Layer
SendgridS3
Apache
Commons
AWS
SDK
Backend Structure
Database
Data Access Layer
Service Layer
HTTP Layer
SendgridS3
Apache
Commons
AWS
SDK
Frontend Stack
High-level Architecture
Static Page Server
html, js, css,
…
API Server
GET, PUT, POST,
DELETE
{
"name" : ...
}
High-level Architecture
Static Page Server
html, js, css,
…
API Server
GET, PUT, POST,
DELETE
{
"name" : ...
}
Serving static contents
var express = require('express');
var fs = require('fs');
var app = express();
var port = process.env.PORT || 4000;
var devMode = process.env.SERVE_MODE != "SERVE_PROD";
var serveInfo = { dir: __dirname + ‘/dev-bin', maxAge: 0}
if (!devMode) {
var oneHour = 60*60*1000;
serveInfo = { dir: __dirname + ‘/prod-bin', maxAge: oneHour}
}
app.use(express.static(serveInfo.dir, { maxAge: serveInfo.maxAge }));
app.get('*', function(request, response, next) {
response.sendFile(serveInfo.dir + '/index.html');
});
app.listen(port, function() {
console.log("Started on " + port + " (dev mode = " + devMode + ")n");
});
High-level Architecture
API Server Static Page Server
html, js, css,
…
GET, PUT, POST,
DELETE
{
"name" : ...
}
High-level Architecture
API Server Static Page Server
html, js, css,
…
GET, PUT, POST,
DELETE
{
"name" : ...
}
Why Scala.js?
Why Scala.js?
Why Scala.js
Scala!
Why Scala.js
StaticTypes
Why Scala.js
Functional Programming
Why Scala.js
Isomorphism
Why Scala.js
Maturity!
Why Scala.js
Eco-system
UI Framework
Choosing a UI Framework
Choosing a UI Framework
Simple
Mental Model
Choosing a UI Framework
Simple
Mental Model
Immutable
Data
Choosing a UI Framework
Simple
Mental Model
Functional
programming
Immutable
Data
Choosing a UI Framework
Simple
Mental Model
Mobile
Functional
programming
Immutable
Data
Choosing a UI Framework
Simple
Mental Model
Mobile
Functional
programming
Immutable
Data
Isomorphism
Choosing a UI Framework
Simple
Mental Model
CommunityMobile
Functional
programming
Immutable
Data
Isomorphism
Choosing a UI Framework
Simple
Mental Model
CommunityMobile
Functional
programming
Immutable
Data
Isomorphism
What is React?
• “A JavaScript library for building user interfaces” by
Facebook
• Focuses just on the UI
• Uses virtual DOM
• One-way data-flow
Frontend Overview
Frontend Overview
Router
Frontend Overview
Router
Frontend Overview
Router Flux
Component
Frontend Overview
Router Flux
Component
Frontend Overview
Router
Store
Flux
Component
Frontend Overview
Router
Store
Flux
Component
Frontend Overview
Router
Store
Flux
Component
Rest Client
Frontend Overview
Router
Store
Flux
Component
Rest Client
Frontend Overview
Router
Store
Flux
Component
Rest Client
Frontend Overview
Router
Store
Flux
Component
Rest Client
Frontend Overview
ComponentRouter
Store
Flux
Component
Rest Client
Frontend Overview
ComponentRouter
Store
Flux
Component
Rest Client
Scala.js with React
• Statically-typed wrapper around React
• Fluent, builder API to create components
• Well-implemented router (v2)
scalajs-react
Simple Mental Model
View
PropertiesState
Composition
Composition
Composition
Composition
Composition
Real World Composition
Real World Composition
Real World Composition
Mostly Immutable
ComponentRouter
Store
Flux
Component
Rest Client
Taking advantage of immutability
def shouldComponentUpdate(scope: ScopeType,
nextProps: P,
nextState: S) = {
scope.props != nextProps ||
scope.state != nextState
}
Flux
Flux Component
object ArtistRegistrationWrapper extends
FluxComponent[String, ArtistEditDto](Seq(ArtistStore, InstrumentStore)) {
def onArtistChange(artist: ArtistEditDto): Unit = {
ArtistUpdated(artist).dispatch()
}
...
def element(props: String) = {
...
div(
ArtistRegistration(
ArtistRegistrationProps(
artist, allInstruments, onArtistChange,
onArtistCoverPhotoChange, onArtistProfilsePhotoChange)
)
)
}
}
Component
object ArtistRegistration extends
Component[ArtistRegistrationProps] {
def element(props: ArtistRegistrationProps): ReactTag = {
div(…)
}
}
Responding to events
override def receive = {
case ArtistUpdated(newValue) =>
artist = newValue
emitChange()
case ArtistSaved =>
save()
emitChange()
...
No sweat undo/redo
trait CompositionStore extends AbstractStore {
val compositionStack = new UndoStack[Composition]()
override def receive = {
case NewComposition =>
compositionStack.clear()
loaded()
case LoadComposition(c) =>
compositionStack.clear()
compositionStack.push(c)
loaded()
case UpdateComposition(c) =>
compositionStack.push(c)
emitChange()
case UndoComposition =>
compositionStack.undo()
emitChange()
case RedoComposition =>
compositionStack.redo()
emitChange()
...
}
Mobile: React Native
Mobile: React Native
https://facebook.github.io/react-native
Mobile: React Native
https://github.com/chandu0101/scalajs-react-native
https://facebook.github.io/react-native
Using external components
Bridging Native React Components
• Problem:
• You got to use components developed in the
wild
• Requires significant boilerplate to make it work
from scalajs-react
• Solution: Some macro magic!
Bridging Native React Components
• Problem:
• You got to use components developed in the
wild
• Requires significant boilerplate to make it work
from scalajs-react
• Solution: Some macro magic!
github.com/payalabs/scalajs-react-bridge
Example Bridge Component
case class TagsInput(id: js.UndefOr[String] = js.undefined,
className: js.UndefOr[String] = js.undefined,
ref: js.UndefOr[String] = js.undefined,
key: js.UndefOr[Any] = js.undefined,
defaultValue: js.UndefOr[Seq[String]] = js.undefined,
value: js.UndefOr[Array[String]] = js.undefined,
placeholder: js.UndefOr[String] = js.undefined,
onChange: js.UndefOr[js.Array[String] => Unit] = js.undefined,
validate: js.UndefOr[String => Boolean] = js.undefined,
transform: js.UndefOr[String => String] = js.undefined)
extends ReactBridgeComponent
UsingTagsInput
div(
TagsInput(
defaultValue = Seq(“foo","bar"),
onChange = printSequence _
)
)
Using MDL in React
• Problem:
• Components need to be “upgraded”
• Solution:
• React wrapper component around a ReactTag
• Upgrades element upon mounting
• Implicits to avoid noise
Using MDL in React
• Problem:
• Components need to be “upgraded”
• Solution:
• React wrapper component around a ReactTag
• Upgrades element upon mounting
• Implicits to avoid noise
github.com/payalabs/scalajs-react-mdl
Example MDL Use
a(className := "mdl-button mdl-js-button
mdl-button--raised mdl-button—colored
mdl-js-ripple-effect",
onClick --> saveAction())("Save").material
Example MDL Use
a(className := "mdl-button mdl-js-button
mdl-button--raised mdl-button—colored
mdl-js-ripple-effect",
onClick --> saveAction())("Save").material
Things on the Horizon
• GraphQL?
• Stitch?
• Relay?
• Falcor?
?
Ramnivas Laddad
@ramnivas

More Related Content

Full Stack Scala