spring day | spring and scala | eberhard wolff

46
Scala and Spring Eberhard Wolff Architecture and Technology Manager adesso AG, Germany

Upload: jax-london

Post on 10-May-2015

964 views

Category:

Technology


1 download

DESCRIPTION

2011-10-31 | 09:45 AM - 10:30 AMSpring is widely used in the Java world - but does it make any sense to combine it with Scala? This talk gives an answer and shows how and why Spring is useful in the Scala world. All areas of Spring such as Dependency Injection, Aspect-Oriented Programming and the Portable Service Abstraction as well as Spring MVC are covered.

TRANSCRIPT

Page 1: Spring Day | Spring and Scala | Eberhard Wolff

Scala and Spring Eberhard Wolff

Architecture and Technology Manager adesso AG, Germany

Page 2: Spring Day | Spring and Scala | Eberhard Wolff

Why Scala and Spring?

•  Scala –  Strongly typed

language –  Elegant –  Functional

programming –  Focus on

Concurrency –  Lack of enterprise

frameworks

•  Spring –  The tools for

enterprise apps –  Well established –  Lots of know how –  Very flexible

Page 3: Spring Day | Spring and Scala | Eberhard Wolff

Spring‘s Core Elements

•  Dependency Injection – Organize the collaboration of objects

•  Aspect Oriented Programming – Handle cross cutting concerns like security

or transactions •  Portable Service Abstraction

– Easy, unified APIs for JMS, JDBC, tx … •  Testing •  How can they be used with Scala?

Page 4: Spring Day | Spring and Scala | Eberhard Wolff

Dependency Injection

Page 5: Spring Day | Spring and Scala | Eberhard Wolff

Dependency Injection

•  Depended objects are injected

•  Advantages: – Better handling of dependencies – Easier testability

– Easier configuration

Page 6: Spring Day | Spring and Scala | Eberhard Wolff

Dependency Injection

•  Dependency Injection is a Pattern •  i.e. you can implement it in code •  …and therefore in plain Scala •  Configuration in a file: more flexibility

– No compile / redeploy – Configure values, not just references

•  Spring offers a lot of approaches to DI

Page 7: Spring Day | Spring and Scala | Eberhard Wolff

Example •  DAO depends on a DataSource•  Injected in the constructor •  Matches Scala’s immutability approach

class CustomerDAO(dataSource: DataSource) { val jdbcTemplate = new JdbcTemplate(dataSource)...}

Page 8: Spring Day | Spring and Scala | Eberhard Wolff

On Singletons

•  Scala introduces objects as Singletons •  Example uses Scala classes •  Spring needs to do the creation so

Dependency Injection can be done •  Might consider @Configurable but

that adds AspectJ Load Time Weaving…

•  More flexibility concerning scopes

Page 9: Spring Day | Spring and Scala | Eberhard Wolff

Spring XML Configuration <beans ...> <jdbc:embedded-database type="HSQL" id="dataSource" /> <bean id="customerDAO" class="de.adesso.scalaspring.dao.CustomerDAO"> <constructor-arg ref="dataSource" /> </bean></beans>

Page 10: Spring Day | Spring and Scala | Eberhard Wolff

Spring XML Configuration

•  Very easy and little difference to Java •  For optional configuration:

Use @BeanProperty to generate getters and setters

•  Marks property as configurable by Spring

•  Might want to create your own Conversions to configure Scala types

Page 11: Spring Day | Spring and Scala | Eberhard Wolff

Spring XML & Scala Collections •  Scala has its own collection classes •  Cannot be configured with Spring XML

out of the box •  Need Conversions •  Or create custom namespace

<bean class="de.adesso....ScalaBean"> <property name="list" > <scala:list > <value type="java.lang.Integer">42</value> </scala:list> </property></bean>

Page 12: Spring Day | Spring and Scala | Eberhard Wolff

Spring JavaConfig

•  Allows the definition of Spring Beans using Java classes

•  Classes contain code to create Spring Beans

•  Still conforms to Spring Bean rules – Singleton, AOP, autowiring etc

•  Can be used with Scala

Page 13: Spring Day | Spring and Scala | Eberhard Wolff

Spring JavaConfig with Scala @Configurationclass ScalaConfig { @Autowired var dataSource: DataSource = _ @Bean def transactionManager() = new DataSourceTransactionManager(dataSource) @Bean def customerDAO() = new CustomerDAO(dataSource)}

Defined in XML

Not really elegant..

Page 14: Spring Day | Spring and Scala | Eberhard Wolff

Spring JavaConfig •  Almost like a Spring Configuration DSL •  No need for Spring Scala DSL (?) •  Full power of Scala for creating objects •  Can also add configuration for value from

properties files etc •  Also nice for infrastructure

•  But reconfiguration = recompiling and redeployment

Page 15: Spring Day | Spring and Scala | Eberhard Wolff

Annotations

•  Annotate classes •  Classpath scanned for annotated

classes •  These become Spring beans

Page 16: Spring Day | Spring and Scala | Eberhard Wolff

Annotations Code

<beans ... ><context:component-scan base-package="de.adesso.scalaspring.dao" />

@Componentclass CustomerDAO { @Autowired var dataSource: DataSource = _ }

Page 17: Spring Day | Spring and Scala | Eberhard Wolff

Annotations Code

<beans ... default-autowire="constructor"><context:component-scan base-package="de.adesso.scalaspring.dao" />

@Componentclass CustomerDAO(dataSource: DataSource) {}

Page 18: Spring Day | Spring and Scala | Eberhard Wolff

Naming Convention

<context:component-scan base-package="de.adesso.scalaspring.dao" use-default-filters="false"> <context:include-filter type="regex" expression=".*DAO" /></context:component-scan>

class CustomerDAO(dataSource: DataSource) {}

No annotations – just a naming convention

Page 19: Spring Day | Spring and Scala | Eberhard Wolff

Service Abstraction

Page 20: Spring Day | Spring and Scala | Eberhard Wolff

Service Abstraction

•  Example: JDBC •  Common advantages:

– Runtime exceptions instead of checked exceptions

– Uniform API (e.g. transactions) – Resource handling solved

Page 21: Spring Day | Spring and Scala | Eberhard Wolff

Service Abstraction: Code •  Works out of the box •  However, needs Java type issues (Integer)

class CustomerDAO(dataSource: DataSource) { val jdbcTemplate = new JdbcTemplate(dataSource) def deleteById(id: Int) = jdbcTemplate.update( "DELETE FROM CUSTOMER WHERE ID=?", id : java.lang.Integer)}

Page 22: Spring Day | Spring and Scala | Eberhard Wolff

More Complex

•  How can one access a ResultSet? •  Resource handled by JDBC •  Cannot return it – it has to be closed •  Solution: callback •  …and inner class

Page 23: Spring Day | Spring and Scala | Eberhard Wolff

Callbacks in Java public class CustomerDAO extends SimpleJdbcDaoSupport { private static final class CustomerResultSetRowMapper implements ParameterizedRowMapper<Customer> { public Customer mapRow(ResultSet rs, int rowNum) { Customer customer = new Customer(rs.getString(1), rs.getString(2), rs.getDouble(4)); customer.setId(rs.getInt(3)); return customer;

} } public List<Customer> getByName(String name) { return getSimpleJdbcTemplate() .query( "SELECT * FROM T_CUSTOMER WHERE NAME=?", new CustomerResultSetRowMapper(), name); }}

Page 24: Spring Day | Spring and Scala | Eberhard Wolff

Callbacks in Scala

•  Callbacks are really functions •  Called on each row

•  Use template with Scala function?

Page 25: Spring Day | Spring and Scala | Eberhard Wolff

Callback in Scala def findById(id: Int): Option[Customer] = { val result: Buffer[Customer] = jdbcTemplate.query( "SELECT * FROM CUSTOMER C WHERE C.ID=?", (rs: ResultSet) => { Customer(rs.getInt(1), rs.getString(2), rs.getString(3), rs.getDouble(4)) }, id : java.lang.Integer) result.headOption}

Page 26: Spring Day | Spring and Scala | Eberhard Wolff

Behind the Scenes: Implicit

•  Converts a function into a callback object

•  Transparently behind the scenes implicit def rowMapperImplicit[T]( func: (ResultSet) => T) = { new RowMapper[T] { def mapRow(rs: ResultSet, rowNum: Int) = func(rs).asInstanceOf[T] }}

Page 27: Spring Day | Spring and Scala | Eberhard Wolff

Some Problems

•  Scala value types and collections must be converted to Java objects (i.e. Int to Integer)

•  null instead of Option[T] •  classOf[T] instead of plain type

•  Wrapper would be more natural but more effort

Page 28: Spring Day | Spring and Scala | Eberhard Wolff

Aspect Oriented Programming

Page 29: Spring Day | Spring and Scala | Eberhard Wolff

Why AOP?

•  Centralized implementation of cross cutting concerns

•  E.g. security, transactions, tracing.. •  Aspect =

– Advice : executed code – Pointcut : where the code is executed

•  Let’s see some Pointcut expressions…

Page 30: Spring Day | Spring and Scala | Eberhard Wolff

execution(void hello())

Execution of method hello, no parameters, void return type

Page 31: Spring Day | Spring and Scala | Eberhard Wolff

execution(int com.ewolff.Service.hello(int))

Execution of method hello in class Service in package com.ewolff one int as parameters, int return type

Page 32: Spring Day | Spring and Scala | Eberhard Wolff

execution(* *Service.*(..))

Execution of any method in class with suffix Any number of parameters, any return type

Any Service i.e. add behavior to every service

(security, transaction)

Defines what constitutes a service

Proper and orderly usage of AOP

Page 33: Spring Day | Spring and Scala | Eberhard Wolff

AOP Example @Aspectpublic class TracingAspect {

@Before("execution(* com.ewolff.highscore..*.*(..))")public void traceEnter(JoinPoint joinPoint) { System.out.println("enter "+joinPoint);}

@After("execution(* com.ewolff.highscore..*.*(..))")public void traceExit(JoinPoint joinPoint) { System.out.println("exit "+joinPoint);}

}

Page 34: Spring Day | Spring and Scala | Eberhard Wolff

Problems

•  Must provide parameter less constructor •  Pointcut depends on Java type system •  Scala has a different type system •  Can combine Scala + Spring AOP

– Use bean Pointcut: bean(aVerySpecificBean) bean(*DAO)

– Or Annotations: execution(@retry.Retry * *(..))

Page 35: Spring Day | Spring and Scala | Eberhard Wolff

AOP and Scala: 2nd Thought

•  Spring AOP is not efficient •  Method calls are done dynamically •  AspectJ will make project setup too

complex •  A modern programming language

should handle cross cutting concerns •  E.g. meta programming in dynamic

languages •  Can we do better?

Page 36: Spring Day | Spring and Scala | Eberhard Wolff

Functions

•  Can use functions to “wrap” methods, blocks and functions and do transactions

•  Based on TransactionTemplate and callbacks

Page 37: Spring Day | Spring and Scala | Eberhard Wolff

Code implicit def txCallbackImplicit[T](func: => T)…def transactional[T]( propagation: Propagation = Propagation.REQUIRED, …) (func: => T): T = { val txAttribute = new TransactionAttributeWithRollbackRules( propagation,…) val txTemplate = new TransactionTemplate(txManager,txAttribute) txTemplate.execute(func)}

Page 38: Spring Day | Spring and Scala | Eberhard Wolff

Usage

•  Can be used to wrap any code block •  Not just methods •  But: No way to make a whole class /

system transactional

transactional(propagation = Propagation.REQUIRES_NEW) { customerDAO.save( Customer(0, "Wolff", "Eberhard", 42.0)) throw new RuntimeException()}

Page 39: Spring Day | Spring and Scala | Eberhard Wolff

Testing

Page 40: Spring Day | Spring and Scala | Eberhard Wolff

Testing in Spring

•  Injection in Test classes

•  Transaction handling – Start a transaction for each test method – At the end of the method: Rollback

•  Benefit: No need to clean up the database

•  Good start: No production code in Scala

Page 41: Spring Day | Spring and Scala | Eberhard Wolff

Testing with JUnit 4, Spring and Scala

@RunWith(classOf[SpringJUnit4ClassRunner])@Transactional@ContextConfiguration(Array("/spring/scalaSpringConfig.xml"))class CustomerDAOTest extends Config { @Autowired var customerDAO : CustomerDAO = null @Test def testSaveDelete() { val numberOfCustomersBefore = customerDAO.count() …}}

Page 42: Spring Day | Spring and Scala | Eberhard Wolff

Sum Up

Page 43: Spring Day | Spring and Scala | Eberhard Wolff

Sum Up

•  Scala and Spring are a good match •  Spring is very adaptable •  Dependency Injection

– Works, some improvements possible •  Service Abstraction

– Functions are a good fit •  AOP

– Can work with Scala but not ideal – Scala can do similar things with functions

Page 44: Spring Day | Spring and Scala | Eberhard Wolff

Potential Improvements

•  Dependency Injection – Support for all Scala collections – Support for Scala properties – Support for Scala singletons – Conversions for all basic Scala types – Spring configuration DSL

•  Service Abstraction – Provide implicits for all callbacks

Page 45: Spring Day | Spring and Scala | Eberhard Wolff

Potential Improvements

•  AOP – Provide functions for all common aspects

•  Testing – Support Scala test frameworks – http://www.cakesolutions.org/specs2-

spring.html

Page 46: Spring Day | Spring and Scala | Eberhard Wolff

Links •  https://github.com/ewolff/scala-spring •  Request for Scala version of Spring (only 12 votes)

https://jira.springsource.org/browse/SPR-7876 •  Scala and AspectJ: Approaching modularization of crosscutting

functionalitieshttp://days2011.scala-lang.org/sites/days2011/files/52.%20AspectJ.pdf

•  Sample for Spring Security and Scala https://github.com/tekul/scalasec

•  Spring Integration Scala DSL https://github.com/SpringSource/spring-integration-scala

•  (German) Thesis about Scala & Lift vs. Java EE: http://www.slideshare.net/adessoAG/vergleich-des-scala-webframeworks-lift-mit-dem-java-ee-programmiermodell

•  (German) Thesis about Scala, JSF and Hibernate: http://www.slideshare.net/bvonkalm/thesis-5821628