SlideShare a Scribd company logo
1 of 42
Download to read offline
Sept 06 2014
Ngoc Dao 
https://github.com/ngocdaothanh 
Takeharu Oshida 
https://github.com/georgeOsdDev 
http://mobilus.co.jp/
What is 
Xitrum? 
Xitrum is an async and clustered ! 
Scala web framework and HTTP(S) server ! 
on top of Netty, Akka
Why you should use 
Xitrum? 
• Featureful! 
• Easy to use! 
• High performance 
Scala, Netty, and Akka are fast! 
• Scalable 
Can scale to a cluster of servers using 
Akka cluster and/or Hazelcast
Homepage: 
http://xitrum-framework.github.io/ 
(there are various demos) 
Guides (English, Japanese, Russian): 
http://xitrum-framework.github.io/guide.html 
(Korean version is in progress) 
! 
Community (Google Group): 
https://groups.google.com/forum/#!forum/ 
xitrum-framework
Where 
Xitrum is used? 
KONNECT (Messaging Service)! 
http://mobilus.co.jp/konnect/! 
! 
KONNECT can be used in mobile games, 
mobiles apps, SNS websites etc. 
Xitrum is also being used in France, Korea, 
Russia, Singapore etc.
Xitrum:! 
WebSocket (SockJS)! 
CORS support
2010-2013 Xitrum 1.x-2.x 
http://bit.ly/xitrum13 
2014 Xitrum 3.x 
• Netty 4.x 
• Swagger 
• Component 
• FileMonitor, i18n 
• CORS 
• WebJARs 
• Glokka 
• Agent7 (autoreload classes on change) 
! 
! 
http://bit.ly/xitrum-changelog 
!
How Xitrum 
works?
Client 
Netty 
Async 
Dispatch 
request 
Action FutureAction ActorAction 
Akka 
Xitrum 
I/O thread pool to 
accept requests and reply 
responses 
Thread pool 
to run FutureAction and 
ActorAction 
Client 
Run directly on 
Netty I/O thread 
Netty handler 
Netty handler 
Netty handler 
Netty handler 
Xitrum 
Your program
http://bit.ly/xitrum-handlers
Client 
Client Client 
Akka cluster (code)! 
Hazelcast (data) 
Client 
Netty 
Xitrum 
A FA AA 
Akka 
Netty 
Xitrum 
A FA AA 
Akka 
Server N Server N+1
Embed Xitrum 
object MyApp { 
def main(args: Array[String]) { 
... 
// Somewhere in your app 
xitrum.Server.start() 
... 
} 
1. Collect routes! 
} 
! 
2. Start HTTP/HTTPS servers
Action example 
import xitrum.Action 
import xitrum.annotation.GET 
! 
@GET("hello") 
class MyAction extends Action { 
def execute() { 
respondText("Hello") 
} 
} 
FutureAction! 
ActorAction
Annotations: Scala vs Java 
Scala: @GET("matsuri", "festival") 
Java: @GET(Array("matsuri", "festival")) 
! 
Scala: 
case class GET(paths: String*) extends 
scala.annotation.StaticAnnotation 
! 
Java: 
public @interface GET { 
String[] value(); 
}
Benefits of using annotations 
Routes in .class and .jar in classpath are 
automatically collected and merged. 
A.class 
B.class 
lib1.jar 
lib2.jar 
Routes
Problem with annotations 
Collecting routes from .class and .jar files is slow.! 
! 
Solutions:! 
• In development mode, routes in .class and .jar 
files that are not in the current working directory 
are cached to file routes.cache. 
• To avoid loading lots of classes, don't collect 
routes from: java.xxx, javax.xxx, scala.xxx, 
sun.xxx, com.sun.xxx
Annotations defined by Xitrum:! 
http://bit.ly/xitrum-annotations! 
! 
Lib to scan classes in classpath to collect routes:! 
https://github.com/xitrum-framework/sclasner
Demo overview 
GET / GET /chat 
username 
password 
login 
Hello 
! 
Hello! 
How are you? 
Fine 
message send 
POST /login SockJS /connect 
https://github.com/xitrum-framework/matsuri14
Demo overview 
• Simple HTTP CRUD with MongoDB 
POST /admin/user 
GET /admin/user 
GET /admin/user/:userId 
PUT /admin/user/:userId 
DELETE /admin/user/:userId 
PUT/PATCH/DELETE can be emulated via 
POST with _method=PUT/PATCH/DELETE 
! 
• API documentation with Swagger
DB Cluseter 
Xitrum1 Akka Hazelcast 
Xitrum2 Akka Hazelcast 
Xitrum3 
Cluster 
LB 
(HAProxy, Nginx, 
Route53 etc.) 
NoSQL 
RDB 
Other services 
Akka Hazelcast 
https://github.com/xitrum-framework/glokka 
https://github.com/xitrum-framework/xitrum-hazelcast
Getting started 
with xitrum-new 
skeleton 
https://github.com/xitrum-framework/xitrum-new 
https://github.com/xitrum-framework/xitrum-scalate
@GET("admin") 
class AdminIndex extends Action { 
def execute() { 
// Get all users 
val users = User.listAll() 
// Pass users to view template 
at("users") = users 
! 
// Response respons view with template 
respondView() 
} 
} 
ActorAction 
FutureAction 
Action
- import matsuri.demo.action._! 
- import matsuri.demo.model.User! 
! 
div.row#usersTable! 
table.table.table-striped#messageTable! 
thead! 
tr.bg-primary! 
View 
• Scalate template with jade 
(mustache, scaml, or ssp) 
• "at" function 
• i18n with GNU gettext 
th.col-xs-2 =t("Name")! 
th.col-xs-2 =t("Age")! 
th.col-xs-2 =t("Desc")! 
th.col-xs-2 =t("Created time")! 
th.col-xs-2 =t("Updated time")! 
th.col-xs-2 =t("Last login time")! 
tbody! 
- for (user <- at("users").asInstanceOf[List[User]])! 
tr! 
th! 
a(href={url[AdminUserShow](("name", user.name))}) = user.name! 
th = user.age! 
th = user.desc! 
th = user.createdAtAsStr! 
th = user.updatedAtAsStr! 
th = user.lastLoginAsStr
└── src 
└── scalate 
└── matsuri 
└── demo 
└── action 
├── AdminIndex.jade 
└── DefaultLayout.jade 
package matsuri.demo.action 
! 
import xitrum.Action 
! 
trait DefaultLayout extends Action { 
override def layout = 
renderViewNoLayout[DefaultLayout]() 
} 
Layout
!!! 5 
html 
head 
!= antiCsrfMeta 
!= xitrumCss 
! 
meta(content="text/html; charset=utf-8" http-equiv="content-type") 
title ScalaMatsuri2014 Xitrum Demo 
! 
link(rel="shortcut icon" href={publicUrl("favicon.ico")}) 
link(type="text/css" rel="stylesheet" media="all" href={webJarsUrl("bootstrap/3.2.0/css", 
"bootstrap.css", "bootstrap.min.css")}) 
link(type="text/css" rel="stylesheet" media="all" href={publicUrl("app.css")}) 
! 
body 
.container 
h1 
! 
#flash 
!~ jsRenderFlash() 
!= renderedView 
Layout 
! 
!= jsDefaults 
script(src={webJarsUrl("bootstrap/3.2.0/js", "bootstrap.js", "bootstrap.min.js")}) 
script(src={webJarsUrl("underscorejs/1.6.0", "underscore.js", "underscore-min.js")}) 
!= jsForView
form(role="form" method="post" action={url[AdminUserCreate]}) 
!= antiCsrfInput 
div.modal-header 
button.close(type="button" data-dismiss="modal") 
Form 
span(aria-hidden="true") &times; 
span.sr-only =t("Close") 
h4.modal-title#myModalLabel =t("Create New User") 
div.modal-body 
div.form-group 
label(for="newUserName") =t("Name") 
input.form-control#newUserName(name="name" type="text" 
• "url" function 
• jquery-validation 
• Anti csrf token 
placeholder={t("Enter Name")} minlength=5 maxlenght=10 required=true) 
div.form-group 
label(for="newUserPass") =t("Password") 
input.form-control#newUserPass(name="password" type="password" 
placeholder={t("Enter Password")} minlength=8 required=true) 
! 
div.modal-footer 
button.btn.btn-default(type="button" data-dismiss="modal") = t("Cancel") 
button.btn.btn-primary(type="submit") = t("Save")
@POST("admin/user") 
class AdminUserCreate extends AdminAction { 
def execute() { 
// Get request paramaters 
val name = param("name") 
val password = param("password") 
// Optional parameters 
val age = paramo[Int]("age") 
val desc = paramo("desc") 
! 
Required.exception("name", name) 
Required.exception("password", password) 
! 
User.create(name, password, age, desc) 
flash(t("Success")) 
redirectTo[AdminIndex]() 
} 
Get 
request 
params 
with 
param(s) 
and 
param(o)
object SVar { 
object isAdmin extends SessionVar[Boolean] 
} 
Use before filter 
to check 
trait AdminFilter { 
this: Action => 
! 
beforeFilter { 
if (SVar.isAdmin.isDefined) true else authBasic() 
} 
! 
private def authBasic(): Boolean = { 
basicAuth(Config.basicAuth.realm) { (username, password) => 
if (username == Config.basicAuth.name && password == Config.basicAuth.pass) { 
SVar.isAdmin.set(true) 
true 
} else { 
false 
} 
} 
} 
authentication 
info in session
@Swagger( 
Swagger.Summary("Create User"), 
Swagger.Response(200, "status = 0: success, 1: failed to create user"), 
Swagger.Response(400, "Invalid request parameter"), 
Swagger.StringForm("name"), 
Swagger.StringForm("password"), 
Swagger.OptIntForm("age"), 
Swagger.OptStringForm("desc") 
) 
API 
doc 
• /xitrum/swagger 
• /xitrum/swagger-ui 
• Create test client with Swagger-codegen 
https://github.com/wordnik/swagger-ui 
https://github.com/wordnik/swagger-codegen 
https://github.com/wordnik/swagger-spec
@GET("login", "") 
class LoginIndex extends DefaultLayout { 
def execute() { 
respondView() 
} 
} 
! 
@POST("login") 
class Login extends Action { 
def execute() { 
session.clear() 
val name = param("name") 
val password = param("password") 
! 
User.authLogin(name, password) match { 
case Some(user) => 
SVar.userName.set(user.name) 
redirectTo[ChatIndex]() 
! 
case None => 
flash(t(s"Invalid username or password")) 
redirectTo[LoginIndex]() 
} 
} 
} 
Login
jsAddToView( 
"var url = '" + sockJsUrl[ChatAction] + "';" + 
""" 
var socket; 
var initSocket = function() { 
socket = new SockJS(url); 
socket.onopen = function(event) { 
console.log("socket onopen", event.data); 
socket.send(JSON.parse({"msg":"Hello Xitrum"})); 
}; 
socket.onclose = function(event) {console.log("socket onclose", event.data);}; 
socket.onmessage = function(event) {console.log("socket onmessage", event.data);}; 
}; 
initSocket(); 
""" 
) 
!= jsDefaults 
script(src={webJarsUrl("bootstrap/3.2.0/js", "bootstrap.js", "bootstrap.min.js")}) 
script(src={webJarsUrl("underscorejs/1.6.0", "underscore.js", "underscore-min.js")}) 
!= jsForView 
• jsAddToView/jsForView 
• sockJsUrl 
• webJarsUrl 
Create 
chat 
client 
with 
SockJS
import xitrum.{SockJsAction, SockJsText} 
import xitrum.annotation.SOCKJS 
! 
@SOCKJS("connect") 
class ChatAction extends SockJsAction with LoginFilter { 
def execute() { 
context.become { 
SockJsAction 
(an Actor) 
case SockJsText(text) => 
SeriDeseri.fromJson[Map[String, String]](text) match { 
case Some(jsonMap) => 
// echo 
respondSockJsText(SeriDeseri.toJson(jsonMap)) 
case None => 
log.warn(s"Failed to parse request: $text") 
respondSockJsText("invalid request") 
} 
Create 
} 
• SockJsAction 
• SockJsText/respondSockJsText 
• SeriDeseri.fromJson[T] / SeriDeseri.toJson(ref:AnyRef)
Lookup 
singleton 
Actor 
with 
Glokka 
Xitrum 
socket open 
Client 
HubActor 
trait Hub extends Actor { 
protected var clients = Seq[ActorRef]() 
def receive = { 
case Subscribe(option) => 
clients = clients :+ sender 
case Unsubscribe(option) => 
clients = clients.filterNot(_ == sender) 
case Terminated(client) => 
clients = clients.filterNot(_ == client) 
case ignore => 
} 
import glokka.Registry 
object Hub { 
val KEY_PROXY = "HUB_PROXY" 
val actorRegistry = Registry.start(Config.actorSystem, 
KEY_PROXY) 
} 
! 
def lookUpHub(key: String, hubProps: Props, option: Any = None) 
{ 
Hub.actorRegistry ! Registry.Register(key, hubProps) 
context.become { 
hub ! Subscribe 
ChatAction ChatAction ChatAction ChatAction 
case result: Registry.FoundOrCreated => 
result.ref ! Subscribe 
} 
} 
Client Client Client 
https://github.com/xitrum-framework/glokka
Messaging overview 
SockJsText! 
(socket.send) hub ! Push(msg) 
clients.foreach { _ ! Publish(msg)} respondSockJSText(msg:String) 
Client ChatAction HubActor 
socket.onmessage 
SockJsText hub ! Pull(msg) 
case class Done (option: Map[String, Any] = Map.empty) // Hub -> Action 
case class Publish(option: Map[String, Any] = Map.empty) // Hub -> Action 
case class Pull (option: Map[String, Any] = Map.empty) // Action -> Hub 
case class Push (option: Map[String, Any] = Map.empty) // Action -> Hub 
https://github.com/georgeOsdDev/glokka-demo 
ChatAction Client 
ChatAction 
ChatAction 
Client 
Client 
respondSockJSText(msg:String) sender ! Done(msg) 
Client ChatAction HubActor 
respondSockJSText(msg:String) sender ! Done(msg) 
socket.onmessage
Cluster config for Hazelcast 
hazelcastMode = clusterMember 
! 
cache = xitrum.hazelcast.Cache 
#cache { 
# # Simple in-memory cache 
# "xitrum.local.LruCache" { 
xitrum.conf 
# maxElems = 10000 
# } 
• Xitrum-hazelcast 
#} 
• Shared Session 
• Shared Cache 
! 
session { 
store = xitrum.hazelcast.Session 
# Store sessions on client side 
#store = xitrum.scope.session.CookieSessionStore
akka { 
loggers = ["akka.event.slf4j.Slf4jLogger"] 
logger-startup-timeout = 30s 
! 
actor { 
provider = "akka.cluster.ClusterActorRefProvider" 
} 
! 
# This node 
remote { 
log-remote-lifecycle-events = off 
netty.tcp { 
hostname = "127.0.0.1" 
port = 2551 # 0 means random port 
} 
} 
! 
cluster { 
seed-nodes = [ 
"akka.tcp://xitrum@127.0.0.1:2551", 
"akka.tcp://xitrum@127.0.0.1:2552"] 
! 
auto-down-unreachable-after = 10s 
} 
} 
Cluster 
config 
for 
Akka
Live class reload 
during development 
https://github.com/xitrum-framework/agent7 
https://github.com/dcevm/dcevm 
java -javaagent:`dirname $0`/agent7-1.0.jar 
-XXaltjvm=dcevm -Xms256M -Xmx512M -Xss1M 
-XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=384M 
-jar `dirname $0`/sbt-launch-0.13.5.jar "$@" 
https://github.com/xitrum-framework/xitrum-package
Package project for 
deploying to 
production server 
https://github.com/xitrum-framework/xitrum-package 
sbt/sbt xitrum-package
Monitor Xitrum 
in production mode 
• Scalive 
• Metrics 
• Log to fluentd 
https://github.com/xitrum-framework/scalive 
http://www.slideshare.net/georgeosd/scalive 
http://xitrum-framework.github.io/guide/3.18/en/ 
log.html#log-to-fluentd
Thank 
you!

More Related Content

What's hot

SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin
SenchaCon 2016: Modernizing the Ext JS Class System - Don GriffinSenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin
SenchaCon 2016: Modernizing the Ext JS Class System - Don GriffinSencha
 
Survive JavaScript - Strategies and Tricks
Survive JavaScript - Strategies and TricksSurvive JavaScript - Strategies and Tricks
Survive JavaScript - Strategies and TricksJuho Vepsäläinen
 
Demystifying Oak Search
Demystifying Oak SearchDemystifying Oak Search
Demystifying Oak SearchJustin Edelson
 
Java EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSFJava EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSFJiayun Zhou
 
Activator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetupActivator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetupHenrik Engström
 
Building a java tracer
Building a java tracerBuilding a java tracer
Building a java tracerrahulrevo
 
Performance Optimization and JavaScript Best Practices
Performance Optimization and JavaScript Best PracticesPerformance Optimization and JavaScript Best Practices
Performance Optimization and JavaScript Best PracticesDoris Chen
 
Java FX 2.0 - A Developer's Guide
Java FX 2.0 - A Developer's GuideJava FX 2.0 - A Developer's Guide
Java FX 2.0 - A Developer's GuideStephen Chin
 
Node Architecture and Getting Started with Express
Node Architecture and Getting Started with ExpressNode Architecture and Getting Started with Express
Node Architecture and Getting Started with Expressjguerrero999
 
Softshake 2013: 10 reasons why java developers are jealous of Scala developers
Softshake 2013: 10 reasons why java developers are jealous of Scala developersSoftshake 2013: 10 reasons why java developers are jealous of Scala developers
Softshake 2013: 10 reasons why java developers are jealous of Scala developersMatthew Farwell
 
Building a real life application in node js
Building a real life application in node jsBuilding a real life application in node js
Building a real life application in node jsfakedarren
 
Using Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databasesUsing Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databasesRaimonds Simanovskis
 
How and Where in GLORP
How and Where in GLORPHow and Where in GLORP
How and Where in GLORPESUG
 
Building servers with Node.js
Building servers with Node.jsBuilding servers with Node.js
Building servers with Node.jsConFoo
 
The DOM is a Mess @ Yahoo
The DOM is a Mess @ YahooThe DOM is a Mess @ Yahoo
The DOM is a Mess @ Yahoojeresig
 

What's hot (20)

Spring data requery
Spring data requerySpring data requery
Spring data requery
 
SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin
SenchaCon 2016: Modernizing the Ext JS Class System - Don GriffinSenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin
SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin
 
JavaCro'14 - Scala and Java EE 7 Development Experiences – Peter Pilgrim
JavaCro'14 - Scala and Java EE 7 Development Experiences – Peter PilgrimJavaCro'14 - Scala and Java EE 7 Development Experiences – Peter Pilgrim
JavaCro'14 - Scala and Java EE 7 Development Experiences – Peter Pilgrim
 
Survive JavaScript - Strategies and Tricks
Survive JavaScript - Strategies and TricksSurvive JavaScript - Strategies and Tricks
Survive JavaScript - Strategies and Tricks
 
Demystifying Oak Search
Demystifying Oak SearchDemystifying Oak Search
Demystifying Oak Search
 
Mastering Java ByteCode
Mastering Java ByteCodeMastering Java ByteCode
Mastering Java ByteCode
 
Java EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSFJava EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSF
 
Activator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetupActivator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetup
 
Building a java tracer
Building a java tracerBuilding a java tracer
Building a java tracer
 
Jet presentation
Jet presentationJet presentation
Jet presentation
 
Performance Optimization and JavaScript Best Practices
Performance Optimization and JavaScript Best PracticesPerformance Optimization and JavaScript Best Practices
Performance Optimization and JavaScript Best Practices
 
Java FX 2.0 - A Developer's Guide
Java FX 2.0 - A Developer's GuideJava FX 2.0 - A Developer's Guide
Java FX 2.0 - A Developer's Guide
 
Node Architecture and Getting Started with Express
Node Architecture and Getting Started with ExpressNode Architecture and Getting Started with Express
Node Architecture and Getting Started with Express
 
Softshake 2013: 10 reasons why java developers are jealous of Scala developers
Softshake 2013: 10 reasons why java developers are jealous of Scala developersSoftshake 2013: 10 reasons why java developers are jealous of Scala developers
Softshake 2013: 10 reasons why java developers are jealous of Scala developers
 
Building a real life application in node js
Building a real life application in node jsBuilding a real life application in node js
Building a real life application in node js
 
Using Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databasesUsing Ruby on Rails with legacy Oracle databases
Using Ruby on Rails with legacy Oracle databases
 
How and Where in GLORP
How and Where in GLORPHow and Where in GLORP
How and Where in GLORP
 
Zen of Akka
Zen of AkkaZen of Akka
Zen of Akka
 
Building servers with Node.js
Building servers with Node.jsBuilding servers with Node.js
Building servers with Node.js
 
The DOM is a Mess @ Yahoo
The DOM is a Mess @ YahooThe DOM is a Mess @ Yahoo
The DOM is a Mess @ Yahoo
 

Similar to Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング

Rich Portlet Development in uPortal
Rich Portlet Development in uPortalRich Portlet Development in uPortal
Rich Portlet Development in uPortalJennifer Bourey
 
RESTful Web Applications with Apache Sling
RESTful Web Applications with Apache SlingRESTful Web Applications with Apache Sling
RESTful Web Applications with Apache SlingBertrand Delacretaz
 
soft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch
 
Universal JavaScript
Universal JavaScriptUniversal JavaScript
Universal JavaScript名辰 洪
 
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)Doris Chen
 
jQuery Tips Tricks Trivia
jQuery Tips Tricks TriviajQuery Tips Tricks Trivia
jQuery Tips Tricks TriviaCognizant
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...Fabio Franzini
 
Front End Development for Back End Developers - UberConf 2017
Front End Development for Back End Developers - UberConf 2017Front End Development for Back End Developers - UberConf 2017
Front End Development for Back End Developers - UberConf 2017Matt Raible
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareAlona Mekhovova
 
An Introduction to Tornado
An Introduction to TornadoAn Introduction to Tornado
An Introduction to TornadoGavin Roy
 
vJUG - The JavaFX Ecosystem
vJUG - The JavaFX EcosystemvJUG - The JavaFX Ecosystem
vJUG - The JavaFX EcosystemAndres Almiray
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsFrancois Zaninotto
 
GitBucket: The perfect Github clone by Scala
GitBucket: The perfect Github clone by ScalaGitBucket: The perfect Github clone by Scala
GitBucket: The perfect Github clone by Scalatakezoe
 
Ajax tutorial
Ajax tutorialAjax tutorial
Ajax tutorialKat Roque
 
Express Presentation
Express PresentationExpress Presentation
Express Presentationaaronheckmann
 
Build Your Own CMS with Apache Sling
Build Your Own CMS with Apache SlingBuild Your Own CMS with Apache Sling
Build Your Own CMS with Apache SlingBob Paulin
 

Similar to Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング (20)

Rich Portlet Development in uPortal
Rich Portlet Development in uPortalRich Portlet Development in uPortal
Rich Portlet Development in uPortal
 
Spine.js
Spine.jsSpine.js
Spine.js
 
RESTful Web Applications with Apache Sling
RESTful Web Applications with Apache SlingRESTful Web Applications with Apache Sling
RESTful Web Applications with Apache Sling
 
soft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.js
 
Universal JavaScript
Universal JavaScriptUniversal JavaScript
Universal JavaScript
 
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
 
jQuery Tips Tricks Trivia
jQuery Tips Tricks TriviajQuery Tips Tricks Trivia
jQuery Tips Tricks Trivia
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
Front End Development for Back End Developers - UberConf 2017
Front End Development for Back End Developers - UberConf 2017Front End Development for Back End Developers - UberConf 2017
Front End Development for Back End Developers - UberConf 2017
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middleware
 
Azure F#unctions
Azure F#unctionsAzure F#unctions
Azure F#unctions
 
An Introduction to Tornado
An Introduction to TornadoAn Introduction to Tornado
An Introduction to Tornado
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
 
vJUG - The JavaFX Ecosystem
vJUG - The JavaFX EcosystemvJUG - The JavaFX Ecosystem
vJUG - The JavaFX Ecosystem
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
GitBucket: The perfect Github clone by Scala
GitBucket: The perfect Github clone by ScalaGitBucket: The perfect Github clone by Scala
GitBucket: The perfect Github clone by Scala
 
Ajax tutorial
Ajax tutorialAjax tutorial
Ajax tutorial
 
5.node js
5.node js5.node js
5.node js
 
Express Presentation
Express PresentationExpress Presentation
Express Presentation
 
Build Your Own CMS with Apache Sling
Build Your Own CMS with Apache SlingBuild Your Own CMS with Apache Sling
Build Your Own CMS with Apache Sling
 

More from scalaconfjp

脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~
脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~
脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~scalaconfjp
 
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会scalaconfjp
 
GraalVM Overview Compact version
GraalVM Overview Compact versionGraalVM Overview Compact version
GraalVM Overview Compact versionscalaconfjp
 
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...scalaconfjp
 
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...scalaconfjp
 
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeau
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan GoyeauScala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeau
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeauscalaconfjp
 
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...scalaconfjp
 
Scala ♥ Graal by Flavio Brasil
Scala ♥ Graal by Flavio BrasilScala ♥ Graal by Flavio Brasil
Scala ♥ Graal by Flavio Brasilscalaconfjp
 
Introduction to GraphQL in Scala
Introduction to GraphQL in ScalaIntroduction to GraphQL in Scala
Introduction to GraphQL in Scalascalaconfjp
 
Safety Beyond Types
Safety Beyond TypesSafety Beyond Types
Safety Beyond Typesscalaconfjp
 
Reactive Kafka with Akka Streams
Reactive Kafka with Akka StreamsReactive Kafka with Akka Streams
Reactive Kafka with Akka Streamsscalaconfjp
 
Reactive microservices with play and akka
Reactive microservices with play and akkaReactive microservices with play and akka
Reactive microservices with play and akkascalaconfjp
 
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメントScalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメントscalaconfjp
 
DWANGO by ドワンゴ
DWANGO by ドワンゴDWANGO by ドワンゴ
DWANGO by ドワンゴscalaconfjp
 
OCTOPARTS by M3, Inc.
OCTOPARTS by M3, Inc.OCTOPARTS by M3, Inc.
OCTOPARTS by M3, Inc.scalaconfjp
 
Try using Aeromock by Marverick, Inc.
Try using Aeromock by Marverick, Inc.Try using Aeromock by Marverick, Inc.
Try using Aeromock by Marverick, Inc.scalaconfjp
 
統計をとって高速化する
Scala開発 by CyberZ,Inc.
統計をとって高速化する
Scala開発 by CyberZ,Inc.統計をとって高速化する
Scala開発 by CyberZ,Inc.
統計をとって高速化する
Scala開発 by CyberZ,Inc.scalaconfjp
 
Short Introduction of Implicit Conversion by TIS, Inc.
Short Introduction of Implicit Conversion by TIS, Inc.Short Introduction of Implicit Conversion by TIS, Inc.
Short Introduction of Implicit Conversion by TIS, Inc.scalaconfjp
 
ビズリーチ x ScalaMatsuri by BIZREACH, Inc.
ビズリーチ x ScalaMatsuri  by BIZREACH, Inc.ビズリーチ x ScalaMatsuri  by BIZREACH, Inc.
ビズリーチ x ScalaMatsuri by BIZREACH, Inc.scalaconfjp
 
sbt, past and future / sbt, 傾向と対策
sbt, past and future / sbt, 傾向と対策sbt, past and future / sbt, 傾向と対策
sbt, past and future / sbt, 傾向と対策scalaconfjp
 

More from scalaconfjp (20)

脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~
脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~
脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~
 
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会
 
GraalVM Overview Compact version
GraalVM Overview Compact versionGraalVM Overview Compact version
GraalVM Overview Compact version
 
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...
 
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...
 
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeau
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan GoyeauScala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeau
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeau
 
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
 
Scala ♥ Graal by Flavio Brasil
Scala ♥ Graal by Flavio BrasilScala ♥ Graal by Flavio Brasil
Scala ♥ Graal by Flavio Brasil
 
Introduction to GraphQL in Scala
Introduction to GraphQL in ScalaIntroduction to GraphQL in Scala
Introduction to GraphQL in Scala
 
Safety Beyond Types
Safety Beyond TypesSafety Beyond Types
Safety Beyond Types
 
Reactive Kafka with Akka Streams
Reactive Kafka with Akka StreamsReactive Kafka with Akka Streams
Reactive Kafka with Akka Streams
 
Reactive microservices with play and akka
Reactive microservices with play and akkaReactive microservices with play and akka
Reactive microservices with play and akka
 
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメントScalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
 
DWANGO by ドワンゴ
DWANGO by ドワンゴDWANGO by ドワンゴ
DWANGO by ドワンゴ
 
OCTOPARTS by M3, Inc.
OCTOPARTS by M3, Inc.OCTOPARTS by M3, Inc.
OCTOPARTS by M3, Inc.
 
Try using Aeromock by Marverick, Inc.
Try using Aeromock by Marverick, Inc.Try using Aeromock by Marverick, Inc.
Try using Aeromock by Marverick, Inc.
 
統計をとって高速化する
Scala開発 by CyberZ,Inc.
統計をとって高速化する
Scala開発 by CyberZ,Inc.統計をとって高速化する
Scala開発 by CyberZ,Inc.
統計をとって高速化する
Scala開発 by CyberZ,Inc.
 
Short Introduction of Implicit Conversion by TIS, Inc.
Short Introduction of Implicit Conversion by TIS, Inc.Short Introduction of Implicit Conversion by TIS, Inc.
Short Introduction of Implicit Conversion by TIS, Inc.
 
ビズリーチ x ScalaMatsuri by BIZREACH, Inc.
ビズリーチ x ScalaMatsuri  by BIZREACH, Inc.ビズリーチ x ScalaMatsuri  by BIZREACH, Inc.
ビズリーチ x ScalaMatsuri by BIZREACH, Inc.
 
sbt, past and future / sbt, 傾向と対策
sbt, past and future / sbt, 傾向と対策sbt, past and future / sbt, 傾向と対策
sbt, past and future / sbt, 傾向と対策
 

Recently uploaded

A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfDrew Moseley
 
Software Coding for software engineering
Software Coding for software engineeringSoftware Coding for software engineering
Software Coding for software engineeringssuserb3a23b
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Developmentvyaparkranti
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 

Recently uploaded (20)

A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdf
 
Software Coding for software engineering
Software Coding for software engineeringSoftware Coding for software engineering
Software Coding for software engineering
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Development
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 

Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング

  • 2. Ngoc Dao https://github.com/ngocdaothanh Takeharu Oshida https://github.com/georgeOsdDev http://mobilus.co.jp/
  • 3. What is Xitrum? Xitrum is an async and clustered ! Scala web framework and HTTP(S) server ! on top of Netty, Akka
  • 4. Why you should use Xitrum? • Featureful! • Easy to use! • High performance Scala, Netty, and Akka are fast! • Scalable Can scale to a cluster of servers using Akka cluster and/or Hazelcast
  • 5. Homepage: http://xitrum-framework.github.io/ (there are various demos) Guides (English, Japanese, Russian): http://xitrum-framework.github.io/guide.html (Korean version is in progress) ! Community (Google Group): https://groups.google.com/forum/#!forum/ xitrum-framework
  • 6. Where Xitrum is used? KONNECT (Messaging Service)! http://mobilus.co.jp/konnect/! ! KONNECT can be used in mobile games, mobiles apps, SNS websites etc. Xitrum is also being used in France, Korea, Russia, Singapore etc.
  • 8. 2010-2013 Xitrum 1.x-2.x http://bit.ly/xitrum13 2014 Xitrum 3.x • Netty 4.x • Swagger • Component • FileMonitor, i18n • CORS • WebJARs • Glokka • Agent7 (autoreload classes on change) ! ! http://bit.ly/xitrum-changelog !
  • 10. Client Netty Async Dispatch request Action FutureAction ActorAction Akka Xitrum I/O thread pool to accept requests and reply responses Thread pool to run FutureAction and ActorAction Client Run directly on Netty I/O thread Netty handler Netty handler Netty handler Netty handler Xitrum Your program
  • 12. Client Client Client Akka cluster (code)! Hazelcast (data) Client Netty Xitrum A FA AA Akka Netty Xitrum A FA AA Akka Server N Server N+1
  • 13. Embed Xitrum object MyApp { def main(args: Array[String]) { ... // Somewhere in your app xitrum.Server.start() ... } 1. Collect routes! } ! 2. Start HTTP/HTTPS servers
  • 14. Action example import xitrum.Action import xitrum.annotation.GET ! @GET("hello") class MyAction extends Action { def execute() { respondText("Hello") } } FutureAction! ActorAction
  • 15. Annotations: Scala vs Java Scala: @GET("matsuri", "festival") Java: @GET(Array("matsuri", "festival")) ! Scala: case class GET(paths: String*) extends scala.annotation.StaticAnnotation ! Java: public @interface GET { String[] value(); }
  • 16. Benefits of using annotations Routes in .class and .jar in classpath are automatically collected and merged. A.class B.class lib1.jar lib2.jar Routes
  • 17. Problem with annotations Collecting routes from .class and .jar files is slow.! ! Solutions:! • In development mode, routes in .class and .jar files that are not in the current working directory are cached to file routes.cache. • To avoid loading lots of classes, don't collect routes from: java.xxx, javax.xxx, scala.xxx, sun.xxx, com.sun.xxx
  • 18. Annotations defined by Xitrum:! http://bit.ly/xitrum-annotations! ! Lib to scan classes in classpath to collect routes:! https://github.com/xitrum-framework/sclasner
  • 19. Demo overview GET / GET /chat username password login Hello ! Hello! How are you? Fine message send POST /login SockJS /connect https://github.com/xitrum-framework/matsuri14
  • 20. Demo overview • Simple HTTP CRUD with MongoDB POST /admin/user GET /admin/user GET /admin/user/:userId PUT /admin/user/:userId DELETE /admin/user/:userId PUT/PATCH/DELETE can be emulated via POST with _method=PUT/PATCH/DELETE ! • API documentation with Swagger
  • 21. DB Cluseter Xitrum1 Akka Hazelcast Xitrum2 Akka Hazelcast Xitrum3 Cluster LB (HAProxy, Nginx, Route53 etc.) NoSQL RDB Other services Akka Hazelcast https://github.com/xitrum-framework/glokka https://github.com/xitrum-framework/xitrum-hazelcast
  • 22.
  • 23. Getting started with xitrum-new skeleton https://github.com/xitrum-framework/xitrum-new https://github.com/xitrum-framework/xitrum-scalate
  • 24. @GET("admin") class AdminIndex extends Action { def execute() { // Get all users val users = User.listAll() // Pass users to view template at("users") = users ! // Response respons view with template respondView() } } ActorAction FutureAction Action
  • 25. - import matsuri.demo.action._! - import matsuri.demo.model.User! ! div.row#usersTable! table.table.table-striped#messageTable! thead! tr.bg-primary! View • Scalate template with jade (mustache, scaml, or ssp) • "at" function • i18n with GNU gettext th.col-xs-2 =t("Name")! th.col-xs-2 =t("Age")! th.col-xs-2 =t("Desc")! th.col-xs-2 =t("Created time")! th.col-xs-2 =t("Updated time")! th.col-xs-2 =t("Last login time")! tbody! - for (user <- at("users").asInstanceOf[List[User]])! tr! th! a(href={url[AdminUserShow](("name", user.name))}) = user.name! th = user.age! th = user.desc! th = user.createdAtAsStr! th = user.updatedAtAsStr! th = user.lastLoginAsStr
  • 26. └── src └── scalate └── matsuri └── demo └── action ├── AdminIndex.jade └── DefaultLayout.jade package matsuri.demo.action ! import xitrum.Action ! trait DefaultLayout extends Action { override def layout = renderViewNoLayout[DefaultLayout]() } Layout
  • 27. !!! 5 html head != antiCsrfMeta != xitrumCss ! meta(content="text/html; charset=utf-8" http-equiv="content-type") title ScalaMatsuri2014 Xitrum Demo ! link(rel="shortcut icon" href={publicUrl("favicon.ico")}) link(type="text/css" rel="stylesheet" media="all" href={webJarsUrl("bootstrap/3.2.0/css", "bootstrap.css", "bootstrap.min.css")}) link(type="text/css" rel="stylesheet" media="all" href={publicUrl("app.css")}) ! body .container h1 ! #flash !~ jsRenderFlash() != renderedView Layout ! != jsDefaults script(src={webJarsUrl("bootstrap/3.2.0/js", "bootstrap.js", "bootstrap.min.js")}) script(src={webJarsUrl("underscorejs/1.6.0", "underscore.js", "underscore-min.js")}) != jsForView
  • 28. form(role="form" method="post" action={url[AdminUserCreate]}) != antiCsrfInput div.modal-header button.close(type="button" data-dismiss="modal") Form span(aria-hidden="true") &times; span.sr-only =t("Close") h4.modal-title#myModalLabel =t("Create New User") div.modal-body div.form-group label(for="newUserName") =t("Name") input.form-control#newUserName(name="name" type="text" • "url" function • jquery-validation • Anti csrf token placeholder={t("Enter Name")} minlength=5 maxlenght=10 required=true) div.form-group label(for="newUserPass") =t("Password") input.form-control#newUserPass(name="password" type="password" placeholder={t("Enter Password")} minlength=8 required=true) ! div.modal-footer button.btn.btn-default(type="button" data-dismiss="modal") = t("Cancel") button.btn.btn-primary(type="submit") = t("Save")
  • 29. @POST("admin/user") class AdminUserCreate extends AdminAction { def execute() { // Get request paramaters val name = param("name") val password = param("password") // Optional parameters val age = paramo[Int]("age") val desc = paramo("desc") ! Required.exception("name", name) Required.exception("password", password) ! User.create(name, password, age, desc) flash(t("Success")) redirectTo[AdminIndex]() } Get request params with param(s) and param(o)
  • 30. object SVar { object isAdmin extends SessionVar[Boolean] } Use before filter to check trait AdminFilter { this: Action => ! beforeFilter { if (SVar.isAdmin.isDefined) true else authBasic() } ! private def authBasic(): Boolean = { basicAuth(Config.basicAuth.realm) { (username, password) => if (username == Config.basicAuth.name && password == Config.basicAuth.pass) { SVar.isAdmin.set(true) true } else { false } } } authentication info in session
  • 31. @Swagger( Swagger.Summary("Create User"), Swagger.Response(200, "status = 0: success, 1: failed to create user"), Swagger.Response(400, "Invalid request parameter"), Swagger.StringForm("name"), Swagger.StringForm("password"), Swagger.OptIntForm("age"), Swagger.OptStringForm("desc") ) API doc • /xitrum/swagger • /xitrum/swagger-ui • Create test client with Swagger-codegen https://github.com/wordnik/swagger-ui https://github.com/wordnik/swagger-codegen https://github.com/wordnik/swagger-spec
  • 32. @GET("login", "") class LoginIndex extends DefaultLayout { def execute() { respondView() } } ! @POST("login") class Login extends Action { def execute() { session.clear() val name = param("name") val password = param("password") ! User.authLogin(name, password) match { case Some(user) => SVar.userName.set(user.name) redirectTo[ChatIndex]() ! case None => flash(t(s"Invalid username or password")) redirectTo[LoginIndex]() } } } Login
  • 33. jsAddToView( "var url = '" + sockJsUrl[ChatAction] + "';" + """ var socket; var initSocket = function() { socket = new SockJS(url); socket.onopen = function(event) { console.log("socket onopen", event.data); socket.send(JSON.parse({"msg":"Hello Xitrum"})); }; socket.onclose = function(event) {console.log("socket onclose", event.data);}; socket.onmessage = function(event) {console.log("socket onmessage", event.data);}; }; initSocket(); """ ) != jsDefaults script(src={webJarsUrl("bootstrap/3.2.0/js", "bootstrap.js", "bootstrap.min.js")}) script(src={webJarsUrl("underscorejs/1.6.0", "underscore.js", "underscore-min.js")}) != jsForView • jsAddToView/jsForView • sockJsUrl • webJarsUrl Create chat client with SockJS
  • 34. import xitrum.{SockJsAction, SockJsText} import xitrum.annotation.SOCKJS ! @SOCKJS("connect") class ChatAction extends SockJsAction with LoginFilter { def execute() { context.become { SockJsAction (an Actor) case SockJsText(text) => SeriDeseri.fromJson[Map[String, String]](text) match { case Some(jsonMap) => // echo respondSockJsText(SeriDeseri.toJson(jsonMap)) case None => log.warn(s"Failed to parse request: $text") respondSockJsText("invalid request") } Create } • SockJsAction • SockJsText/respondSockJsText • SeriDeseri.fromJson[T] / SeriDeseri.toJson(ref:AnyRef)
  • 35. Lookup singleton Actor with Glokka Xitrum socket open Client HubActor trait Hub extends Actor { protected var clients = Seq[ActorRef]() def receive = { case Subscribe(option) => clients = clients :+ sender case Unsubscribe(option) => clients = clients.filterNot(_ == sender) case Terminated(client) => clients = clients.filterNot(_ == client) case ignore => } import glokka.Registry object Hub { val KEY_PROXY = "HUB_PROXY" val actorRegistry = Registry.start(Config.actorSystem, KEY_PROXY) } ! def lookUpHub(key: String, hubProps: Props, option: Any = None) { Hub.actorRegistry ! Registry.Register(key, hubProps) context.become { hub ! Subscribe ChatAction ChatAction ChatAction ChatAction case result: Registry.FoundOrCreated => result.ref ! Subscribe } } Client Client Client https://github.com/xitrum-framework/glokka
  • 36. Messaging overview SockJsText! (socket.send) hub ! Push(msg) clients.foreach { _ ! Publish(msg)} respondSockJSText(msg:String) Client ChatAction HubActor socket.onmessage SockJsText hub ! Pull(msg) case class Done (option: Map[String, Any] = Map.empty) // Hub -> Action case class Publish(option: Map[String, Any] = Map.empty) // Hub -> Action case class Pull (option: Map[String, Any] = Map.empty) // Action -> Hub case class Push (option: Map[String, Any] = Map.empty) // Action -> Hub https://github.com/georgeOsdDev/glokka-demo ChatAction Client ChatAction ChatAction Client Client respondSockJSText(msg:String) sender ! Done(msg) Client ChatAction HubActor respondSockJSText(msg:String) sender ! Done(msg) socket.onmessage
  • 37. Cluster config for Hazelcast hazelcastMode = clusterMember ! cache = xitrum.hazelcast.Cache #cache { # # Simple in-memory cache # "xitrum.local.LruCache" { xitrum.conf # maxElems = 10000 # } • Xitrum-hazelcast #} • Shared Session • Shared Cache ! session { store = xitrum.hazelcast.Session # Store sessions on client side #store = xitrum.scope.session.CookieSessionStore
  • 38. akka { loggers = ["akka.event.slf4j.Slf4jLogger"] logger-startup-timeout = 30s ! actor { provider = "akka.cluster.ClusterActorRefProvider" } ! # This node remote { log-remote-lifecycle-events = off netty.tcp { hostname = "127.0.0.1" port = 2551 # 0 means random port } } ! cluster { seed-nodes = [ "akka.tcp://xitrum@127.0.0.1:2551", "akka.tcp://xitrum@127.0.0.1:2552"] ! auto-down-unreachable-after = 10s } } Cluster config for Akka
  • 39. Live class reload during development https://github.com/xitrum-framework/agent7 https://github.com/dcevm/dcevm java -javaagent:`dirname $0`/agent7-1.0.jar -XXaltjvm=dcevm -Xms256M -Xmx512M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=384M -jar `dirname $0`/sbt-launch-0.13.5.jar "$@" https://github.com/xitrum-framework/xitrum-package
  • 40. Package project for deploying to production server https://github.com/xitrum-framework/xitrum-package sbt/sbt xitrum-package
  • 41. Monitor Xitrum in production mode • Scalive • Metrics • Log to fluentd https://github.com/xitrum-framework/scalive http://www.slideshare.net/georgeosd/scalive http://xitrum-framework.github.io/guide/3.18/en/ log.html#log-to-fluentd