Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Two Scoops of Scala
Kārlis Lauva
April 09, 2014
Programming
0
88
Two Scoops of Scala
April tech talk at FullContact
Kārlis Lauva
April 09, 2014
Tweet
Share
More Decks by Kārlis Lauva
See All by Kārlis Lauva
Let's talk about PureScript
karlis
0
61
Going Full Monty with full.monty
karlis
1
67
The Transatlantic Struggle
karlis
0
48
Valsts pārvaldes atvērto datu semantiskās integrācijas procesi
karlis
0
84
Tornado in 1 Hour (or Less)
karlis
4
170
Other Decks in Programming
See All in Programming
Windows コンテナ Dojo 第5回 OpenShift で学ぶ Kubernetes 入門
oniak3ibm
PRO
0
180
테라폼으로 ECR 관리하기 (How to Manage ECR with Terraform)
posquit0
0
530
Rector, time to refactor your code easily
guikingone
2
150
パスワードに関する最近の動向
kenchan0130
1
330
2022年のモダンCSS改
tonkotsuboy_com
24
16k
10歳の minne から、これから長く続くプロダクトを作るすべての人へ
tsumichan
9
3.6k
僕が便利だと感じる Snow Monkey の特徴/20220723_Gifu_WordPress_Meetup
oleindesign
0
110
Automating Gradle benchmarks at N26
ubiratansoares
PRO
1
140
OSS貢献を気軽にしたい Let's Go Talk #1
yuyaabo
2
240
2022 - COSCUP - 打造高速 Ruby 專案開發流程
elct9620
0
100
Google I/O 2022 Android関連概要 / Google I/O 2022 Android summary
phicdy
0
390
Amazon Lookout for Visionで 筆跡鑑定してみた
cmnakamurashogo
0
160
Featured
See All Featured
Music & Morning Musume
bryan
35
4.3k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
498
130k
Why You Should Never Use an ORM
jnunemaker
PRO
47
7.6k
How to Ace a Technical Interview
jacobian
266
21k
How GitHub Uses GitHub to Build GitHub
holman
465
280k
The Illustrated Children's Guide to Kubernetes
chrisshort
18
40k
For a Future-Friendly Web
brad_frost
166
7.5k
Fantastic passwords and where to find them - at NoRuKo
philnash
27
1.6k
5 minutes of I Can Smell Your CMS
philhawksworth
196
18k
KATA
mclloyd
7
8.8k
Why Our Code Smells
bkeepers
PRO
324
55k
How to name files
jennybc
40
63k
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?