scala and spring

Post on 18-May-2015

15.279 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

This presentation shows how Spring can be used with Scala.

TRANSCRIPT

Eberhard Wolff Architecture and Technology Manager adesso AG, Germany

Spring und Scala

About me •  Eberhard Wolff •  Architecture & Technology Manager at adesso •  adesso is a leading IT consultancy in Germany •  Speaker •  Author (e.g. first German Spring book) •  Blog: http://ewolff.com •  Twitter: @ewolff •  http://slideshare.com/ewolff •  eberhard.wolff@adesso.de

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

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?

DEPENDENCY INJECTION

Dependency Injection

•  Depended objects are injected

•  Advantages: – Better handling of dependencies – Easier testability

– Easier configuration

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 •  XML, JavaConfig and Annotations

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

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

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

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>

Spring XML Configuration

•  Very easy and little difference to Java •  Scala won’t create getter and setter for

<property > •  So: Use Scala’s @BeanProperty to

generate getters and setters •  Marks property as configurable by Spring •  Might want to create your own Conversions

to configure Scala types

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>

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

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..

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

Annotations

•  Annotate classes •  Classpath scanned for annotated classes •  These become Spring beans

Annotations Code

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

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

Annotations Code

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

@Componentclass CustomerDAO(dataSource: DataSource) {}

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

SERVICE ABSTRACTION

Service Abstraction

•  Example: JDBC •  Common advantages:

– Runtime exceptions instead of checked exceptions

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

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)}

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

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); }}

Callbacks in Scala

•  Callbacks are really functions •  Called on each row

•  Use template with Scala function?

Callback in Scala

•  Why can the function be converted in a RowMapper?

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)) } : RowMapper[Customer] ,id : java.lang.Integer) result.headOption}

Implicit Conversions in Scala

•  Implicits allow conversion from one type to another

•  Example: Double to Int •  Used any time an Int is needed and a Double

is provided •  Can we use implicits to convert a function to

a callback class?

implicit def double2int(d:Double): Int = d.toInt

Implicit for Function to Callback

•  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) }}

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

ASPECT ORIENTED PROGRAMMING

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…

execution(void hello())

Execution of method hello, no parameters, void return type

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

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

Execution of any method in class in any package with suffix Service 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

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);}

}

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 * *(..))

Transactions with AOP

•  Spring’s @Transaction annotation •  AOP is used for transactions and security •  Mark a method or class as transactional •  AOP behind the scenes

@Transactionalclass CustomerDAO(dataSource: DataSource) { @Transactional def save(customer: Customer): Customer = { }}

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?

Functions

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

•  Based on TransactionTemplate and callbacks

•  TransactionTemplate executes callbacks in a transaction

Code

implicit def txCallbackImplicit[T](func: => T)…•  Again implicit •  Converts a function with return type T to a TransactionCallback

•  Now we need to call the TransactionTemplate to provide the transaction

•  A function will take the transaction configuration and call the passed in function

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

1st parameter: transaction configuration

2nd parameter: function

Call TransactionTemplate with function (converted to TransactionCallback) and configuration

Usage

•  Can wrap methods to make them transactional

@Componentclass TxCustomerDAO(dataSource: DataSource) { def save(customer: Customer): Customer = transactional() { jdbcTemplate.update(…); }}

Usage

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

system transactional

transactional(propagation=Propagation.REQUIRED){ customerDAO.save( Customer(0, "Wolff", "Eberhard", 42.0))}

TESTING

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

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() …}}

SUM UP

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

– XML works, some improvements possible – Annotations and JavaConfig: No problems

•  Service Abstraction – Functions are a good fit

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

Potential Improvements

•  Dependency Injection – Support for Scala collections mostly done – Support for Scala properties (no @BeanProperty) – Support for Scala Objects aka Singletons – Conversions for all basic Scala types – Spring configuration DSL (?)

•  Service Abstraction – Provide implicits for non-JDBC callbacks

Potential Improvements

•  AOP – Provide functions for all common aspects besides

transaction

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

Links •  https://github.com/ewolff/scala-spring •  Request for Scala version of Spring (only 16 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

www.AAAjobs.de

jobs@adesso.de

Wir suchen Sie als

Ø  Software-Architekt (m/w) Ø  Projektleiter (m/w) Ø  Senior Software Engineer (m/w)

Ø  Kommen Sie zum Stand und gewinnen Sie ein iPad 2!

top related