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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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
AI駆動開発で崩れていくコードベースを立て直す
kyoko_nr_nr
1
400
代数的データ型って何が嬉しいの? #frontend_phpcon_do
kajitack
7
2.4k
New "Type" system on PicoRuby
pocke
1
390
1人1案件のプロダクトエンジニア時代に、"プロセス監督"としてチャレンジしたこと
non0113
0
360
AI時代の仕事技芸論 — ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ
kuranuki
1
540
TSKaigi 2026 TypeScriptバックエンドのオブザーバビリティ戦略 — Datadog × NestJSの実践
taiseiyamamotoan
1
210
Why Laravel apps break—Mastering the fundamentals to keep them maintainable
kentaroutakeda
1
320
These Five Tricks Can Make Your Apps Greener, Cheaper, & Nicer
hollycummins
0
250
生成AI時代にこそ効くGo | Why Go Works in the Age of Generative AI
mom0tomo
8
3k
タクシーアプリ『GO』の バックエンド開発のおける AI利活用と若者のすべて
pyama86
3
1.8k
脅威をエンジニアリングの糧にして――現場編 / Turning Threats into Engineering Fuel — Field Edition
nrslib
0
220
RailsTokyo 2026#4: AI様があれば、 Hotwireの弱点は消えるか?
naofumi
5
1k
Featured
See All Featured
The Mindset for Success: Future Career Progression
greggifford
PRO
0
340
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
160
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
270
Designing for humans not robots
tammielis
254
26k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
150
So, you think you're a good person
axbom
PRO
2
2k
The browser strikes back
jonoalderson
0
1.1k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.1k
Joys of Absence: A Defence of Solitary Play
codingconduct
1
380
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
280
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.1k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.3k
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?