Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Two Scoops of Scala
Search
Kārlis Lauva
April 09, 2014
Programming
120
0
Share
Two Scoops of Scala
April tech talk at FullContact
Kārlis Lauva
April 09, 2014
More Decks by Kārlis Lauva
See All by Kārlis Lauva
Let's talk about PureScript
karlis
0
87
Going Full Monty with full.monty
karlis
1
100
The Transatlantic Struggle
karlis
0
82
Valsts pārvaldes atvērto datu semantiskās integrācijas procesi
karlis
1
200
Tornado in 1 Hour (or Less)
karlis
4
200
Other Decks in Programming
See All in Programming
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.2k
色即是空、空即是色、データサイエンス
kamoneggi
1
240
PHPで使える日時の表現と、その知り方 #frontend_phpcon_do
o0h
PRO
0
140
運用エージェントは "作る" から "育てる" へ - 記憶と自己進化の3層設計パターン / self-evolving-agents-three-layer-agent-design
gawa
12
3.3k
Modding RubyKaigi for Myself
yui_knk
0
830
脅威をエンジニアリングの糧にして――現場編 / Turning Threats into Engineering Fuel — Field Edition
nrslib
0
220
プロパティの順序で型推論が壊れる!? TypeScript6.0の修正からContext-Sensitivityの仕組みを追う
bicstone
2
1.3k
CSC307 Lecture 17
javiergs
PRO
0
290
初めてのRubyKaigiはこう見えた
jellyfish700
0
370
サーバーレスで作る、動画データ管理基盤
oyasumipants
0
320
新規プロダクトを高速で生み出すハーネスエンジニアリング
seanchas116
18
7.6k
Stage 3 Decorators でできること / できないこと / TSKaigi 2026
susisu
1
1.4k
Featured
See All Featured
Deep Space Network (abreviated)
tonyrice
0
160
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.3k
Automating Front-end Workflow
addyosmani
1370
210k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
150
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Odyssey Design
rkendrick25
PRO
2
650
ラッコキーワード サービス紹介資料
rakko
1
3.5M
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
350
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
240
Fashionably flexible responsive web design (full day workshop)
malarkey
408
66k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
520
Done Done
chrislema
186
16k
Transcript
Two scoops of Scala & Unfiltered April 2014 FullContact techTalk
@skazhy
Scala? • object oriented and functional programming language • Type
safe • Runs on JVM
Unfiltered? • A toolkit for HTTP in Scala • Really,
really modular • Works with Netty and Jetty • Built for meetup.com realtime API • Makes good use of Scala's idioms
Toolchain • SBT - Scala Build Tool • Best conventions
from Maven world • Iterative development in SBT shell
My setup • IntelliJ + SBT console(s) inside tmux •
IntelliJ 13 has SBT support baked in
Deployment • Works great with Jenkins & Asgard • Minimal
configuration tweaks needed (wait for the next slide)
• A tool for fetching templates for Scala projects •
g8 skazhy/unfiltered-netty-rx • All SBT plugins for deployment and IntelliJ are included Bootstrapping with giter8
Using opinionated RESTful frameworks for microservices?
None
Example time!
object MyPlan extends cycle.Plan with cycle.ThreadPool with ServerErrorResponse { def
intent = { case GET(Path("/")) => ResponseString("Hello!") case OPTIONS(_) => Created ~> Location("/foo") case _ => NotFound } } unfiltered.netty.Http(1337).handler(MyPlan).run()
An Intent is a partial function that pattern matches HTTP
requests
A Plan is a binding between intent and the underlying
interface
Pattern matching • Decomposing data structures to extract certain fields
or validate them • Really powerful in Scala • “routing” mechanism in Unfiltered
None
Match on request methods • Use builtins: GET(_) POST(_) PATCH(_)
• Or define your own: object SPACEJUMP extends Method("SPACEJUMP")
What happens under the hood? class Method(method: String) { def
unapply[T](req: HttpRequest[T]) = if (req.method.equalsIgnoreCase(method)) Some(req) else None } object POST extends Method("POST")
Match on request headers BasicAuth(username, password) UserAgent("Cobook")
...on URN Path("/foobar") Path(Seg("contactLists" :: "v2" :: listId :: Nil))
// Will extract /contactLists/v2/1234
...or query parameters object AccountIdParam extends Params.Extract("numericId", Params.first ~> Params.nonempty
~> Params.long) PATCH(Params(AccountIdParam(accountId))) // Will extract 1234 from PATCH /foo?numericId=1234
None
function composition!
Responses are composable case _ => Unauthorized ~> ResponseString("No pasaran")
~> ResponseHeader("WWW-Authenticate", "Basic realm=foo")
• HTTP requests are stateless • HTTP responses are side
effects
Async made easy case req @ GET(Path("/async")) => val futureOp
= asyncOperation futureOp.onSuccess { case result => req.respond(Ok ~> ResponseString(result)) } futureOp.onFailure { case _ => req.respond(InternalServerError) }
Unfiltered plays well with RxJava too
case req @ GET(Path("/reactive")) => observableOp.subscribe( result => req.respond(ResponseString(result)) _
=> req.respond(InternalServerError) )
What about testing?
• Separate library for testing with Specs2 • Mocking with
Mockito • Comes bundled with the giter8 template unfiltered-specs2
object OperationPostSpec extends Specification { "PATCH /foo" should { lazy
val r = Http(url((host \ "foo").PATCH)) lazy val response = r() "return HTTP 200" in { response.getResponseStatus mustEqual 200 } } }
Consider using Unfiltered when you... • need an async &
lightweight HTTP service • Have separate business logic • Want to leverage the λ-force
Questions?