Bernhard Wenzel
www.bernhardwenzel.com
Using Spring with Scala
Spring I/O
2016
Overview
1.Introduction & Motivation
2.Practical examples
3.Evaluation
4.Questions
Spring I/O
2016
Target audience
• Developers with Java/Spring background
• Scala curious or beginner
Spring I/O
2016
Why Spring + Scala?
Spring I/O
2016
Why Spring + Scala?
Spring I/O
2016
Why Scala?
• For fun
• Learning a new language makes me a better
developer
• Functional Programming!
• For...
Spring I/O
2016
What I like about Scala
(as a Java dev)
• Code tends to be more concise
• Scala was built for FP from grou...
Spring I/O
2016
Why Scala & Spring
• Learning a new language is enough, I’d like to keep
my favourite frameworks & tools (...
Spring I/O
2016
2. Examples
www.spring.io/guides
Spring I/O
2016
Translated guides from Java to Scala
• Copy & Paste of Java files into Scala dir
• Transformed each .java ...
Spring I/O
2016
First example: serving web content
with Spring MVC
Spring I/O
2016
Make Gradle work with Scala
build.gradle
...
apply plugin: 'scala'
apply plugin: 'application'
mainClassNa...
Spring I/O
2016
Application class
@SpringBootApplication
public class Application {
public static void main(String[] args)...
Spring I/O
2016
Template
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving...
Spring I/O
2016
Controller
@Controller
public class GreetingController {
@RequestMapping("/greeting")
public String greeti...
Spring I/O
2016
That’s it
$ gradle run
. . .
2016-05-06 16:05:52.644 INFO 1297 --- [ restartedMain] s.b.c.e.t.TomcatEmbedd...
Spring I/O
2016
Translation steps:
• Gradle: add scala plugin (optional application)
• Application class: split into compa...
Spring I/O
2016
Example: consuming REST
services
Spring I/O
2016
Beans in Java
Value.java
@JsonIgnoreProperties(ignoreUnknown = true)
public class Value {
private Long id;...
Spring I/O
2016
Beans in Scala
Value.scala
@JsonIgnoreProperties(ignoreUnknown = true)
class Value {
@BeanProperty
var id:...
Spring I/O
2016
Application class
public void run(String... args) throws Exception {
RestTemplate restTemplate = new RestT...
Spring I/O
2016
Asynchronous version using Lambdas
Application.java
AsyncRestTemplate asyncTemplate = new AsyncRestTemplat...
Spring I/O
2016
Java 8 Lambdas vs.
Scala function literals
(a:Int, b:Int) => a + b
Scala function literal
(Integer a, Inte...
Spring I/O
2016
Asynchronous version
Application.scala
quoteFuture.addCallback(
(success: SuccessCallback[ResponseEntity[Q...
Spring I/O
2016
Asynchronous version
Scala functions =! Java Lambdas
quoteFuture.addCallback(
(success: SuccessCallback[Re...
Spring I/O
2016
We need ugly anonymous classes
Application.scala
quoteFuture.addCallback(new ListenableFutureCallback[Resp...
Spring I/O
2016
Works in Scala
$ gradle run
. ____ _ __ _ _
/ / ___'_ __ _ _(_)_ __ __ _    
( ( )___ | '_ | '_| | '_ / _`...
Spring I/O
2016
Translation steps
• Beans: use @BeanProperty annotation
• Java 8 Lambdas != Scala function literals, in Sc...
Spring I/O
2016
Providing REST API using Spring Data
Rest
Spring I/O
2016
Person resource in Scala
@Entity
class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@BeanP...
Spring I/O
2016
Repository
@RepositoryRestResource(collectionResourceRel = "people",
path = "people")
public interface Per...
Spring I/O
2016
Oops…
PersonRepository.scala:8: type arguments [hello.Person,Long]
do not conform to trait PagingAndSortin...
Spring I/O
2016
Repository
PersonRepository.scala
@RepositoryRestResource(collectionResourceRel = "people",
path = "people...
Spring I/O
2016
Spring Data Rest in Scala
$ curl http://localhost:8080
{
"_links" : {
"people" : {
"href" : "http://localh...
Spring I/O
2016
Translation steps
• When using Java/Spring interface, beware of Java
base types
Spring I/O
2016
Final example: JDBC
public void run(String... strings) throws Exception {
jdbcTemplate.execute("DROP TABLE...
Spring I/O
2016
JDBC: Java Batch Update
// Use a Java 8 stream to print out each tuple of the list
splitUpNames.forEach(
n...
Spring I/O
2016
jdbcTemplate.query(
"SELECT id, first_name, last_name FROM customers " +
"WHERE first_name = ?",
new Objec...
Spring I/O
2016
override def run(args: String*): Unit = {
jdbcTemplate.execute("DROP TABLE customers IF EXISTS")
jdbcTempl...
Spring I/O
2016
JDBC Scala names
collection
import scala.collection.mutable.ListBuffer
val splitUpNames = ListBuffer(
"Joh...
Spring I/O
2016
jdbcTemplate.batchUpdate(
"INSERT INTO customers(first_name, last_name) VALUES (?,?)“,
splitUpNames
.asIns...
Spring I/O
2016
JDBC Scala batchUpdate
Still a Scala collection
jdbcTemplate.batchUpdate(
"INSERT INTO customers(first_nam...
Spring I/O
2016
Convert from Scala
JavaConverters.asJava <- Scala
import collection.JavaConverters._
jdbcTemplate.batchUpd...
Spring I/O
2016
jdbcTemplate.query(
"SELECT id, first_name, last_name FROM customers WHERE first_name = ?",
Array("Josh")....
Spring I/O
2016
JDBC Scala print query
Returns Java collection
jdbcTemplate.query(
. . .
).foreach(…)
Spring I/O
2016
import collection.JavaConverters._
jdbcTemplate.query(
. . .
).asScala
.foreach((customer:Customer)
=> log...
Spring I/O
2016
Works in Scala
$ gradle run
. ____ _ __ _ _
/ / ___'_ __ _ _(_)_ __ __ _    
( ( )___ | '_ | '_| | '_ / _`...
Spring I/O
2016
Translation steps
• Use Scala mutable collection when calling Java
• Type casting
• Java Object/Scala AnyR...
Spring I/O
2016
3. Evaluation
Spring I/O
2016
We „just“ need to translate from Scala to Java
and vice versa
3. Evaluation
Good news: it works!
Spring I/O
2016
Spring I/O
2016
Simple translation steps
• add Scala plugin to Gradle
• Application class requires object
• add Array to @...
Spring I/O
2016
Slightly annoying translation steps
• Avoiding Scala base types for Sprint interfaces
• Casting to/from Ja...
Spring I/O
2016
Annoying translation step
• Can’t use Scala functions as Java 8 Lamdbas
Spring I/O
2016
Annoying translation step
Will work in Scala 2.12
jdbcTemplate.query(
"SELECT id, first_name, last_name FR...
Spring I/O
2016
Scala SDK is getting better dealing with Java
• Additional frameworks?
• e.g. defunct (Pivotal) Spring-Sca...
Spring I/O
2016
Conclusion
• It works. Spring is just another Java framework that
I can use from Scala
Spring I/O
2016
Conclusion
• Drawbacks using Spring instead of pure Scala
framework:
• not always able to write most idiom...
Spring I/O
2016
Conclusion
• Advantages:
• I can keep my Spring productivity & use a well
proven framework while focusing ...
Spring I/O
2016
Thank you
• Source code available at Github:
github.com/BernhardWenzel/spring-scala-examples
• Slides and ...
Upcoming SlideShare
Loading in …5
×

Using Spring with Scala

300 views

Published on

Demonstrating the steps that are necessary to use Spring with Scala by translating Spring.io's guides from Java to Scala. A talk I have given at the Spring I/O 2016 in Barcelona

Published in: Software
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
300
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
12
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Using Spring with Scala

  1. 1. Bernhard Wenzel www.bernhardwenzel.com Using Spring with Scala
  2. 2. Spring I/O 2016 Overview 1.Introduction & Motivation 2.Practical examples 3.Evaluation 4.Questions
  3. 3. Spring I/O 2016 Target audience • Developers with Java/Spring background • Scala curious or beginner
  4. 4. Spring I/O 2016 Why Spring + Scala?
  5. 5. Spring I/O 2016 Why Spring + Scala?
  6. 6. Spring I/O 2016 Why Scala? • For fun • Learning a new language makes me a better developer • Functional Programming! • For profit • Scala is (becoming) popular: LinkedIn, Guardian, Twitter, many more ...
  7. 7. Spring I/O 2016 What I like about Scala (as a Java dev) • Code tends to be more concise • Scala was built for FP from ground up • In Scala I can mix OO + FP • Java interop allows to move gradually towards Scala • Java 8 is catching up (e.g. Lambdas) but Scala still has many other features (e.g. Pattern matching)
  8. 8. Spring I/O 2016 Why Scala & Spring • Learning a new language is enough, I’d like to keep my favourite frameworks & tools (SpringBoot, Gradle) • New languages come with new frameworks that are unproven • I want to gradually introduce Scala into my existing Java&Spring project
  9. 9. Spring I/O 2016 2. Examples www.spring.io/guides
  10. 10. Spring I/O 2016 Translated guides from Java to Scala • Copy & Paste of Java files into Scala dir • Transformed each .java into .scala • Kept Gradle as build tool • Source code available at GitHub (github.com/BernhardWenzel/spring-scala- examples)
  11. 11. Spring I/O 2016 First example: serving web content with Spring MVC
  12. 12. Spring I/O 2016 Make Gradle work with Scala build.gradle ... apply plugin: 'scala' apply plugin: 'application' mainClassName = "hello.Application" ... dependencies { ... compile 'org.scala-lang:scala-library:2.11.1' ... }
  13. 13. Spring I/O 2016 Application class @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } @SpringBootApplication class Application { } object Application extends App { SpringApplication.run(classOf[Application], args:_*) }
  14. 14. Spring I/O 2016 Template <!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Getting Started: Serving Web Content</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <p th:text="'Hello, ' + ${name} + '!'" /> </body> </html>
  15. 15. Spring I/O 2016 Controller @Controller public class GreetingController { @RequestMapping("/greeting") public String greeting( @RequestParam(value="name",required=false) String name, Model model) { model.addAttribute("name", name); return "greeting";}} @Controller class GreetingController { @RequestMapping(Array("/greeting")) def greeting( @RequestParam(value="name", required=false) name: String, model: Model) : String = { model.addAttribute("name", name) "greeting" }}
  16. 16. Spring I/O 2016 That’s it $ gradle run . . . 2016-05-06 16:05:52.644 INFO 1297 --- [ restartedMain] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat 2016-05-06 16:05:52.650 INFO 1297 --- [ restartedMain] scala.App$class : Started App.class in $ curl http://localhost:8080/greeting?name=SpringIO <!DOCTYPE HTML> <html> <head> <title>Getting Started: Serving Web Content</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <p>Hello, SpringIO!</p> </body> </html>
  17. 17. Spring I/O 2016 Translation steps: • Gradle: add scala plugin (optional application) • Application class: split into companion object in Scala and run with args:_* • Controller: @RequestMapping annotation need to convert String into Array(String)
  18. 18. Spring I/O 2016 Example: consuming REST services
  19. 19. Spring I/O 2016 Beans in Java Value.java @JsonIgnoreProperties(ignoreUnknown = true) public class Value { private Long id; private String quote; public Long getId() {return this.id;} public String getQuote() {return this.quote;} public void setId(Long id) {this.id = id;} public void setQuote(String quote) {this.quote = quote;} @Override public String toString() { return "Value{" + "id=" + id + ", quote='" + quote + ''' + '}'; }}
  20. 20. Spring I/O 2016 Beans in Scala Value.scala @JsonIgnoreProperties(ignoreUnknown = true) class Value { @BeanProperty var id: Long = _ @BeanProperty var quote: String = _ override def toString : String = "Value{id=" + id +", quote=" + quote +"}" }
  21. 21. Spring I/O 2016 Application class public void run(String... args) throws Exception { RestTemplate restTemplate = new RestTemplate(); Quote quote = restTemplate.getForObject( "http://gturnquist-quoters.cfapps.io/api/random", Quote.class); log.info(quote.toString()); } override def run(args: String*): Unit = { val restTemplate = new RestTemplate() val quote : Quote = restTemplate.getForObject( "http://gturnquist-quoters.cfapps.io/api/random", classOf[Quote]) log.info(quote.toString) }
  22. 22. Spring I/O 2016 Asynchronous version using Lambdas Application.java AsyncRestTemplate asyncTemplate = new AsyncRestTemplate(); final ListenableFuture<ResponseEntity<Quote>> quoteFuture = asy "http://gturnquist-quoters.cfapps.io/api/random", Quote.class); quoteFuture.addCallback( success -> log.info("async: " + quote), failure -> log.error("Async error", failure)); void addCallback( SuccessCallback<? super T> successCallback, FailureCallback failureCallback);
  23. 23. Spring I/O 2016 Java 8 Lambdas vs. Scala function literals (a:Int, b:Int) => a + b Scala function literal (Integer a, Integer b) -> a + b Java 8 lambdas
  24. 24. Spring I/O 2016 Asynchronous version Application.scala quoteFuture.addCallback( (success: SuccessCallback[ResponseEntity[Quote]]) => log.info("async: " + quote), (failure: FailureCallback) => log.error("Async error",failure))
  25. 25. Spring I/O 2016 Asynchronous version Scala functions =! Java Lambdas quoteFuture.addCallback( (success: SuccessCallback[ResponseEntity[Quote]]) => log.info("async: " + quote), (failure: FailureCallback) => log.error("Async error",failure)) Application.scala
  26. 26. Spring I/O 2016 We need ugly anonymous classes Application.scala quoteFuture.addCallback(new ListenableFutureCallback[ResponseEntit override def onSuccess(entity : ResponseEntity[Quote]) : Unit = log.info("async: " + entity.getBody.toString) override def onFailure(t : Throwable) : Unit = log.error("Async error", t) })
  27. 27. Spring I/O 2016 Works in Scala $ gradle run . ____ _ __ _ _ / / ___'_ __ _ _(_)_ __ __ _ ( ( )___ | '_ | '_| | '_ / _` | / ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |___, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.3.3.RELEASE) … 2016-05-02 11:44:49.052 INFO 3702 --- [ main] hello.Application : async: Quote{type='success' over configuration, providing an experience on par with frameworks that excel at early stage development, such as Ruby on Rails.}} … BUILD SUCCESSFUL
  28. 28. Spring I/O 2016 Translation steps • Beans: use @BeanProperty annotation • Java 8 Lambdas != Scala function literals, in Scala have to use anonymous classes
  29. 29. Spring I/O 2016 Providing REST API using Spring Data Rest
  30. 30. Spring I/O 2016 Person resource in Scala @Entity class Person { @Id @GeneratedValue(strategy = GenerationType.AUTO) @BeanProperty var id: Long = _ @BeanProperty var firstName: String = _ @BeanProperty var lastName: String = _ }
  31. 31. Spring I/O 2016 Repository @RepositoryRestResource(collectionResourceRel = "people", path = "people") public interface PersonRepository extends PagingAndSortingRepository<Person, Long> { List<Person> findByLastName(@Param("name") String name); } @RepositoryRestResource(collectionResourceRel = "people", path = "people") trait PersonRepository extends PagingAndSortingRepository[Person, Long] { def findByLastName(@Param("name") name: String): List[Person] }
  32. 32. Spring I/O 2016 Oops… PersonRepository.scala:8: type arguments [hello.Person,Long] do not conform to trait PagingAndSortingRepository's type parameter bounds [T,ID <: java.io.Serializable] trait PersonRepository extends PagingAndSortingRepository[Person, Long] { scala.Long != java.lang.Long
  33. 33. Spring I/O 2016 Repository PersonRepository.scala @RepositoryRestResource(collectionResourceRel = "people", path = "people") trait PersonRepository extends PagingAndSortingRepository[Person, java.lang.Long] { def findByLastName(@Param("name") name: String): List[Person] } Explicitly refer to Java base type import java.lang.Long
  34. 34. Spring I/O 2016 Spring Data Rest in Scala $ curl http://localhost:8080 { "_links" : { "people" : { "href" : "http://localhost:8080/people{?page,size,sort}", "templated" : true }, "profile" : { "href" : "http://localhost:8080/profile" } } }
  35. 35. Spring I/O 2016 Translation steps • When using Java/Spring interface, beware of Java base types
  36. 36. Spring I/O 2016 Final example: JDBC public void run(String... strings) throws Exception { jdbcTemplate.execute("DROP TABLE customers IF EXISTS"); jdbcTemplate.execute("CREATE TABLE customers(" + "id SERIAL, first_name VARCHAR(255), last_name VARCHAR(255) // Split up the array of whole names into an array of // first/last names List<Object[]> splitUpNames = Arrays .asList("John Woo", "Jeff Dean", "Josh Bloch", "Josh Long“) .stream() .map(name -> name.split(" ")) .collect(Collectors.toList()); . . .
  37. 37. Spring I/O 2016 JDBC: Java Batch Update // Use a Java 8 stream to print out each tuple of the list splitUpNames.forEach( name -> log.info(String.format( Inserting customer record for %s %s", name[0], name[1]))); // Uses JdbcTemplate's batchUpdate operation to // bulk load data jdbcTemplate.batchUpdate( "INSERT INTO customers(first_name, last_name) VALUES (?,?)", splitUpNames); log.info("Querying for customer records where first_name = 'Josh':");
  38. 38. Spring I/O 2016 jdbcTemplate.query( "SELECT id, first_name, last_name FROM customers " + "WHERE first_name = ?", new Object[] { "Josh" }, (rs, rowNum) -> new Customer( rs.getLong("id"), rs.getString("first_name"), rs.getString("last_name")) ).forEach(customer -> log.info(customer.toString())); public interface RowMapper<T> { T mapRow(ResultSet rs, int rowNum) throws SQLException; } public <T> List<T> query(String sql, Object[] args, RowMapper<T> rowMapper) JDBC: Java Query
  39. 39. Spring I/O 2016 override def run(args: String*): Unit = { jdbcTemplate.execute("DROP TABLE customers IF EXISTS") jdbcTemplate.execute("CREATE TABLE customers("id SERIAL, first_name VARCHAR(255), last_name VARCHAR(255))“) JDBC Scala create tables
  40. 40. Spring I/O 2016 JDBC Scala names collection import scala.collection.mutable.ListBuffer val splitUpNames = ListBuffer( "John Woo", "Jeff Dean", "Josh Bloch", "Josh Long“) .map(_.split(" ")) splitUpNames.foreach(name => log.info( "Inserting customer record for %s %s".format(name(0), name(1)))) Scala: collections are immutable java.util.List <-> scala.collection.mutable.Buffer
  41. 41. Spring I/O 2016 jdbcTemplate.batchUpdate( "INSERT INTO customers(first_name, last_name) VALUES (?,?)“, splitUpNames .asInstanceOf[mutable.Buffer[Array[AnyRef]]) JDBC Scala batchUpdate java.lang.Object <-> scala.AnyRef List<Object[]> <-> mutable.Buffer[Array[AnyRef]] public int[] batchUpdate(String sql, List<Object[]> batchArgs)
  42. 42. Spring I/O 2016 JDBC Scala batchUpdate Still a Scala collection jdbcTemplate.batchUpdate( "INSERT INTO customers(first_name, last_name) VALUES (?,?)“, splitUpNames .asInstanceOf[mutable.Buffer[Array[AnyRef]]) java.lang.Object <-> scala.AnyRef List<Object[]> <-> mutable.Buffer[Array[AnyRef]] public int[] batchUpdate(String sql, List<Object[]> batchArgs)
  43. 43. Spring I/O 2016 Convert from Scala JavaConverters.asJava <- Scala import collection.JavaConverters._ jdbcTemplate.batchUpdate( "INSERT INTO customers(first_name, last_name) VALUES (?,?)“, splitUpNames .asInstanceOf[mutable.Buffer[Array[AnyRef]].asJava)
  44. 44. Spring I/O 2016 jdbcTemplate.query( "SELECT id, first_name, last_name FROM customers WHERE first_name = ?", Array("Josh").asInstanceOf[Array[AnyRef]], new RowMapper[Customer]{ override def mapRow(rs: ResultSet, rowNum: Int): Customer = new Customer( rs.getLong("id"), rs.getString("first_name"), rs.getString("last_name")) }) JDBC Scala query (again casting Object -> AnyRef) (again implement anonymous class)
  45. 45. Spring I/O 2016 JDBC Scala print query Returns Java collection jdbcTemplate.query( . . . ).foreach(…)
  46. 46. Spring I/O 2016 import collection.JavaConverters._ jdbcTemplate.query( . . . ).asScala .foreach((customer:Customer) => log.info(customer.toString)) Convert from Java Java -> JavaConverters.asScala
  47. 47. Spring I/O 2016 Works in Scala $ gradle run . ____ _ __ _ _ / / ___'_ __ _ _(_)_ __ __ _ ( ( )___ | '_ | '_| | '_ / _` | / ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |___, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.3.3.RELEASE) ...[main] hello.Application: Creating tables ...[main] hello.Application: Inserting customer record for John Woo ...[main] hello.Application: Inserting customer record for Jeff Dean ...[main] hello.Application: Inserting customer record for Josh Bloch ...[main] hello.Application: Inserting customer record for Josh Long ...[main] hello.Application: Querying for customer records where first_name = 'Josh': ...[main] hello.Application: Customer[id=3, firstName=Josh, lastName=Bloch] ...[main] hello.Application: Customer[id=4, firstName=Josh, lastName=Long]
  48. 48. Spring I/O 2016 Translation steps • Use Scala mutable collection when calling Java • Type casting • Java Object/Scala AnyRef, • Java []/Scala Array • Java List/Scala Buffer • Collection transformations asJava and asScala
  49. 49. Spring I/O 2016 3. Evaluation
  50. 50. Spring I/O 2016 We „just“ need to translate from Scala to Java and vice versa 3. Evaluation Good news: it works!
  51. 51. Spring I/O 2016
  52. 52. Spring I/O 2016 Simple translation steps • add Scala plugin to Gradle • Application class requires object • add Array to @Annotations(Array(…)) • Fields of beans require @BeanProperty annotation
  53. 53. Spring I/O 2016 Slightly annoying translation steps • Avoiding Scala base types for Sprint interfaces • Casting to/from Java (e.g. Java Object to Scala AnyRef) • Requiring scala.JavaTransformations toJava and toScala with collections • Using Scala mutable collections when interacting with Java
  54. 54. Spring I/O 2016 Annoying translation step • Can’t use Scala functions as Java 8 Lamdbas
  55. 55. Spring I/O 2016 Annoying translation step Will work in Scala 2.12 jdbcTemplate.query( "SELECT id, first_name, last_name FROM customers WHERE first_name = ?", Array("Josh").asInstanceOf[Array[AnyRef]], (rs: ResultSet, rowNum: Int) => new Customer( rs.getLong("id"), rs.getString("first_name"), rs.getString("last_name"))) • Can’t use Scala functions as Java 8 Lamdbas
  56. 56. Spring I/O 2016 Scala SDK is getting better dealing with Java • Additional frameworks? • e.g. defunct (Pivotal) Spring-Scala project • Eases some issues, e.g. no @BeanProperty necessary • Better to be consistent across all Java dependencies
  57. 57. Spring I/O 2016 Conclusion • It works. Spring is just another Java framework that I can use from Scala
  58. 58. Spring I/O 2016 Conclusion • Drawbacks using Spring instead of pure Scala framework: • not always able to write most idiomatic Scala code • translation from/to Java can be annoying sometimes
  59. 59. Spring I/O 2016 Conclusion • Advantages: • I can keep my Spring productivity & use a well proven framework while focusing on Scala features • Scala SDK constantly improving Java interop so current issues can be expected to become obsolete
  60. 60. Spring I/O 2016 Thank you • Source code available at Github: github.com/BernhardWenzel/spring-scala-examples • Slides and talk online: bernhardwenzel.com/blog/2016/04/22/using-spring- with-scala/ Contact: • http://bernhardwenzel.com • twitter: @bernhardwenzel

×