javantura v2 - all together now - making groovy and scala sing together - dinko srkoč
Upload: hujak-hrvatska-udruga-java-korisnika-croatian-java-user-association
Post on 05-Jul-2015
504 views
DESCRIPTION
Can two JVM languages, none of them Java, work harmoniously, side by side? Should they? In this lecture we’ll see how code written in Groovy and Scala work with Java and how they can be made to work with each other. The lecture is based on the experience of introducing Scala to an actual Groovy project.TRANSCRIPT
![Page 1: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/1.jpg)
All Together Nowmaking Groovy and Scala sing together
Dinko Srkoč, Helix d.o.o.
1 / 33
![Page 2: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/2.jpg)
Agenda1. Introduction
2. Communication with Java
Java & Groovy
Java & Scala
3. Communication without Java
Scala & Groovy
4. Trouble with Dependencies
2 / 33
1 / 33
![Page 3: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/3.jpg)
Introductionmotivation, build systems, about Groovy/Scala
3 / 33
![Page 4: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/4.jpg)
3 / 33
MotivationWhy would anyone use Groovy and Scala in the same project?
4 / 33
![Page 5: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/5.jpg)
MotivationWhy would anyone use Groovy and Scala in the same project?
For us: using Akka in a Groovy project
concurrency
remoting + symmetric communication
5 / 33
![Page 6: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/6.jpg)
Build SystemThe choice: Ant, Maven, ?
6 / 33
![Page 7: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/7.jpg)
Build SystemThe choice: Ant, Maven, ?
The actual choice: SBT vs Gradle
7 / 33
![Page 8: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/8.jpg)
Build SystemThe choice: Ant, Maven, ?
The actual choice: SBT vs Gradle
8 / 33
![Page 9: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/9.jpg)
Build SystemThe choice: Ant, Maven, ?
The actual choice: SBT vs Gradle
supports Groovy and Scala equally well
easy to write build scripts
DSL in Groovy
(we were already using it)
9 / 33
![Page 10: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/10.jpg)
Gradle example:
apply plugin: 'groovy'apply plugin: 'scala'
repositories { mavenCentral()}
dependencies { compile 'org.codehaus.groovy:groovy-all:2.3.7' compile "org.scala-lang:scala-library:2.11.4"}
// Scala: zinc based compiler - incremental compilationtasks.withType(ScalaCompile) { scalaCompileOptions.useAnt = false }
// order of compilation:// 1. Java// 2. Groovy// 3. ScalacompileScala.dependsOn(compileGroovy)
10 / 33
![Page 11: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/11.jpg)
Communication with JavaGroovy & Java (match made in heaven)
Scala & Java (match made in Scala)
11 / 33
![Page 12: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/12.jpg)
11 / 33
Java from GroovyA no-brainer
import java.util.List;
public interface IJava { Integer sum(List<Integer> xs);}
import org.apache.commons.lang3.RandomStringUtils as RndStr
class GroovyClass implements IJava { Integer id
Integer sum(List xs) { xs.sum() }
String rndStr() { RndStr.random(10) }}
12 / 33
![Page 13: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/13.jpg)
Groovy from Javajoint compilation mode
class GroovyClass { Integer id def calc(a, Closure cl) { cl(a) }}
import groovy.lang.Closure;
class JavaClass { public static void main(String[] args) { GroovyClass gcl = new GroovyClass(); // in Groovy: new GroovyClass(id: 42)
gcl.setId(42); // in Groovy: gcl.id = 42 System.out.println("id=" + gcl.getId()); // in Groovy: gcl.id
gcl.calc(1, new Closure<Object>(null) { // in Groovy: gcl.calc(1) { a } Object doCall(Object a) { System.out.println(a); return a; } }); }}
13 / 33
![Page 14: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/14.jpg)
About Joint Compilationresolves circular dependencies between Java, Groovy, and back again:
public class JavaClass {} // in JavaClass.java
class GroovyClass extends JavaClass {} // in GroovyClass.groovy
public class JavaClass2 extends GroovyClass {} // in JavaClass2.java
process:
1. Groovy compiler makes stubs from Groovy code
2. Groovy compiler puts Groovy stubs from step (1) on the classpath and
invokes Java compiler
3. Java compiler compiles Java code (Groovy dependencies resolved
from stubs)
4. Groovy compiler compiles Groovy code (Java dependencies resolved
from compiled Java code)
14 / 33
![Page 15: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/15.jpg)
Java & GroovyGroovy tries to be as close to Java as possible:
similar syntax
uses Java's data structures
straightforward to use from Java
Groovy's Java API extensions can be used via DefaultGroovyMethods
dynamic meta progamming stuff not available from Java
traits (new feature in Groovy 2.3) awkward from Java
15 / 33
![Page 16: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/16.jpg)
Java from Scalaimport java.util.List;
public interface IJava { Integer sum(List<Integer> xs);}public class JavaClass { public String aValue();}
import java.util.{ List ⇒ JList }
import org.apache.commons.lang3.{ RandomStringUtils ⇒ RndStr }
class ScalaClass(var id: Int) extends IJava {
override def sum(xs: JList[Integer]): Integer = { import scala.collection.JavaConverters._ // List(1, 2, 3).sum ... works, but // xs.sum ... doesn't
xs.asScala.foldLeft(0) { (acc, x) ⇒ acc + x } }
def calcVal(javaClass: JavaClass): String =
Option(javaClass.aValue()).map { s ⇒ change(s) } getOrElse "(undefined)"
16 / 33
![Page 17: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/17.jpg)
def rndStr = RndStr.random(10)
Java from Scalaimport java.util.List;
public interface IJava { Integer sum(List<Integer> xs);}public class JavaClass { public String aValue();}
import java.util.{ List ⇒ JList }
import org.apache.commons.lang3.{ RandomStringUtils ⇒ RndStr }
class ScalaClass(var id: Int) extends IJava {
override def sum(xs: JList[Integer]): Integer = { import scala.collection.JavaConverters._ // List(1, 2, 3).sum ... works, but // xs.sum ... doesn't
xs.asScala.foldLeft(0) { (acc, x) ⇒ acc + x } }
def calcVal(javaClass: JavaClass): String =
Option(javaClass.aValue()).map { s ⇒ change(s) } getOrElse "(undefined)"
17 / 33
![Page 18: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/18.jpg)
def rndStr = RndStr.random(10)
Java from Scalaimport java.util.List;
public interface IJava { Integer sum(List<Integer> xs);}public class JavaClass { public String aValue();}
import java.util.{ List ⇒ JList }
import org.apache.commons.lang3.{ RandomStringUtils ⇒ RndStr }
class ScalaClass(var id: Int) extends IJava {
override def sum(xs: JList[Integer]): Integer = { import scala.collection.JavaConverters._ // List(1, 2, 3).sum ... works, but // xs.sum ... doesn't
xs.asScala.foldLeft(0) { (acc, x) ⇒ acc + x } }
def calcVal(javaClass: JavaClass): String =
Option(javaClass.aValue()).map { s ⇒ change(s) } getOrElse "(undefined)"
18 / 33
![Page 19: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/19.jpg)
def rndStr = RndStr.random(10)
Java from Scalaimport java.util.List;
public interface IJava { Integer sum(List<Integer> xs);}public class JavaClass { public String aValue();}
import java.util.{ List ⇒ JList }
import org.apache.commons.lang3.{ RandomStringUtils ⇒ RndStr }
class ScalaClass(var id: Int) extends IJava {
override def sum(xs: JList[Integer]): Integer = { import scala.collection.JavaConverters._ // List(1, 2, 3).sum ... works, but // xs.sum ... doesn't
xs.asScala.foldLeft(0) { (acc, x) ⇒ acc + x } }
def calcVal(javaClass: JavaClass): String =
Option(javaClass.aValue()).map { s ⇒ change(s) } getOrElse "(undefined)"
19 / 33
![Page 20: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/20.jpg)
def rndStr = RndStr.random(10)
Scala from Javajoint compilation mode
class ScalaClass(var id: Int) {
def calc(a: Int, f: Int ⇒ Int): Int = f(a) def -> (x: Int): Int = x + 1}
import scala.runtime.AbstractFunction1;
public class JavaClass {
public static void main(String[] args) { ScalaClass scl = new ScalaClass(1);
scl.id_$eq(42); // in Scala: scl.id = 42 System.out.println("id = " + scl.id()); // in Scala: scl.id
int i = scl.$minus$greater(1); // in Scala: scl -> 1
scl.calc(new AbstractFunction1<Integer, Integer>() { public Integer apply(Integer i) { return i * 2; }
}); // in Scala: scl.calc(i ⇒ i * 2) }}
20 / 33
![Page 21: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/21.jpg)
Scala from Javajoint compilation mode
class ScalaClass(var id: Int) {
def calc(a: Int, f: Int ⇒ Int): Int = f(a) def -> (x: Int): Int = x + 1}
import scala.runtime.AbstractFunction1;
public class JavaClass {
public static void main(String[] args) { ScalaClass scl = new ScalaClass(1);
scl.id_$eq(42); // in Scala: scl.id = 42 System.out.println("id = " + scl.id()); // in Scala: scl.id
int i = scl.$minus$greater(1); // in Scala: scl -> 1
scl.calc(new AbstractFunction1<Integer, Integer>() { public Integer apply(Integer i) { return i * 2; }
}); // in Scala: scl.calc(i ⇒ i * 2) }}
21 / 33
![Page 22: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/22.jpg)
Scala from Javajoint compilation mode
class ScalaClass(var id: Int) {
def calc(a: Int, f: Int ⇒ Int): Int = f(a) def -> (x: Int): Int = x + 1}
import scala.runtime.AbstractFunction1;
public class JavaClass {
public static void main(String[] args) { ScalaClass scl = new ScalaClass(1);
scl.id_$eq(42); // in Scala: scl.id = 42 System.out.println("id = " + scl.id()); // in Scala: scl.id
int i = scl.$minus$greater(1); // in Scala: scl -> 1
scl.calc(new AbstractFunction1<Integer, Integer>() { public Integer apply(Integer i) { return i * 2; }
}); // in Scala: scl.calc(i ⇒ i * 2) }}
22 / 33
![Page 23: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/23.jpg)
Scala from Javajoint compilation mode
class ScalaClass(var id: Int) {
def calc(a: Int, f: Int ⇒ Int): Int = f(a) def -> (x: Int): Int = x + 1}
import scala.runtime.AbstractFunction1;
public class JavaClass {
public static void main(String[] args) { ScalaClass scl = new ScalaClass(1);
scl.id_$eq(42); // in Scala: scl.id = 42 System.out.println("id = " + scl.id()); // in Scala: scl.id
int i = scl.$minus$greater(1); // in Scala: scl -> 1
scl.calc(new AbstractFunction1<Integer, Integer>() { public Integer apply(Integer i) { return i * 2; }
}); // in Scala: scl.calc(i ⇒ i * 2) }}
23 / 33
![Page 24: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/24.jpg)
Java & ScalaScala uses Java libs easily, but guarding against null is common -
prevalence of Option on boundaries with Java
conversions between Java and Scala collections
Scala operators can have funny names in Java
(e.g. :: (cons) is seen as $colon$colon in Java)
Scala is semantically richer - some concepts are different or have no
equivalent in Java
declaration site variance vs use site variance (wildcards) annotations
abstract types (no equivalence in Java)
algebraic data types vs Java enums
Scala traits are awkward from Java
24 / 33
![Page 25: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/25.jpg)
Communication without JavaGroovy <3 Scala ?
25 / 33
![Page 26: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/26.jpg)
25 / 33
Scala & Groovyusing code from one language in another is no more difficult than using it
from Java
26 / 33
![Page 27: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/27.jpg)
Scala & Groovyusing code from one language in another is no more difficult than using it
from Java
but
27 / 33
![Page 28: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/28.jpg)
Scala & Groovyusing code from one language in another is no more difficult than using it
from Java
but
having circular dependencies is problematic
because there is no joint compilation
28 / 33
![Page 29: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/29.jpg)
Trouble with Dependenciesjoint compilation - not!
29 / 33
![Page 30: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/30.jpg)
29 / 33
Example (1/2)order of compilation (defined in Gradle build script):
1. Groovy
2. Scala
class GroovyClass { def process() { def scl = new ScalaClass() // depends on not yet compiled scl.calc(42) // scala code }}
class ScalaClass { def calc(Int i): String = ???}
How to compile the above code?
30 / 33
![Page 31: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/31.jpg)
Example (2/2)a clumsy solution (a.k.a. a hack)
class ScalaClass { String calc(int i) { throw new Exception("This is a stub. Not to be used!") }}
class GroovyClass { def process() { def scl = new ScalaClass() // Groovy compiler sees scl.calc(42) // ScalaClass as Groovy code }}
class ScalaClass { // Scala compiler overrides def calc(Int i): String = ??? // Groovy's ScalaClass}
31 / 33
![Page 32: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/32.jpg)
Summarywith API designed for interoperability Groovy and Scala
can sing harmoniously (more or less)
avoid circular dependencies if possible
Pain points
no joint compile mode other than with Java
different data structures - needs conversion
functional expressions of one language translate to anonymous class
construction in other
different programming idioms can cause more verbose code on the other
side
32 / 33
![Page 33: Javantura v2 - All Together Now - making Groovy and Scala sing together - Dinko Srkoč](https://reader035.vdocuments.us/reader035/viewer/2022062514/559867451a28abc92f8b4847/html5/thumbnails/33.jpg)
Thank you!
Q & A
Slideshow created with remark.
Drawings by yours truly.
33 / 33