2011-10-31 | 09:45 AM - 10:30 AM
Spring 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.
The 7 Things I Know About Cyber Security After 25 Years | April 2024
Spring Day | Spring and Scala | Eberhard Wolff
1. Scala and Spring
Eberhard Wolff
Architecture and Technology Manager
adesso AG, Germany
2. Why Scala and Spring?
• Scala • Spring
– Strongly typed – The tools for
language enterprise apps
– Elegant – Well established
– Functional – Lots of know how
programming – Very flexible
– Focus on
Concurrency
– Lack of enterprise
frameworks
3. 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?
6. 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
7. Example
• DAO depends on a DataSource
• Injected in the constructor
• Matches Scala’s immutability approach
class CustomerDAO(dataSource: DataSource) {
val jdbcTemplate = new JdbcTemplate(dataSource)
...
}
8. 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
9. 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>
10. 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
11. 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>
12. 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
13. Spring JavaConfig with Scala
@Configuration
class ScalaConfig { Defined in
XML
@Autowired
var dataSource: DataSource = _
@Bean Not really
def transactionManager() = elegant..
new DataSourceTransactionManager(dataSource)
@Bean
def customerDAO() = new CustomerDAO(dataSource)
}
14. 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
20. Service Abstraction
• Example: JDBC
• Common advantages:
– Runtime exceptions instead of checked
exceptions
– Uniform API (e.g. transactions)
– Resource handling solved
21. 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)
}
22. 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
23. 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);
}
}
24. Callbacks in Scala
• Callbacks are really functions
• Called on each row
• Use template with Scala function?
25. 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
}
26. 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]
}
}
27. 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
32. 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
33. AOP Example
@Aspect
public 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);
}
}
34. 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 * *(..))
35. 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?
36. Functions
• Can use functions to “wrap” methods,
blocks and functions and do
transactions
• Based on TransactionTemplate
and callbacks
37. 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)
}
38. 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()
}
40. 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
41. 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()
…}
}
43. 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
44. 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
45. Potential Improvements
• AOP
– Provide functions for all common aspects
• Testing
– Support Scala test frameworks
– http://www.cakesolutions.org/specs2-
spring.html
46. 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
functionalities
http://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