scala for sling - apache software foundation

59
LOGO SPEAKER‘S COMPANY Scala for Sling Building RESTful Web Applications with Scala for Sling http://people.apache.org/~mduerig/scala4sling/ Michael Dürig Day Software AG 10080

Upload: others

Post on 11-Feb-2022

12 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Scala for Sling - Apache Software Foundation

LOGO SPEAKER‘S COMPANY

Scala for SlingBuilding RESTful Web Applications with Scala for Sling

http://people.apache.org/~mduerig/scala4sling/

Michael Dürig

Day Software AG

10080

Page 2: Scala for Sling - Apache Software Foundation

2

AGENDA

> Introduction

> What is Apache Sling?

> What is Scala?

> Scala for Sling

> Summary and questions

Page 3: Scala for Sling - Apache Software Foundation

3

Introduction

> Michael Dürig

– Developer for Day Software

– http://michid.wordpress.com/

> Michael Marth

– Technology Evangelist for Day Software

– http://dev.day.com/

Page 4: Scala for Sling - Apache Software Foundation

4

Overview

> What to expect

– Proof of concept

– Experimental code

> What not to expect

– Product showcase, tutorial

– Live coding (demo code available from

http://people.apache.org/~mduerig/scala4sling/)

> Prerequisites

– Basic understanding of Java content repositories (JCR)

– Prior exposure to Scala a plus

Page 5: Scala for Sling - Apache Software Foundation

5

AGENDA

> Introduction

> What is Apache Sling?

> What is Scala?

> Scala for Sling

> Summary and questions

Page 6: Scala for Sling - Apache Software Foundation

6

Sling builds on JCR

> Web application framework for JCR

– JCR (JSR-170/JSR-283): Apache Jackrabbit

– OSGi-based: Apache Felix

– http://incubator.apache.org/sling/

> Scriptable application layer for JCR

– JSR-223: Scripting for the Java platform

> REST over JCR

– Content resolution for mapping request URLs to JCR nodes

– Servlet resolution for mapping JCR nodes to request handlers (i.e. scripts)

Page 7: Scala for Sling - Apache Software Foundation

7

URL decomposition

GET /forum/scala4sling.thread.html

Page 8: Scala for Sling - Apache Software Foundation

8

URL decomposition

GET /forum/scala4sling.thread.html

Repository

Page 9: Scala for Sling - Apache Software Foundation

9

URL decomposition

GET /forum/scala4sling.thread.html

RepositoryRepository path

Page 10: Scala for Sling - Apache Software Foundation

10

URL decomposition

GET /forum/scala4sling.thread.html

RepositoryRepository path

Application selection

Page 11: Scala for Sling - Apache Software Foundation

11

URL decomposition

GET /forum/scala4sling.thread.html

RepositoryRepository path Script selection

Application selection

Page 12: Scala for Sling - Apache Software Foundation

12

AGENDA

> Introduction

> What is Apache Sling?

> What is Scala?

> Scala for Sling

> Summary and questions

Page 13: Scala for Sling - Apache Software Foundation

13

Scala builds on the JVM

> Multi-paradigm language for the JVM

– Conceived by Martin Odersky and his group (EPFL, Lausanne)

– Fully interoperable with Java

– IDE plugins for Eclipse and IntelliJ IDEA

– http://www.scala-lang.org/

> Concise, elegant, and type safe

– Touch and feel of a genuine scripting language

– Smoothly integrates object oriented and functional features

– Great for creating DSLs

Page 14: Scala for Sling - Apache Software Foundation

> Values

> Type parameters

14

Type inference: the scripting touch

val x = 42 // x has type Int

val s = x.toString // s has type String

val q = s.substring(s) // type mismatch; found String, required Int

class Pair[S, T](s: S, t: T)

def makePair[S, T](s: S, t: T) = new Pair(s, t)

val p = makePair(42.0, "Scala") // p has type Pair[Double, String]

Page 15: Scala for Sling - Apache Software Foundation

> Values

> Type parameters

15

Type inference: the scripting touch

val x = 42 // x has type Int

val s = x.toString // s has type String

val q = s.substring(s) // type mismatch; found String, required Int

class Pair[S, T](s: S, t: T)

def makePair[S, T](s: S, t: T) = new Pair(s, t)

val p = makePair(42.0, "Scala") // p has type Pair[Double, String]

class Pair<S, T> {

public final S s;

public final T t;

public Pair(S s, T t) {

super();

this.s = s;

this.t = t;

}

}

public <S, T> Pair<S, T> makePair(S s, T t) {

return new Pair<S, T>(s, t);

}

public final Pair<Double, String> p = makePair(42.0, "Scala");

Page 16: Scala for Sling - Apache Software Foundation

16

XML <pre>literals</pre>

> HTML? Scala!val title = "Hello Jazoon 09"

println {

<html>

<body>

<h1>{ title }</h1>

{

(for (c <- title) yield c)

.mkString(" ")

}

</body>

</html>

}

Page 17: Scala for Sling - Apache Software Foundation

17

XML <pre>literals</pre>

> HTML? Scala!val title = "Hello Jazoon 09"

println {

<html>

<body>

<h1>{ title }</h1>

{

(for (c <- title) yield c)

.mkString(" ")

}

</body>

</html>

}

println {

Elem(null, "html", Null, TopScope,

Elem(null, "body", Null, TopScope,

Elem(null, "h1", Null, TopScope,

Text(title)

),

Text(

(for (c <- title) yield c)

.mkString(" ")

)

)

)

}

Page 18: Scala for Sling - Apache Software Foundation

18

XML <pre>literals</pre>

> HTML? Scala!val title = "Hello Jazoon 09"

println {

<html>

<body>

<h1>{ title }</h1>

{

(for (c <- title) yield c)

.mkString(" ")

}

</body>

</html>

}

<html>

<body>

<h1>Hello Jazoon 09</h1>

H e l l o J a z o o n 0 9

</body>

</html>

Page 19: Scala for Sling - Apache Software Foundation

19

Implicits: pimp my library

> Implicit conversion

> Déjà vu?

– Similar to extension methods in C#

– Similar to conversion constructors in C++

– Equivalent to type classes in Haskell

implicit def translate(s: String) = new {

def toGerman = s match {

case "Example" => "Beispiel"

// ...

case _ => throw new Exception("No translation for " + s)

}

}

val german = "Example".toGerman

Page 20: Scala for Sling - Apache Software Foundation

20

Objects are functions are objects…

> Object as function

> Function as object

object Twice {

def apply(n: Int) = 2*n

}

println(Twice(21)) // prints 42

def twice(n: Int) = 2*n

val doubler = twice(_)

println(doubler(21)) // prints 42

Page 21: Scala for Sling - Apache Software Foundation

21

AGENDA

> Introduction

> What is Apache Sling?

> What is Scala?

> Scala for Sling

> Summary and questions

Page 22: Scala for Sling - Apache Software Foundation

22

Demo application: Forum

Page 23: Scala for Sling - Apache Software Foundation

package forum {

object html {

import html_Bindings._

// ...

println {

<html>

<body>

Welcome to the { currentNode("name") } forum

&mdash; { Calendar.getInstance.getTime }

{ ThreadNewForm.render }

{ ThreadOverview.render(currentNode) }

</body>

</html>

}

}

23

Forum: html.scala

Page 24: Scala for Sling - Apache Software Foundation

package forum {

object html {

import html_Bindings._

// ...

println {

<html>

<body>

Welcome to the { currentNode("name") } forum

&mdash; { Calendar.getInstance.getTime }

{ ThreadNewForm.render }

{ ThreadOverview.render(currentNode) }

</body>

</html>

}

}

GET /forum.html

24

Forum: html.scala

Page 25: Scala for Sling - Apache Software Foundation

package forum {

object html {

import html_Bindings._

// ...

println {

<html>

<body>

Welcome to the { currentNode("name") } forum

&mdash; { Calendar.getInstance.getTime }

{ ThreadNewForm.render }

{ ThreadOverview.render(currentNode) }

</body>

</html>

}

}

Put Sling variables into scope

(currentNode, request, response, etc.)

25

Forum: html.scala

Page 26: Scala for Sling - Apache Software Foundation

package forum {

object html {

import html_Bindings._

// ...

println {

<html>

<body>

Welcome to the { currentNode("name") } forum

&mdash; { Calendar.getInstance.getTime }

{ ThreadNewForm.render }

{ ThreadOverview.render(currentNode) }

</body>

</html>

}

}

/**

* Print out an object followed by a new line character.

* @param x the object to print.

*/

def println(x: Any): Unit = out.println(x)

26

Forum: html.scala

Page 27: Scala for Sling - Apache Software Foundation

package forum {

object html {

import html_Bindings._

// ...

println {

<html>

<body>

Welcome to the { currentNode("name") } forum

&mdash; { Calendar.getInstance.getTime }

{ ThreadNewForm.render }

{ ThreadOverview.render(currentNode) }

</body>

</html>

}

}

/**

* Print out an object followed by a new line character.

* @param x the object to print.

*/

def println(x: Any): Unit = out.println(x)

27

Forum: html.scala

Page 28: Scala for Sling - Apache Software Foundation

package forum {

object html {

import html_Bindings._

// ...

println {

<html>

<body>

Welcome to the { currentNode("name") } forum

&mdash; { Calendar.getInstance.getTime }

{ ThreadNewForm.render }

{ ThreadOverview.render(currentNode) }

</body>

</html>

}

}

28

Forum: html.scala

implicit def rich(node: Node) = new {

def apply(property: String) = node.getProperty(property).getString

...

}

Page 29: Scala for Sling - Apache Software Foundation

object ThreadOverview {

// imports omitted

def render(node: Node) =

emptyUnless(node.hasNodes) {

<h1>threads</h1>

<ul>{ node.nodes map toListItem }</ul>

}

private def toListItem(node: Node) = {

<li>

{ node("subject") }

(<a href={ node.path + ".thread.html"}>show thread</a>)

</li>

}

}

29

Forum: thread overview

Page 30: Scala for Sling - Apache Software Foundation

object ThreadOverview {

// imports omitted

def render(node: Node) =

emptyUnless(node.hasNodes) {

<h1>threads</h1>

<ul>{ node.nodes map toListItem }</ul>

}

private def toListItem(node: Node) = {

<li>

{ node("subject") }

(<a href={ node.path + ".thread.html"}>show thread</a>)

</li>

}

}

30

Forum: thread overview

def emptyUnless(condition: Boolean)(block: => NodeSeq) =

if (condition) block

else Empty

Page 31: Scala for Sling - Apache Software Foundation

object ThreadNewForm {

def render = {

<h1>start a new thread</h1>

<form action="/content/forum/*" method="POST"

enctype="multipart/form-data">

subject <input name="subject" type="text" />

<textarea name="body"></textarea>

logo <input name="logo“ type="file" />

<input type="submit" value="save" />

<input name=":redirect" value="/content/forum.html" type="hidden" />

</form>

}

}

31

Forum: form data

Page 32: Scala for Sling - Apache Software Foundation

object ThreadNewForm {

def render = {

<h1>start a new thread</h1>

<form action="/content/forum/*" method="POST"

enctype="multipart/form-data">

subject <input name="subject" type="text" />

<textarea name="body"></textarea>

logo <input name="logo“ type="file" />

<input type="submit" value="save" />

<input name=":redirect" value="/content/forum.html" type="hidden" />

</form>

}

}

32

Forum: form data

Page 33: Scala for Sling - Apache Software Foundation

object ThreadNewForm {

def render = {

<h1>start a new thread</h1>

<form action="/content/forum/*" method="POST"

enctype="multipart/form-data">

subject <input name="subject" type="text" />

<textarea name="body"></textarea>

logo <input name="logo“ type="file" />

<input type="submit" value="save" />

<input name=":redirect" value="/content/forum.html" type="hidden" />

</form>

}

}

33

Forum: form data

POST should add new child node to /content/forum/

Page 34: Scala for Sling - Apache Software Foundation

object ThreadNewForm {

def render = {

<h1>start a new thread</h1>

<form action="/content/forum/*" method="POST"

enctype="multipart/form-data">

subject <input name="subject" type="text" />

<textarea name="body"></textarea>

logo <input name="logo“ type="file" />

<input type="submit" value="save" />

<input name=":redirect" value="/content/forum.html" type="hidden" />

</form>

}

}

34

Forum: form data

POST should add new child node to /content/forum/

... with properties subject and body of

type String,

Page 35: Scala for Sling - Apache Software Foundation

object ThreadNewForm {

def render = {

<h1>start a new thread</h1>

<form action="/content/forum/*" method="POST"

enctype="multipart/form-data">

subject <input name="subject" type="text" />

<textarea name="body"></textarea>

logo <input name="logo“ type="file" />

<input type="submit" value="save" />

<input name=":redirect" value="/content/forum.html" type="hidden" />

</form>

}

}

35

Forum: form data

POST should add new child node to /content/forum/

... with properties subject and body of

type String,

... and a child node logo of type nt:file.

Page 36: Scala for Sling - Apache Software Foundation

object ThreadNewForm {

def render = {

<h1>start a new thread</h1>

<form action="/content/forum/*" method="POST"

enctype="multipart/form-data">

subject <input name="subject" type="text" />

<textarea name="body"></textarea>

logo <input name="logo“ type="file" />

<input type="submit" value="save" />

<input name=":redirect" value="/content/forum.html" type="hidden" />

</form>

}

}

36

Forum: form data

Redirect to forum.html on success

Page 37: Scala for Sling - Apache Software Foundation

37

Extracting form fields

> Sling post servlet

– No action required: used by default

– Creates nodes and properties for form fields

– Tweaked with hidden form fields

– Sensible defaults

> Custom POST request handler

– Write a script POST.scala

– Process form fields in code

– Full control over request processing

Page 38: Scala for Sling - Apache Software Foundation

38

Forum: custom POST request handlerpackage forum {

object POST {

import POST_Bindings._

// ...

val node = addNodes(session.root, newPath)

node.setProperty("body", request("body"))

node.setProperty(“subject", request(“subject"))

if (request("logo") != "") {

val logoNode = node.addNode("logo", "nt:file")

val contentNode = logoNode.addNode("jcr:content", "nt:resource")

val logo = request.getRequestParameter("logo")

contentNode.setProperty("jcr:lastModified", Calendar.getInstance)

contentNode.setProperty("jcr:mimeType", logo.getContentType)

contentNode.setProperty("jcr:data", logo.getInputStream)

}

session.save

response.sendRedirect(request(":redirect"))

}

}

Page 39: Scala for Sling - Apache Software Foundation

39

Forum: custom POST request handlerpackage forum {

object POST {

import POST_Bindings._

// ...

val node = addNodes(session.root, newPath)

node.setProperty("body", request("body"))

node.setProperty(“subject", request(“subject"))

if (request("logo") != "") {

val logoNode = node.addNode("logo", "nt:file")

val contentNode = logoNode.addNode("jcr:content", "nt:resource")

val logo = request.getRequestParameter("logo")

contentNode.setProperty("jcr:lastModified", Calendar.getInstance)

contentNode.setProperty("jcr:mimeType", logo.getContentType)

contentNode.setProperty("jcr:data", logo.getInputStream)

}

session.save

response.sendRedirect(request(":redirect"))

}

}

POST /forum.html

Page 40: Scala for Sling - Apache Software Foundation

40

Forum: custom POST request handlerpackage forum {

object POST {

import POST_Bindings._

// ...

val node = addNodes(session.root, newPath)

node.setProperty("body", request("body"))

node.setProperty(“subject", request(“subject"))

if (request("logo") != "") {

val logoNode = node.addNode("logo", "nt:file")

val contentNode = logoNode.addNode("jcr:content", "nt:resource")

val logo = request.getRequestParameter("logo")

contentNode.setProperty("jcr:lastModified", Calendar.getInstance)

contentNode.setProperty("jcr:mimeType", logo.getContentType)

contentNode.setProperty("jcr:data", logo.getInputStream)

}

session.save

response.sendRedirect(request(":redirect"))

}

}

Add node for this post

Page 41: Scala for Sling - Apache Software Foundation

41

Forum: custom POST request handlerpackage forum {

object POST {

import POST_Bindings._

// ...

val node = addNodes(session.root, newPath)

node.setProperty("body", request("body"))

node.setProperty(“subject", request(“subject"))

if (request("logo") != "") {

val logoNode = node.addNode("logo", "nt:file")

val contentNode = logoNode.addNode("jcr:content", "nt:resource")

val logo = request.getRequestParameter("logo")

contentNode.setProperty("jcr:lastModified", Calendar.getInstance)

contentNode.setProperty("jcr:mimeType", logo.getContentType)

contentNode.setProperty("jcr:data", logo.getInputStream)

}

session.save

response.sendRedirect(request(":redirect"))

}

}

Set properties for body and subject

Page 42: Scala for Sling - Apache Software Foundation

42

Forum: custom POST request handlerpackage forum {

object POST {

import POST_Bindings._

// ...

val node = addNodes(session.root, newPath)

node.setProperty("body", request("body"))

node.setProperty(“subject", request(“subject"))

if (request("logo") != "") {

val logoNode = node.addNode("logo", "nt:file")

val contentNode = logoNode.addNode("jcr:content", "nt:resource")

val logo = request.getRequestParameter("logo")

contentNode.setProperty("jcr:lastModified", Calendar.getInstance)

contentNode.setProperty("jcr:mimeType", logo.getContentType)

contentNode.setProperty("jcr:data", logo.getInputStream)

}

session.save

response.sendRedirect(request(":redirect"))

}

}

If the request contains a logo

Page 43: Scala for Sling - Apache Software Foundation

43

Forum: custom POST request handlerpackage forum {

object POST {

import POST_Bindings._

// ...

val node = addNodes(session.root, newPath)

node.setProperty("body", request("body"))

node.setProperty(“subject", request(“subject"))

if (request("logo") != "") {

val logoNode = node.addNode("logo", "nt:file")

val contentNode = logoNode.addNode("jcr:content", "nt:resource")

val logo = request.getRequestParameter("logo")

contentNode.setProperty("jcr:lastModified", Calendar.getInstance)

contentNode.setProperty("jcr:mimeType", logo.getContentType)

contentNode.setProperty("jcr:data", logo.getInputStream)

}

session.save

response.sendRedirect(request(":redirect"))

}

}

If the request contains a logo

... add a child node logo of type nt:file

Page 44: Scala for Sling - Apache Software Foundation

44

Forum: custom POST request handlerpackage forum {

object POST {

import POST_Bindings._

// ...

val node = addNodes(session.root, newPath)

node.setProperty("body", request("body"))

node.setProperty(“subject", request(“subject"))

if (request("logo") != "") {

val logoNode = node.addNode("logo", "nt:file")

val contentNode = logoNode.addNode("jcr:content", "nt:resource")

val logo = request.getRequestParameter("logo")

contentNode.setProperty("jcr:lastModified", Calendar.getInstance)

contentNode.setProperty("jcr:mimeType", logo.getContentType)

contentNode.setProperty("jcr:data", logo.getInputStream)

}

session.save

response.sendRedirect(request(":redirect"))

}

}

If the request contains a logo

... add a child node logo of type nt:file

... and set properties jcr:lastModified,

jcr:mimeType and jcr:data

Page 45: Scala for Sling - Apache Software Foundation

45

Forum: custom POST request handlerpackage forum {

object POST {

import POST_Bindings._

// ...

val node = addNodes(session.root, newPath)

node.setProperty("body", request("body"))

node.setProperty(“subject", request(“subject"))

if (request("logo") != "") {

val logoNode = node.addNode("logo", "nt:file")

val contentNode = logoNode.addNode("jcr:content", "nt:resource")

val logo = request.getRequestParameter("logo")

contentNode.setProperty("jcr:lastModified", Calendar.getInstance)

contentNode.setProperty("jcr:mimeType", logo.getContentType)

contentNode.setProperty("jcr:data", logo.getInputStream)

}

session.save

response.sendRedirect(request(":redirect"))

}

}

Save changes and send redirect

Page 46: Scala for Sling - Apache Software Foundation

object html_Bindings extends MockBindings {

override def currentNode = new MockNode

with MockItem

override def request = new MockSlingHttpServletRequest

with MockHttpServletRequest

with MockServletRequest

}

object Test extends Application {

forum.html

}

46

Forum: unit testing

Page 47: Scala for Sling - Apache Software Foundation

object html_Bindings extends MockBindings {

override def currentNode = new MockNode

with MockItem

override def request = new MockSlingHttpServletRequest

with MockHttpServletRequest

with MockServletRequest

}

object Test extends Application {

forum.html

}

47

Forum: unit testing

Page 48: Scala for Sling - Apache Software Foundation

object html_Bindings extends MockBindings {

override def currentNode = new MockNode

with MockItem

override def request = new MockSlingHttpServletRequest

with MockHttpServletRequest

with MockServletRequest

}

object Test extends Application {

forum.html

}

48

Forum: unit testing

Page 49: Scala for Sling - Apache Software Foundation

object html_Bindings extends MockBindings {

override def currentNode = new MockNode

with MockItem

override def request = new MockSlingHttpServletRequest

with MockHttpServletRequest

with MockServletRequest

}

object Test extends Application {

forum.html

}

49

Forum: unit testing<html>

<head>

<link href="/apps/forum/static/blue.css" rel="stylesheet"></link>

</head>

<body>

<div id="Header">

Welcome to the forum

&mdash; Wed Jun 17 17:12:48 CEST 2009

</div>

<div id="Menu">

<p>search all threads:

<form action="/content/forum.search.html"

enctype="multipart/form-data" method="GET">

<input value="" type="text" size="10" name="query"></input>

<input value="search" type="submit"></input>

</form>

</p>

</div>

<div id="Content">

<h1>start a new thread</h1>

<span id="inp">

<form action="/content/forum/*" enctype="multipart/form-data" method="POST">

<p>subject</p>

<p><input type="text" name="subject"></input></p>

<p><textarea name="body"></textarea></p>

<p>logo</p>

<p><input type="file" name="logo"></input></p>

<p><input value="save" type="submit"></input></p>

<input value="/content/forum.html" type="hidden" name=":redirect"></input>

</form>

</span>

</div>

</body>

</html>

Page 50: Scala for Sling - Apache Software Foundation

50

AGENDA

> Introduction

> What is Apache Sling?

> What is Scala?

> Scala for Sling

> Summary and questions

Page 51: Scala for Sling - Apache Software Foundation

51

Conclusion

> Advantages

– Scala!

– No language boundary

– Tool support (i.e. IDE, ScalaDoc,

safe refactoring, unit testing)

> Disadvantages

– IDE support shaky, improves

quickly though

– Not much refactoring support as

of today

Page 52: Scala for Sling - Apache Software Foundation

52

Conclusion

> Advantages

– Scala!

– No language boundary

– Tool support (i.e. IDE, ScalaDoc,

safe refactoring, unit testing)

> Disadvantages

– IDE support shaky, improves

quickly though

– Not much refactoring support as

of today

Page 53: Scala for Sling - Apache Software Foundation

53

Conclusion

> Advantages

– Scala!

– No language boundary

– Tool support (i.e. IDE, ScalaDoc,

safe refactoring, unit testing)

> Disadvantages

– IDE support shaky, improves

quickly though

– Not much refactoring support as

of today

<p>Welcome to { currentNode("name") } forum</p>

&mdash; { Calendar.getInstance.getTime }

{ ThreadNewForm.render }

{ ThreadOverview.render(currentNode) }

Page 54: Scala for Sling - Apache Software Foundation

54

Conclusion

> Advantages

– Scala!

– No language boundary

– Tool support (i.e. IDE, ScalaDoc,

safe refactoring, unit testing)

> Disadvantages

– IDE support shaky, improves

quickly though

– Not much refactoring support as

of today

Page 55: Scala for Sling - Apache Software Foundation

55

Conclusion

> Advantages

– Scala!

– No language boundary

– Tool support (i.e. IDE, ScalaDoc,

safe refactoring, unit testing)

> Disadvantages

– IDE support shaky, improves

quickly though

– Not much refactoring support as

of today

Page 56: Scala for Sling - Apache Software Foundation

56

Conclusion

> Advantages

– Scala!

– No language boundary

– Tool support (i.e. IDE, ScalaDoc,

safe refactoring, unit testing)

> Disadvantages

– IDE support shaky, improves

quickly though

– Not much refactoring support as

of today

object html_Bindings {

def currentNode = new MockNode

...

}

object Test extends Application {

forum.html

}

Page 57: Scala for Sling - Apache Software Foundation

57

Conclusion

> Advantages

– Scala!

– No language boundary

– Tool support (i.e. IDE, ScalaDoc,

safe refactoring, unit testing)

> Disadvantages

– IDE support shaky, improves

quickly though

– Not much refactoring support as

of today

Page 58: Scala for Sling - Apache Software Foundation

58

Summary

> Apache Sling

– Great for building RESTful web applications

– Pluggable scripting support (JSR-223)

> Scala

– Great for scripting

– Supports «on the fly» templates through XML literals

– Easy unit testing

Page 59: Scala for Sling - Apache Software Foundation

LOGO SPEAKER‘S COMPANY

Michael Dürig [email protected]

Michael Marth [email protected]

Day Software AG http://www.day.com/

References:

• Scala for Sling: http://people.apache.org/~mduerig/scala4sling/

• The Scala programming language: http://www.scala-lang.org/

• Apache Sling: http://incubator.apache.org/sling/