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


Top Related