SlideShare uma empresa Scribd logo
1 de 45
Baixar para ler offline
Scala Italy 25 may 2013
Scalatra comparison with SpringMVC
Massimiliano Dessì
1
Monday, May 27, 13
GDG Sardegna
Speaker
Max has more than 13 years of experience in programming. He’s a
proud father of three.
Manager of GTUG Sardegna, Founder of SpringFramework IT,
co-founder of Jug Sardegna.
Author of Spring 2.5 AOP.
He works in Energeya as a Product Architect and lives in Cagliari,
Italy.
2
Monday, May 27, 13
GDG Sardegna
Scalatra - SpringMVC
CRUD HTML
REST
JSON
Routing
Template
Security
Agenda
3
Monday, May 27, 13
GDG Sardegna
Spring , Since 2004 - Java Full Stack - Lot of people involved
now property of VMware
Scalatra , Since 2009 - Scala Http Microframework (DSL)
the BBC, LinkedIn,
the Guardian,
games website IGN,
UK government
rely on Scalatra.
Some info
4
Monday, May 27, 13
GDG Sardegna
REST
class JellyBeans extends ScalatraServlet {
get("/jellybs/:id") { ... }
post("/jellybs") { ... }
put("/jellybs/:id") { ... }
delete("/jellybs/:id") { ... }
}
For browser add PUT & DELETE support client side
X-HTTP-METHOD-OVERRIDE or _method=put _method=delete in the post body
class JellyBeansBrowser extends ScalatraFilter with MethodOverride
5
Monday, May 27, 13
GDG SardegnaMassimiliano Dessì
Routes
class JellyBeans extends ScalatraServlet {
get("/jellybs/:id") {
val id:Int = params.getOrElse("id", halt(400)).toInt
...
}
get("/jellybs/download/*.*") { //with wildcard
...
}
get("""^/j(.*)/f(.*)""".or) { //REGEX
...
}
post("/jellybs", request.getRemoteHost == "127.0.0.1",
request.getRemoteUser == "admin") {
....
}
6
Monday, May 27, 13
GDG Sardegna
REST
@Controller
public class JellyBeansController{
@RequestMapping(value = "/jellybs/{id}", method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK) //Http 200
public @ResponseBody JellyB getItem(@PathVariable("id") Integer id) {...}
@RequestMapping(value = "/jellybs", method = RequestMethod.POST) //Http 201
@ResponseStatus(HttpStatus.CREATED) //Http 201
public void createJelly(HttpServletRequest req, HttpServletResponse res,
@RequestBody JellyB item) { ... }
@RequestMapping(value = "/jellybs/{id}", method = RequestMethod.PUT)
@ResponseStatus(HttpStatus.NO_CONTENT) //Http 204
public void updateItem(@RequestBody JellyB item, @PathVariable("id") Integer id)
{ ... }
@RequestMapping(value = "/items/{id}", method = RequestMethod.DELETE)
@ResponseStatus(HttpStatus.NO_CONTENT)//204
public void deleteItem(@PathVariable("id") String id) { ... }
}
For browser add PUT & DELETE support client side
X-HTTP-METHOD-OVERRIDE or _method=put _method=delete in the post body
<filter>
<filter-name>hiddenMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
7
Monday, May 27, 13
GDG Sardegna
Routes
class JellyBeans extends ScalatraServlet {
get("/jellybs/:id") {
val id:Int = params.getOrElse("id", halt(400)).toInt
...
}
get("/jellybs/download/*.*") { //with wildcard
...
}
get("""^/j(.*)/f(.*)""".or) { //REGEX
...
}
post("/jellybs", request.getRemoteHost == "127.0.0.1",
request.getRemoteUser == "admin") {
....
}
8
Monday, May 27, 13
GDG Sardegna
HandlerMapping
@Controller
public class JellyBeansController{
@RequestMapping(value="/jelly.pdf",method = RequestMethod.GET)
public ModelAndView pdf(HttpServletRequest req,@RequestParam String id)
{
...
}
@RequestMapping(value = "/jellybs/{id}", method = RequestMethod.GET)
public String getItem(@PathVariable("id") Integer id) {
...
}
@RequestMapping(value = "/jellybs", method = RequestMethod.POST)
public void createJelly(@ModelAttribute(”jelly”) JellyB jelly) {
...
}
}
DefaultAnnotationHandlerMapping
SimpleUrlHandlerMapping
ControllerClassNameHandlerMapping
9
Monday, May 27, 13
GDG Sardegna
Filter
class JellyBeans extends ScalatraServlet {
before() {
db.acquireConnecion
contentType="text/html"
}
get("/") {
val menu = db.findWelcome()
templateEngine.layout("index.ssp", menu)
}
after() {
db.releaseConnection
}
}
Like Servlet Filter
(or Aspect Oriented Programming)
You can add logic before or the
routes
10
Monday, May 27, 13
GDG Sardegna
Handler Interceptor
public interface HandlerInterceptor{
//before call method’s controller
boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler)
throws Exception;
//after call method’s controller
void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler,
ModelAndView mav) throws Exception;
//after view render()
void afterCompletition(HttpServletRequest req, HttpServletResponse res, Object
handler, Exception ex) throws Exception;
}
Handler mapped on all controllers (as a property of Handlermapping config)
or mapped on url path with <mvc:interceptors> tags
Like Servlet Filter
(or Aspect Oriented Programming)
You can add logic before or after
the controllers methods
11
Monday, May 27, 13
GDG Sardegna
Handlers
Handlers are top level methods for http routines
class JellyBeans extends ScalatraServlet {
notFound {
<h1>Not found</h1>
}
halt(status = 301, headers =
Map("Location" -> "http://www.codemotion.com/"))
get("/jellybs/names/*") {
"Name not found!"
}
}
12
Monday, May 27, 13
GDG Sardegna
Handlers
class JellyBeans extends ScalatraServlet {
get("/jellybs/names/:who") {
params("who") match {
case "Cherry" => "Found Cherry!"
case _ => pass() /* call the next matching route route, routes are
matched from bottom up*/
}
}
get("/jellybs/download/:id") {
jellyBeanService.find(params("id")) match {
case Some(jellybean) => Ok(jellybean)
case None => NotFound("Sorry, jellybean not found")
}
}
}
13
Monday, May 27, 13
GDG Sardegna
Request Response & Friends
class JellyBeans extends ScalatraServlet {
get("/jellybs/shows/:id") {
//access to request,response, session and params
request.body //request body as a string
request.cookies // cookie map
request.isAjax // is ajaxRequest
request.getSession // HttpServletSession
request.locale // user locale
response.getOutputStream //response outputstream
servletContext.get("myIntParam") //servlet context
val idString = params("id")
val id = params.getAs[Int]("id")
//val id = params.getOrElse("id", halt(500)) //another way
....
}
}
14
Monday, May 27, 13
GDG Sardegna
Request Response & Friends
class JellyBeans extends ScalatraServlet {
get("/jellybs/*/conf/*") {
// Matches "GET /jellybs/one/conf/two"
multiParams("splat") // Seq("one", "two")
//wildcard accessible with key splat
}
get("""^/jelly(.*)/fla(.*)""".r) {
// Matches "GET /jellybs/flavor"
multiParams("captures") // == Seq("bs", "vor")
}
}
15
Monday, May 27, 13
GDG Sardegna
Gzip
class GzipJellyBeans extends ScalatraServlet with GZipSupport{
get("/") {
<html>
<body>
<h1>This is
<a href="http://en.wikipedia.org/wiki/Sparta">Sparta</a>!
</h1>
</body>
</html>
}
}
16
Monday, May 27, 13
GDG Sardegna
Flash message
class FlashServlet extends ScalatraServlet with FlashMapSupport{
post("/jellybs/create") {
flash("notice") = "jellybean created successfully"
redirect("/home") //redirect
}
get("/home") {
ssp("/home") //Scala Server Pages
}
17
Monday, May 27, 13
GDG Sardegna
ExceptionResolvers
<bean id="exceptionResolver"
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.springframework.web.HttpSessionRequiredException">welcome</prop>
...
</props>
</property>
</bean>
or in a annotated @Controller class
@ExceptionHandler
public String requestParamNotPresent(HttpMediaTypeException ex)
18
Monday, May 27, 13
GDG Sardegna
Binding
To avoid manual binding from http and our Object Scalatra provide a binding module
case class MyClass(id: Integer, name: String)
post("/myroute") {
val cmd = command[CreateMyClassCommand]
...
}
19
Monday, May 27, 13
GDG Sardegna
Binding
Under the hood
abstract class MyClassCommand[S](implicit mf: Manifest[S])
extends ModelCommand[S] with JsonCommand {
  
implicit def todoStringValidators(b: FieldDescriptor[String]) =
new MyClassStringValidations(b)
}
class CreateMyClassCommand extends MyClassCommand[MyClass] {
protected implicit val jsonFormats = DefaultFormats
val name: Field[String] = asType[String]("name").notBlank.minLength(3)
}
20
Monday, May 27, 13
GDG Sardegna
Binding
Under the hood
class MyClassStringValidations(b: FieldDescriptor[String]) {
def startsWithCap(message: String = "%s must start with a capital letter.") =
b.validateWith(_ =>
     _ flatMap {
new PredicateValidator[String](
b.name,
"""^[A-Z,0-9]""".r.findFirstIn(_).isDefined,
message).validate(_)
   )
}
)
}
21
Monday, May 27, 13
GDG Sardegna
CommandObject
@RequestMapping(value = "/items/{id}", method = RequestMethod.PUT)
@ResponseStatus(HttpStatus.NO_CONTENT)
public String updateItem(JellyB item) {
...
}
Spring bind the request body on the object used in the method (JellyB)
Objects Validation with jsr 303 annotation or with Validator Spring Interface
Error message with JSP/JSTL tags
22
Monday, May 27, 13
GDG Sardegna
Upload
import org.scalatra.ScalatraServlet
import org.scalatra.servlet.FileUploadSupport
import javax.servlet.annotation.MultipartConfig
@MultipartConfig(maxFileSize=10*1024)
trait StorageRoutes extends FileUploadSupport {
self: ScalatraServlet =>
}
23
Monday, May 27, 13
GDG Sardegna
JSON
Automatic Serialization and deserialization of any Case class
object JSONServlet extends ScalatraServlet with JacksonJsonSupport{
case class JellyBean(id: Int, name: String, flavor:String)
protected implicit val jsonFormats: Formats = DefaultFormats
before() {
contentType = formats("json")
}
....
24
Monday, May 27, 13
GDG Sardegna
Actors
The routes can returns a Future
class MyActorServlet(system:ActorSystem, myActor:ActorRef)
extends ScalatraServlet with FutureSupport {
import _root_.akka.pattern.ask
implicit val timeout = Timeout(10)
protected implicit def executor: ExecutionContext = system.dispatcher
get("/async") {
myActor ? "Do stuff and give me an answer"
}
get("/fire-forget") {
myActor ! "Hey, you know what?"
Accepted() //if you do not want return a future
}
}
25
Monday, May 27, 13
GDG Sardegna
Actors
get("/async") {
myActor ? "Do stuff and give me an answer"
}
get("/fire-forget") {
myActor ! "Hey, you know what?"
Accepted() //if you don’t want return a future
}
class CodemotionActor extends Actor {
def receive = {
case "Do stuff and give me an answer" => sender ! "The answer is 42"
case "Hey, you know what?" => println("Yeah I know...")
}
}
}
26
Monday, May 27, 13
GDG Sardegna
Akka
Akka start in the Bootstrap of Scalatra
class ScalatraBootstrap extends LifeCycle {
val system = ActorSystem()
val codemotionActor = system.actorOf(Props[CodemotionActor])
override def init(context: ServletContext) {
context.mount(new JSONServlet, "/jellybs/*")
context.mount(new FrontServlet, "/template/*")
context.mount(new MyActorServlet(system, codemotionActor), "/actors/*")
}
override def destroy(context:ServletContext) {
system.shutdown()
}
}
27
Monday, May 27, 13
GDG Sardegna
Deployment
Scalatra is based on regular Java Servlet 3.0
it can start from:
Standalone from jetty embedded
From Servlet container
Heroku
Jelastic
CloudBees
GAE (not out of the box )
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<listener>
<listener-class>org.scalatra.servlet.ScalatraListener</listener-class>
</listener>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/img/*</url-pattern>
<url-pattern>/css/*</url-pattern>
<url-pattern>/js/*</url-pattern>
<url-pattern>/assets/*</url-pattern>
</servlet-mapping>
</web-app>
28
Monday, May 27, 13
GDG Sardegna
JSON
Automatic Serialization and deserialization of any Case class
object JSONServlet extends ScalatraServlet with JacksonJsonSupport{
...
get("/jellybs/all"){
jellyBeanRepo.all //from class to json
}
post("/jellybs/create") {
val jb = parsedBody.extract[JellyBean] //from json to class
...
}
}
29
Monday, May 27, 13
GDG Sardegna
JSON
30
JSON with third party lib es Jackson
@JsonCreator
public JellyB(Map map) {...}
@JsonAnyGetter
public Map toMap() {...}
Automatic binding
public @ResponseBody JellyB getItem(...)
public void updateItem(@RequestBody JellyB item)
Monday, May 27, 13
GDG Sardegna
Template
Html inline,
Scalate
Twirl (Play2 template)
Scalate
mean
SSP (Scala Server Page)
Scaml
Mustache
Jade
31
Monday, May 27, 13
GDG Sardegna
Template
class ScalateServlet extends ScalatraServlet with ScalateSupport{
get("/"jellybeans/ssp) {
contentType="text/html"
ssp("/index", "foo" -> "uno", "bar" -> "two")
// the layout used it’s WEB-INF/layouts/default.ssp
}
get("/jellybeans/jade") {
jade("/index", "layout" -> "", "foo" -> "one", "bar" -> "two")
// render without a layout.
}
get("/jellybeans/direct") {
templateEngine.layout("/jellybeans/index.ssp")
//direct invoking of scalate
}
32
Monday, May 27, 13
GDG Sardegna
Template
SSP
<%@ var body: String %>
<%@ var title: String = "Some Default Title" %>
<%@ var head: String = "" %>
<html>
<head>
<title>${title}</title>
<%-- page specific head goes here --%>
${unescape(head)}
</head>
<body>
<p>layout header goes here...</p>
${unescape(body)}
<p>layout footer goes here...</p>
</body>
</html>
33
Monday, May 27, 13
GDG Sardegna
Template
JADE
!!! 5
html(lang="en")
head
title= pageTitle
:javascript
if (foo) {
bar()
}
body
h1 Jade - node template engine
#container
- if (youAreUsingJade)
p You are amazing
- else
p Get on it!
:coffeescript
alert "Hello, Coffee!"
34
Monday, May 27, 13
GDG Sardegna
Template
Mustache
Hello {{name}}
You have just won ${{value}}!
{{#in_ca}}
Well, ${{taxed_value}}, after taxes.
{{/in_ca}}
35
Monday, May 27, 13
GDG Sardegna
Template
SCAML
!!! XML
!!!
%html
%head
%title Myspace
%body
%h1 I am the international space station
%p Sign my guestbook
36
Monday, May 27, 13
GDG Sardegna
ViewResolver
JSP, JSTL, Tiles, FreeMarker, XSLT, PDF, Velocity, JExcelApi,
JSON, Atom, RSS, JasperReports
Explicit view with different ViewResolver with different order
values, or with ContentTypeNegotiationViewResolver
mapping different mediaTypes
37
Monday, May 27, 13
GDG Sardegna
Authentication & Security
Scalatra uses Scentry a porting of Ruby Warden authentication
class OurAuthStrategy(protected override val app: ScalatraBase, realm: String)
extends BasicAuthStrategy[User](app, realm) {
protected def validate(userName: String, password: String): Option[User] = {
if(userName == "myusername" && password == "secret") Some(User("myusername"))
else None
}
protected def getUserId(user: User): String = user.id
}
case class User(id: String)
38
Monday, May 27, 13
GDG Sardegna
Authentication & Security
Now we need to combine our strategy and ScentrySupport
trait AuthenticationSupport extends ScentrySupport[User] with BasicAuthSupport[User] {
self: ScalatraBase =>
val realm = "Scalatra Basic Auth Example"
protected def fromSession = { case id: String => User(id) }
protected def toSession = { case usr: User => usr.id }
protected val scentryConfig = (new ScentryConfig {}).asInstanceOf[ScentryConfiguration]
}
39
Monday, May 27, 13
GDG Sardegna
Authentication & Security
Now we need to combine our strategy and ScentrySupport
trait AuthenticationSupport extends ScentrySupport[User] with BasicAuthSupport[User] {
....
override protected def configureScentry = {
scentry.unauthenticated {
scentry.strategies("Basic").unauthenticated()
scentry.strategies("")
}
}
override protected def registerAuthStrategies = {
scentry.register("Basic", app => new OurBasicAuthStrategy(app, realm))
}
protected def validate(userName: String, password: String): Option[User] = {
if(userName == "scalatra" && password == "scalatra") Some(User("scalatra"))
else None
}
}
40
Monday, May 27, 13
GDG Sardegna
Authentication & Security
Now we can use the Authentication for all routes defined in our Authenticated Servlets
class AuthenticatedServlet extends ScalatraServlet with AuthenticationSupport{
//every route goes under authentication
}
Unauthenticated user will see a browser prompt login
41
Monday, May 27, 13
GDG Sardegna
SpringSecurity
FilterServlet to protect urls, roles and AOP intercepting based on User Roles
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<sec:http>
" " <sec:form-login login-page="/login.jsp"
login-processing-url="/j_security_check"
default-target-url="/"
" " " always-use-default-target="true"
authentication-failure-url="/loginError.jsp"/>
" " <sec:logout logout-url="/logout.jsp" invalidate-session="true"
logout-success-url="/login.jsp" />
" " <sec:intercept-url pattern="/styles/**" filters="none"/>
" " <sec:intercept-url pattern="/scripts/**" filters="none"/>
" " <sec:intercept-url pattern="/img/**" filters="none"/>
" " <sec:anonymous username="guest" granted-authority="ROLE_GUEST" />
"
42
Monday, May 27, 13
GDG Sardegna
Test
Test with Specs2
class FrontServletSpec extends ScalatraSpec {
def is =
"GET / on FrontServlet" ^
"should return status 200" ! root200 ^
end
addServlet(classOf[FrontServlet], "/*")
def root200 = get("/") {
status must_== 200
}
}
43
Monday, May 27, 13
GDG Sardegna
Q & A
GTUG Sardegna
44
Monday, May 27, 13
GDG Sardegna
Thanks for your attention!
Massimiliano: @desmax74
GTUG Sardegna
45
Thanks for you attention!
Massimiliano: @desmax74
Monday, May 27, 13

Mais conteúdo relacionado

Semelhante a Scalatra - Massimiliano Dessì (Energeya)

Codemotion 2013 scalatra play spray
Codemotion 2013 scalatra play sprayCodemotion 2013 scalatra play spray
Codemotion 2013 scalatra play sprayrealbot
 
TechDay: Kick Start Your Experience with Android Wear - Mario Viviani
TechDay: Kick Start Your Experience with Android Wear - Mario VivianiTechDay: Kick Start Your Experience with Android Wear - Mario Viviani
TechDay: Kick Start Your Experience with Android Wear - Mario VivianiCodemotion
 
Kick start your experience with android wear - Codemotion Rome 2015
Kick start your experience with android wear - Codemotion Rome 2015Kick start your experience with android wear - Codemotion Rome 2015
Kick start your experience with android wear - Codemotion Rome 2015Codemotion
 
Practical Example of AOP with AspectJ
Practical Example of AOP with AspectJPractical Example of AOP with AspectJ
Practical Example of AOP with AspectJYegor Bugayenko
 
Dependency management & Package management in JavaScript
Dependency management & Package management in JavaScriptDependency management & Package management in JavaScript
Dependency management & Package management in JavaScriptSebastiano Armeli
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your AppLuca Mearelli
 
Big Data processing with Spark, Scala or Java?
Big Data processing with Spark, Scala or Java?Big Data processing with Spark, Scala or Java?
Big Data processing with Spark, Scala or Java?Erik-Berndt Scheper
 
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、GaelykでハンズオンTsuyoshi Yamamoto
 
Private slideshow
Private slideshowPrivate slideshow
Private slideshowsblackman
 
Drupal in aerospace - selling geodetic satellite data with Commerce - Martin ...
Drupal in aerospace - selling geodetic satellite data with Commerce - Martin ...Drupal in aerospace - selling geodetic satellite data with Commerce - Martin ...
Drupal in aerospace - selling geodetic satellite data with Commerce - Martin ...DrupalCamp MSK
 
Magento Dependency Injection
Magento Dependency InjectionMagento Dependency Injection
Magento Dependency InjectionAnton Kril
 
Java 8 Hipster slides
Java 8 Hipster slidesJava 8 Hipster slides
Java 8 Hipster slidesOleg Prophet
 
Struts 2 + Spring
Struts 2 + SpringStruts 2 + Spring
Struts 2 + SpringBryan Hsueh
 
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...Bruno Salvatore Belluccia
 
Agile web development Groovy Grails with Netbeans
Agile web development Groovy Grails with NetbeansAgile web development Groovy Grails with Netbeans
Agile web development Groovy Grails with NetbeansCarol McDonald
 
Knockout.js presentation
Knockout.js presentationKnockout.js presentation
Knockout.js presentationScott Messinger
 
Multi Client Development with Spring - Josh Long
Multi Client Development with Spring - Josh Long Multi Client Development with Spring - Josh Long
Multi Client Development with Spring - Josh Long jaxconf
 

Semelhante a Scalatra - Massimiliano Dessì (Energeya) (20)

Codemotion 2013 scalatra play spray
Codemotion 2013 scalatra play sprayCodemotion 2013 scalatra play spray
Codemotion 2013 scalatra play spray
 
TechDay: Kick Start Your Experience with Android Wear - Mario Viviani
TechDay: Kick Start Your Experience with Android Wear - Mario VivianiTechDay: Kick Start Your Experience with Android Wear - Mario Viviani
TechDay: Kick Start Your Experience with Android Wear - Mario Viviani
 
Kick start your experience with android wear - Codemotion Rome 2015
Kick start your experience with android wear - Codemotion Rome 2015Kick start your experience with android wear - Codemotion Rome 2015
Kick start your experience with android wear - Codemotion Rome 2015
 
Practical Example of AOP with AspectJ
Practical Example of AOP with AspectJPractical Example of AOP with AspectJ
Practical Example of AOP with AspectJ
 
Dependency management & Package management in JavaScript
Dependency management & Package management in JavaScriptDependency management & Package management in JavaScript
Dependency management & Package management in JavaScript
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your App
 
Big Data processing with Spark, Scala or Java?
Big Data processing with Spark, Scala or Java?Big Data processing with Spark, Scala or Java?
Big Data processing with Spark, Scala or Java?
 
Test upload
Test uploadTest upload
Test upload
 
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
 
Private slideshow
Private slideshowPrivate slideshow
Private slideshow
 
Drupal in aerospace - selling geodetic satellite data with Commerce - Martin ...
Drupal in aerospace - selling geodetic satellite data with Commerce - Martin ...Drupal in aerospace - selling geodetic satellite data with Commerce - Martin ...
Drupal in aerospace - selling geodetic satellite data with Commerce - Martin ...
 
World of CSS Grid
World of CSS GridWorld of CSS Grid
World of CSS Grid
 
Magento Dependency Injection
Magento Dependency InjectionMagento Dependency Injection
Magento Dependency Injection
 
Java 8 Hipster slides
Java 8 Hipster slidesJava 8 Hipster slides
Java 8 Hipster slides
 
Struts 2 + Spring
Struts 2 + SpringStruts 2 + Spring
Struts 2 + Spring
 
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
 
Modular and Event-Driven JavaScript
Modular and Event-Driven JavaScriptModular and Event-Driven JavaScript
Modular and Event-Driven JavaScript
 
Agile web development Groovy Grails with Netbeans
Agile web development Groovy Grails with NetbeansAgile web development Groovy Grails with Netbeans
Agile web development Groovy Grails with Netbeans
 
Knockout.js presentation
Knockout.js presentationKnockout.js presentation
Knockout.js presentation
 
Multi Client Development with Spring - Josh Long
Multi Client Development with Spring - Josh Long Multi Client Development with Spring - Josh Long
Multi Client Development with Spring - Josh Long
 

Mais de Scala Italy

Alessandro Abbruzzetti - Kernal64
Alessandro Abbruzzetti - Kernal64Alessandro Abbruzzetti - Kernal64
Alessandro Abbruzzetti - Kernal64Scala Italy
 
Alberto Paro - Hands on Scala.js
Alberto Paro - Hands on Scala.jsAlberto Paro - Hands on Scala.js
Alberto Paro - Hands on Scala.jsScala Italy
 
Andrea Lattuada, Gabriele Petronella - Building startups on Scala
Andrea Lattuada, Gabriele Petronella - Building startups on ScalaAndrea Lattuada, Gabriele Petronella - Building startups on Scala
Andrea Lattuada, Gabriele Petronella - Building startups on ScalaScala Italy
 
Stefano Rocco, Roberto Bentivoglio - Scala in increasingly demanding environm...
Stefano Rocco, Roberto Bentivoglio - Scala in increasingly demanding environm...Stefano Rocco, Roberto Bentivoglio - Scala in increasingly demanding environm...
Stefano Rocco, Roberto Bentivoglio - Scala in increasingly demanding environm...Scala Italy
 
Federico Feroldi - Scala microservices
Federico Feroldi - Scala microservicesFederico Feroldi - Scala microservices
Federico Feroldi - Scala microservicesScala Italy
 
Martin Odersky - Evolution of Scala
Martin Odersky - Evolution of ScalaMartin Odersky - Evolution of Scala
Martin Odersky - Evolution of ScalaScala Italy
 
Daniela Sfregola - Intro to Akka
Daniela Sfregola - Intro to AkkaDaniela Sfregola - Intro to Akka
Daniela Sfregola - Intro to AkkaScala Italy
 
Mirco Dotta - Akka Streams
Mirco Dotta - Akka StreamsMirco Dotta - Akka Streams
Mirco Dotta - Akka StreamsScala Italy
 
Phil Calçado - Your microservice as a function
Phil Calçado - Your microservice as a functionPhil Calçado - Your microservice as a function
Phil Calçado - Your microservice as a functionScala Italy
 
Scala: the language of languages - Mario Fusco (Red Hat)
Scala: the language of languages - Mario Fusco (Red Hat)Scala: the language of languages - Mario Fusco (Red Hat)
Scala: the language of languages - Mario Fusco (Red Hat)Scala Italy
 
Reflection in Scala Whats, Whys and Hows - Walter Cazzola (Dipartimento di In...
Reflection in Scala Whats, Whys and Hows - Walter Cazzola (Dipartimento di In...Reflection in Scala Whats, Whys and Hows - Walter Cazzola (Dipartimento di In...
Reflection in Scala Whats, Whys and Hows - Walter Cazzola (Dipartimento di In...Scala Italy
 
Simplifying development-short - Mirco Dotta (Typesafe)
Simplifying development-short - Mirco Dotta (Typesafe)Simplifying development-short - Mirco Dotta (Typesafe)
Simplifying development-short - Mirco Dotta (Typesafe)Scala Italy
 
Scala in pratica - Stefano Rocco (MoneyFarm)
Scala in pratica - Stefano Rocco (MoneyFarm)Scala in pratica - Stefano Rocco (MoneyFarm)
Scala in pratica - Stefano Rocco (MoneyFarm)Scala Italy
 

Mais de Scala Italy (13)

Alessandro Abbruzzetti - Kernal64
Alessandro Abbruzzetti - Kernal64Alessandro Abbruzzetti - Kernal64
Alessandro Abbruzzetti - Kernal64
 
Alberto Paro - Hands on Scala.js
Alberto Paro - Hands on Scala.jsAlberto Paro - Hands on Scala.js
Alberto Paro - Hands on Scala.js
 
Andrea Lattuada, Gabriele Petronella - Building startups on Scala
Andrea Lattuada, Gabriele Petronella - Building startups on ScalaAndrea Lattuada, Gabriele Petronella - Building startups on Scala
Andrea Lattuada, Gabriele Petronella - Building startups on Scala
 
Stefano Rocco, Roberto Bentivoglio - Scala in increasingly demanding environm...
Stefano Rocco, Roberto Bentivoglio - Scala in increasingly demanding environm...Stefano Rocco, Roberto Bentivoglio - Scala in increasingly demanding environm...
Stefano Rocco, Roberto Bentivoglio - Scala in increasingly demanding environm...
 
Federico Feroldi - Scala microservices
Federico Feroldi - Scala microservicesFederico Feroldi - Scala microservices
Federico Feroldi - Scala microservices
 
Martin Odersky - Evolution of Scala
Martin Odersky - Evolution of ScalaMartin Odersky - Evolution of Scala
Martin Odersky - Evolution of Scala
 
Daniela Sfregola - Intro to Akka
Daniela Sfregola - Intro to AkkaDaniela Sfregola - Intro to Akka
Daniela Sfregola - Intro to Akka
 
Mirco Dotta - Akka Streams
Mirco Dotta - Akka StreamsMirco Dotta - Akka Streams
Mirco Dotta - Akka Streams
 
Phil Calçado - Your microservice as a function
Phil Calçado - Your microservice as a functionPhil Calçado - Your microservice as a function
Phil Calçado - Your microservice as a function
 
Scala: the language of languages - Mario Fusco (Red Hat)
Scala: the language of languages - Mario Fusco (Red Hat)Scala: the language of languages - Mario Fusco (Red Hat)
Scala: the language of languages - Mario Fusco (Red Hat)
 
Reflection in Scala Whats, Whys and Hows - Walter Cazzola (Dipartimento di In...
Reflection in Scala Whats, Whys and Hows - Walter Cazzola (Dipartimento di In...Reflection in Scala Whats, Whys and Hows - Walter Cazzola (Dipartimento di In...
Reflection in Scala Whats, Whys and Hows - Walter Cazzola (Dipartimento di In...
 
Simplifying development-short - Mirco Dotta (Typesafe)
Simplifying development-short - Mirco Dotta (Typesafe)Simplifying development-short - Mirco Dotta (Typesafe)
Simplifying development-short - Mirco Dotta (Typesafe)
 
Scala in pratica - Stefano Rocco (MoneyFarm)
Scala in pratica - Stefano Rocco (MoneyFarm)Scala in pratica - Stefano Rocco (MoneyFarm)
Scala in pratica - Stefano Rocco (MoneyFarm)
 

Último

Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Visualising and forecasting stocks using Dash
Visualising and forecasting stocks using DashVisualising and forecasting stocks using Dash
Visualising and forecasting stocks using Dashnarutouzumaki53779
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 

Último (20)

Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Visualising and forecasting stocks using Dash
Visualising and forecasting stocks using DashVisualising and forecasting stocks using Dash
Visualising and forecasting stocks using Dash
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 

Scalatra - Massimiliano Dessì (Energeya)

  • 1. Scala Italy 25 may 2013 Scalatra comparison with SpringMVC Massimiliano Dessì 1 Monday, May 27, 13
  • 2. GDG Sardegna Speaker Max has more than 13 years of experience in programming. He’s a proud father of three. Manager of GTUG Sardegna, Founder of SpringFramework IT, co-founder of Jug Sardegna. Author of Spring 2.5 AOP. He works in Energeya as a Product Architect and lives in Cagliari, Italy. 2 Monday, May 27, 13
  • 3. GDG Sardegna Scalatra - SpringMVC CRUD HTML REST JSON Routing Template Security Agenda 3 Monday, May 27, 13
  • 4. GDG Sardegna Spring , Since 2004 - Java Full Stack - Lot of people involved now property of VMware Scalatra , Since 2009 - Scala Http Microframework (DSL) the BBC, LinkedIn, the Guardian, games website IGN, UK government rely on Scalatra. Some info 4 Monday, May 27, 13
  • 5. GDG Sardegna REST class JellyBeans extends ScalatraServlet { get("/jellybs/:id") { ... } post("/jellybs") { ... } put("/jellybs/:id") { ... } delete("/jellybs/:id") { ... } } For browser add PUT & DELETE support client side X-HTTP-METHOD-OVERRIDE or _method=put _method=delete in the post body class JellyBeansBrowser extends ScalatraFilter with MethodOverride 5 Monday, May 27, 13
  • 6. GDG SardegnaMassimiliano Dessì Routes class JellyBeans extends ScalatraServlet { get("/jellybs/:id") { val id:Int = params.getOrElse("id", halt(400)).toInt ... } get("/jellybs/download/*.*") { //with wildcard ... } get("""^/j(.*)/f(.*)""".or) { //REGEX ... } post("/jellybs", request.getRemoteHost == "127.0.0.1", request.getRemoteUser == "admin") { .... } 6 Monday, May 27, 13
  • 7. GDG Sardegna REST @Controller public class JellyBeansController{ @RequestMapping(value = "/jellybs/{id}", method = RequestMethod.GET) @ResponseStatus(HttpStatus.OK) //Http 200 public @ResponseBody JellyB getItem(@PathVariable("id") Integer id) {...} @RequestMapping(value = "/jellybs", method = RequestMethod.POST) //Http 201 @ResponseStatus(HttpStatus.CREATED) //Http 201 public void createJelly(HttpServletRequest req, HttpServletResponse res, @RequestBody JellyB item) { ... } @RequestMapping(value = "/jellybs/{id}", method = RequestMethod.PUT) @ResponseStatus(HttpStatus.NO_CONTENT) //Http 204 public void updateItem(@RequestBody JellyB item, @PathVariable("id") Integer id) { ... } @RequestMapping(value = "/items/{id}", method = RequestMethod.DELETE) @ResponseStatus(HttpStatus.NO_CONTENT)//204 public void deleteItem(@PathVariable("id") String id) { ... } } For browser add PUT & DELETE support client side X-HTTP-METHOD-OVERRIDE or _method=put _method=delete in the post body <filter> <filter-name>hiddenMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> 7 Monday, May 27, 13
  • 8. GDG Sardegna Routes class JellyBeans extends ScalatraServlet { get("/jellybs/:id") { val id:Int = params.getOrElse("id", halt(400)).toInt ... } get("/jellybs/download/*.*") { //with wildcard ... } get("""^/j(.*)/f(.*)""".or) { //REGEX ... } post("/jellybs", request.getRemoteHost == "127.0.0.1", request.getRemoteUser == "admin") { .... } 8 Monday, May 27, 13
  • 9. GDG Sardegna HandlerMapping @Controller public class JellyBeansController{ @RequestMapping(value="/jelly.pdf",method = RequestMethod.GET) public ModelAndView pdf(HttpServletRequest req,@RequestParam String id) { ... } @RequestMapping(value = "/jellybs/{id}", method = RequestMethod.GET) public String getItem(@PathVariable("id") Integer id) { ... } @RequestMapping(value = "/jellybs", method = RequestMethod.POST) public void createJelly(@ModelAttribute(”jelly”) JellyB jelly) { ... } } DefaultAnnotationHandlerMapping SimpleUrlHandlerMapping ControllerClassNameHandlerMapping 9 Monday, May 27, 13
  • 10. GDG Sardegna Filter class JellyBeans extends ScalatraServlet { before() { db.acquireConnecion contentType="text/html" } get("/") { val menu = db.findWelcome() templateEngine.layout("index.ssp", menu) } after() { db.releaseConnection } } Like Servlet Filter (or Aspect Oriented Programming) You can add logic before or the routes 10 Monday, May 27, 13
  • 11. GDG Sardegna Handler Interceptor public interface HandlerInterceptor{ //before call method’s controller boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception; //after call method’s controller void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler, ModelAndView mav) throws Exception; //after view render() void afterCompletition(HttpServletRequest req, HttpServletResponse res, Object handler, Exception ex) throws Exception; } Handler mapped on all controllers (as a property of Handlermapping config) or mapped on url path with <mvc:interceptors> tags Like Servlet Filter (or Aspect Oriented Programming) You can add logic before or after the controllers methods 11 Monday, May 27, 13
  • 12. GDG Sardegna Handlers Handlers are top level methods for http routines class JellyBeans extends ScalatraServlet { notFound { <h1>Not found</h1> } halt(status = 301, headers = Map("Location" -> "http://www.codemotion.com/")) get("/jellybs/names/*") { "Name not found!" } } 12 Monday, May 27, 13
  • 13. GDG Sardegna Handlers class JellyBeans extends ScalatraServlet { get("/jellybs/names/:who") { params("who") match { case "Cherry" => "Found Cherry!" case _ => pass() /* call the next matching route route, routes are matched from bottom up*/ } } get("/jellybs/download/:id") { jellyBeanService.find(params("id")) match { case Some(jellybean) => Ok(jellybean) case None => NotFound("Sorry, jellybean not found") } } } 13 Monday, May 27, 13
  • 14. GDG Sardegna Request Response & Friends class JellyBeans extends ScalatraServlet { get("/jellybs/shows/:id") { //access to request,response, session and params request.body //request body as a string request.cookies // cookie map request.isAjax // is ajaxRequest request.getSession // HttpServletSession request.locale // user locale response.getOutputStream //response outputstream servletContext.get("myIntParam") //servlet context val idString = params("id") val id = params.getAs[Int]("id") //val id = params.getOrElse("id", halt(500)) //another way .... } } 14 Monday, May 27, 13
  • 15. GDG Sardegna Request Response & Friends class JellyBeans extends ScalatraServlet { get("/jellybs/*/conf/*") { // Matches "GET /jellybs/one/conf/two" multiParams("splat") // Seq("one", "two") //wildcard accessible with key splat } get("""^/jelly(.*)/fla(.*)""".r) { // Matches "GET /jellybs/flavor" multiParams("captures") // == Seq("bs", "vor") } } 15 Monday, May 27, 13
  • 16. GDG Sardegna Gzip class GzipJellyBeans extends ScalatraServlet with GZipSupport{ get("/") { <html> <body> <h1>This is <a href="http://en.wikipedia.org/wiki/Sparta">Sparta</a>! </h1> </body> </html> } } 16 Monday, May 27, 13
  • 17. GDG Sardegna Flash message class FlashServlet extends ScalatraServlet with FlashMapSupport{ post("/jellybs/create") { flash("notice") = "jellybean created successfully" redirect("/home") //redirect } get("/home") { ssp("/home") //Scala Server Pages } 17 Monday, May 27, 13
  • 18. GDG Sardegna ExceptionResolvers <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="org.springframework.web.HttpSessionRequiredException">welcome</prop> ... </props> </property> </bean> or in a annotated @Controller class @ExceptionHandler public String requestParamNotPresent(HttpMediaTypeException ex) 18 Monday, May 27, 13
  • 19. GDG Sardegna Binding To avoid manual binding from http and our Object Scalatra provide a binding module case class MyClass(id: Integer, name: String) post("/myroute") { val cmd = command[CreateMyClassCommand] ... } 19 Monday, May 27, 13
  • 20. GDG Sardegna Binding Under the hood abstract class MyClassCommand[S](implicit mf: Manifest[S]) extends ModelCommand[S] with JsonCommand {    implicit def todoStringValidators(b: FieldDescriptor[String]) = new MyClassStringValidations(b) } class CreateMyClassCommand extends MyClassCommand[MyClass] { protected implicit val jsonFormats = DefaultFormats val name: Field[String] = asType[String]("name").notBlank.minLength(3) } 20 Monday, May 27, 13
  • 21. GDG Sardegna Binding Under the hood class MyClassStringValidations(b: FieldDescriptor[String]) { def startsWithCap(message: String = "%s must start with a capital letter.") = b.validateWith(_ =>      _ flatMap { new PredicateValidator[String]( b.name, """^[A-Z,0-9]""".r.findFirstIn(_).isDefined, message).validate(_)    ) } ) } 21 Monday, May 27, 13
  • 22. GDG Sardegna CommandObject @RequestMapping(value = "/items/{id}", method = RequestMethod.PUT) @ResponseStatus(HttpStatus.NO_CONTENT) public String updateItem(JellyB item) { ... } Spring bind the request body on the object used in the method (JellyB) Objects Validation with jsr 303 annotation or with Validator Spring Interface Error message with JSP/JSTL tags 22 Monday, May 27, 13
  • 23. GDG Sardegna Upload import org.scalatra.ScalatraServlet import org.scalatra.servlet.FileUploadSupport import javax.servlet.annotation.MultipartConfig @MultipartConfig(maxFileSize=10*1024) trait StorageRoutes extends FileUploadSupport { self: ScalatraServlet => } 23 Monday, May 27, 13
  • 24. GDG Sardegna JSON Automatic Serialization and deserialization of any Case class object JSONServlet extends ScalatraServlet with JacksonJsonSupport{ case class JellyBean(id: Int, name: String, flavor:String) protected implicit val jsonFormats: Formats = DefaultFormats before() { contentType = formats("json") } .... 24 Monday, May 27, 13
  • 25. GDG Sardegna Actors The routes can returns a Future class MyActorServlet(system:ActorSystem, myActor:ActorRef) extends ScalatraServlet with FutureSupport { import _root_.akka.pattern.ask implicit val timeout = Timeout(10) protected implicit def executor: ExecutionContext = system.dispatcher get("/async") { myActor ? "Do stuff and give me an answer" } get("/fire-forget") { myActor ! "Hey, you know what?" Accepted() //if you do not want return a future } } 25 Monday, May 27, 13
  • 26. GDG Sardegna Actors get("/async") { myActor ? "Do stuff and give me an answer" } get("/fire-forget") { myActor ! "Hey, you know what?" Accepted() //if you don’t want return a future } class CodemotionActor extends Actor { def receive = { case "Do stuff and give me an answer" => sender ! "The answer is 42" case "Hey, you know what?" => println("Yeah I know...") } } } 26 Monday, May 27, 13
  • 27. GDG Sardegna Akka Akka start in the Bootstrap of Scalatra class ScalatraBootstrap extends LifeCycle { val system = ActorSystem() val codemotionActor = system.actorOf(Props[CodemotionActor]) override def init(context: ServletContext) { context.mount(new JSONServlet, "/jellybs/*") context.mount(new FrontServlet, "/template/*") context.mount(new MyActorServlet(system, codemotionActor), "/actors/*") } override def destroy(context:ServletContext) { system.shutdown() } } 27 Monday, May 27, 13
  • 28. GDG Sardegna Deployment Scalatra is based on regular Java Servlet 3.0 it can start from: Standalone from jetty embedded From Servlet container Heroku Jelastic CloudBees GAE (not out of the box ) web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <listener> <listener-class>org.scalatra.servlet.ScalatraListener</listener-class> </listener> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/img/*</url-pattern> <url-pattern>/css/*</url-pattern> <url-pattern>/js/*</url-pattern> <url-pattern>/assets/*</url-pattern> </servlet-mapping> </web-app> 28 Monday, May 27, 13
  • 29. GDG Sardegna JSON Automatic Serialization and deserialization of any Case class object JSONServlet extends ScalatraServlet with JacksonJsonSupport{ ... get("/jellybs/all"){ jellyBeanRepo.all //from class to json } post("/jellybs/create") { val jb = parsedBody.extract[JellyBean] //from json to class ... } } 29 Monday, May 27, 13
  • 30. GDG Sardegna JSON 30 JSON with third party lib es Jackson @JsonCreator public JellyB(Map map) {...} @JsonAnyGetter public Map toMap() {...} Automatic binding public @ResponseBody JellyB getItem(...) public void updateItem(@RequestBody JellyB item) Monday, May 27, 13
  • 31. GDG Sardegna Template Html inline, Scalate Twirl (Play2 template) Scalate mean SSP (Scala Server Page) Scaml Mustache Jade 31 Monday, May 27, 13
  • 32. GDG Sardegna Template class ScalateServlet extends ScalatraServlet with ScalateSupport{ get("/"jellybeans/ssp) { contentType="text/html" ssp("/index", "foo" -> "uno", "bar" -> "two") // the layout used it’s WEB-INF/layouts/default.ssp } get("/jellybeans/jade") { jade("/index", "layout" -> "", "foo" -> "one", "bar" -> "two") // render without a layout. } get("/jellybeans/direct") { templateEngine.layout("/jellybeans/index.ssp") //direct invoking of scalate } 32 Monday, May 27, 13
  • 33. GDG Sardegna Template SSP <%@ var body: String %> <%@ var title: String = "Some Default Title" %> <%@ var head: String = "" %> <html> <head> <title>${title}</title> <%-- page specific head goes here --%> ${unescape(head)} </head> <body> <p>layout header goes here...</p> ${unescape(body)} <p>layout footer goes here...</p> </body> </html> 33 Monday, May 27, 13
  • 34. GDG Sardegna Template JADE !!! 5 html(lang="en") head title= pageTitle :javascript if (foo) { bar() } body h1 Jade - node template engine #container - if (youAreUsingJade) p You are amazing - else p Get on it! :coffeescript alert "Hello, Coffee!" 34 Monday, May 27, 13
  • 35. GDG Sardegna Template Mustache Hello {{name}} You have just won ${{value}}! {{#in_ca}} Well, ${{taxed_value}}, after taxes. {{/in_ca}} 35 Monday, May 27, 13
  • 36. GDG Sardegna Template SCAML !!! XML !!! %html %head %title Myspace %body %h1 I am the international space station %p Sign my guestbook 36 Monday, May 27, 13
  • 37. GDG Sardegna ViewResolver JSP, JSTL, Tiles, FreeMarker, XSLT, PDF, Velocity, JExcelApi, JSON, Atom, RSS, JasperReports Explicit view with different ViewResolver with different order values, or with ContentTypeNegotiationViewResolver mapping different mediaTypes 37 Monday, May 27, 13
  • 38. GDG Sardegna Authentication & Security Scalatra uses Scentry a porting of Ruby Warden authentication class OurAuthStrategy(protected override val app: ScalatraBase, realm: String) extends BasicAuthStrategy[User](app, realm) { protected def validate(userName: String, password: String): Option[User] = { if(userName == "myusername" && password == "secret") Some(User("myusername")) else None } protected def getUserId(user: User): String = user.id } case class User(id: String) 38 Monday, May 27, 13
  • 39. GDG Sardegna Authentication & Security Now we need to combine our strategy and ScentrySupport trait AuthenticationSupport extends ScentrySupport[User] with BasicAuthSupport[User] { self: ScalatraBase => val realm = "Scalatra Basic Auth Example" protected def fromSession = { case id: String => User(id) } protected def toSession = { case usr: User => usr.id } protected val scentryConfig = (new ScentryConfig {}).asInstanceOf[ScentryConfiguration] } 39 Monday, May 27, 13
  • 40. GDG Sardegna Authentication & Security Now we need to combine our strategy and ScentrySupport trait AuthenticationSupport extends ScentrySupport[User] with BasicAuthSupport[User] { .... override protected def configureScentry = { scentry.unauthenticated { scentry.strategies("Basic").unauthenticated() scentry.strategies("") } } override protected def registerAuthStrategies = { scentry.register("Basic", app => new OurBasicAuthStrategy(app, realm)) } protected def validate(userName: String, password: String): Option[User] = { if(userName == "scalatra" && password == "scalatra") Some(User("scalatra")) else None } } 40 Monday, May 27, 13
  • 41. GDG Sardegna Authentication & Security Now we can use the Authentication for all routes defined in our Authenticated Servlets class AuthenticatedServlet extends ScalatraServlet with AuthenticationSupport{ //every route goes under authentication } Unauthenticated user will see a browser prompt login 41 Monday, May 27, 13
  • 42. GDG Sardegna SpringSecurity FilterServlet to protect urls, roles and AOP intercepting based on User Roles <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <sec:http> " " <sec:form-login login-page="/login.jsp" login-processing-url="/j_security_check" default-target-url="/" " " " always-use-default-target="true" authentication-failure-url="/loginError.jsp"/> " " <sec:logout logout-url="/logout.jsp" invalidate-session="true" logout-success-url="/login.jsp" /> " " <sec:intercept-url pattern="/styles/**" filters="none"/> " " <sec:intercept-url pattern="/scripts/**" filters="none"/> " " <sec:intercept-url pattern="/img/**" filters="none"/> " " <sec:anonymous username="guest" granted-authority="ROLE_GUEST" /> " 42 Monday, May 27, 13
  • 43. GDG Sardegna Test Test with Specs2 class FrontServletSpec extends ScalatraSpec { def is = "GET / on FrontServlet" ^ "should return status 200" ! root200 ^ end addServlet(classOf[FrontServlet], "/*") def root200 = get("/") { status must_== 200 } } 43 Monday, May 27, 13
  • 44. GDG Sardegna Q & A GTUG Sardegna 44 Monday, May 27, 13
  • 45. GDG Sardegna Thanks for your attention! Massimiliano: @desmax74 GTUG Sardegna 45 Thanks for you attention! Massimiliano: @desmax74 Monday, May 27, 13