Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
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

355 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
  • Be the first to comment

  • Be the first to like this

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

×