3.
INTRODUCTION
CATEGORIZATION OF APPROACHES
Pure Scala approaches: Subcut, Cake
Mixed Java/Scala approaches: Spring-Scala, Guice
Pure Java aproaches: Spring, CDI
4.
INTRODUCTION
WHY JAVA DI FRAMEWORKS AT ALL
Reason 1: Important for existing Java-based projects, when
you need to mix Java and Scala
Reason 2: Mature, proven solutions
5.
EVALUATION CRITERIA
1. As much as possible idiomatic approach
minimal usage of: vars, annotations, special
configuration files
ideal case pure Scala
2. Simple testing
Integration testing
Unit testing too
3. Good fit with Play!
4. No steep learning curve
6.
EVALUATION CRITERIA
Symbols used in evaluation
(+) pros
(-) cons
(±) it depends
8.
SPRING
1. Relies heavily on annotations (-)
2. External configuration file is needed (-)
3. Differences are minimal in relation to Java (±)
4. Immutability possible via constructor injection (+)
5. Setter injection requires additional work in Scala (±)
6. Popular well-designed Java framework (+)
7. More than just DI (±)
8. Various testing possibilities (±)
9.
SPRING SPECIALS
SETTER INJECTION
or
@org.springframework.stereotype.Controller
class Translate extends Controller {
@BeanProperty
@(Autowired @beanSetter)
var translator: Translator = _
...
}
@org.springframework.stereotype.Controller
class Translate extends Controller {
private var translator: Translator = _
@Autowired
def setTranslator(translator: Translator): Unit =
this.translator = translator
...
}
10.
SPRING-SCALA
1. No annotations (+)
2. Wiring in code, no external configuration file (+)
3. Work in progress (-)
4. Immutability via contructor injection (+)
5. Spring under the hood (+)
6. Provides DSL to use Spring templates (±)
7. Various testing possibilities (±)
11.
SPRING-SCALA SPECIALS
TEMPLATES
Improvements: functions, Options, manifests
ConnectionFactory connectionFactory = ...
JmsTemplate template = new JmsTemplate(connectionFactory);
template.send("queue", new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage("Hello World");
}
});
val connectionFactory : ConnectionFactory = ...
val template = new JmsTemplate(connectionFactory)
template.send("queue") {
session: Session => session.createTextMessage("Hello World")
}
12.
SPRING-SCALA SPECIALS
XML CONFIGURATION
class Person(val firstName: String, val lastName: String) { ... }
<beans>
<bean id="firstName" class="java.lang.String">
<constructor-arg value="John"/>
</bean>
<bean id="lastName" class="java.lang.String">
<constructor-arg value="Doe"/>
</bean>
</beans>
class PersonConfiguration extends FunctionalConfiguration {
importXml("classpath:/names.xml")
val john = bean() {
new Person(getBean("firstName"), getBean("lastName"))
}
}
13.
SPRING-SCALA SPECIALS
CONFIGURATION COMPOSITION
You can use also traits for composition
abstract class PersonConfiguration extends FunctionalConfiguration {
val firstName: String
val lastName: String
bean() {
new Person(firstName, lastName)
}
}
class JohnDoeConfiguration extends PersonConfiguration {
val firstName = singleton() { "John" }
val lastName = singleton() { "Doe" }
}
14.
SPRING-SCALA SPECIALS
PROFILES, INIT AND DESTROY
class DataSourceConfiguration extends FunctionalConfiguration {
profile("dev") {
bean("dataSource") {
new BasicDataSource()
} init {
// Set up properties
} destroy { _.close() }
}
profile("prod") {
bean("dataSource") {
val dataSource = new OracleDataSource()
// Set up properties
dataSource
}
}
}
15.
CDI
THE ONLY SOLUTION I DIDN'T TRY BECAUSE OF ITS LIMITS
1. Java EE Standard (JSR-299), part of every JEE6 compiliant
container (±)
2. Relies heavily on annotations (-)
3. Only Singleton and Dependent scoped beans are injected
as direct dependecies (-)
4. Proxy and ThreadLocal magic behind, doesn't work well
with actors (-)
5. Mulitple implementations (±)
6. Various testing possibilities (±)
16.
CDI
LIMITS
Various scopes: singleton, prototype (dependent), session,
request, application
Only singleton and dependent are injected directly
Other scopes use proxies and thread locals
Restriction on proxied classes:
1. Default constructor => no immutablity
2. No final classes and methods => Scala uses some in
beckground implicitly
17.
GOOGLE GUICE
1. Few annotations needed (±)
2. Only DI nothing else, leaner, easier (+)
3. Wiring in code, no external configuration file (+)
4. Immutability via contructor injection (+)
5. Scala DSL for bindings (+)
6. Easy testing (+)
19.
GOOGLE GUICE SPECIALS
INJECTION AND TESTING
Anytime you can inject members using any arbitrary module.
Relevant for setter injection.
It is possible to override production module with another
module in tests. Use ` instead of '
val runner = ...
injector.injectMembers(runner)
val m = Modules 'override' new ProductionModule 'with' new TestModule
val injector = Guice createInjector m
20.
SUBCUT
1. No annotations (+)
2. Wiring in code, no external configuration file (+)
3. Pure Scala library (+)
4. Intrusive code (-)
5. Actually service locator pattern and not DI (-)
6. Limited testing (-)
21.
SUBCUT
BINDING OPTIONS
Example directly from SubCut website
object SomeConfigurationModule extends NewBindingModule (module => {
import module._ // optional but convenient - allows use of bind inst
ead of module.bind
bind [X] toSingle Y
bind [Z] toProvider { codeToGetInstanceOfZ() }
bind [A] toProvider { implicit module => new AnotherInjectedClass(par
am1, param2) } // module singleton
bind [B] to newInstanceOf [Fred] // create a new instance of Fred
every time - Fred require injection
bind [C] to moduleInstanceOf [Jane] // create a module scoped singlet
on Jane that will be used
bind [Int] idBy PoolSize to 3 // bind an Int identified by Pool
Size to constant 3
bind [String] idBy ServerURL to "http://escalatesoft.com"
})
22.
SUBCUT
LESS INTRUSIVE OPTION
Normal definition of component
Using AutoInjectable
Sad news, it needs compiler plugin (macros in next versions)
class SomeServiceOrClass(param1: String, param2: Int)
(implicit val bindingModule: BindingModule)
extends SomeTrait with Injectable {
...
}
class SomeServiceOrClass(param1: String, param2: Int)
extends SomeTrait with AutoInjectable {
...
}
23.
CAKE PATTERN
1. Dependencies are checked in compile time, statically
typed, immutable (+)
2. No library needed, uses only Scala language features (+)
3. Wiring in code, no external configuration file (+)
4. Uses advanced features of Scala, not easy to grasp (-)
5. Easy testing (+)
24.
CAKE PATTERN
EXPLANATION
Definition of module/component
// Module or Component
trait Translation {
// Services it provides
def translator: Translator
// Service interface with multiple implementations
trait Translator {
def translate(what: String): String
}
}
25.
CAKE PATTERN
EXPLANATION
Implementation of component, relies on inharitance
trait FrenchTranslation extends Translation {
// Singleton instance
override val translator = new FrenchTranslator
// Implementation of service
class FrenchTranslator extends Translator {
def translate(what: String): String = {...}
}
}
26.
CAKE PATTERN
EXPLANATION
Expressing dependency and usage, relies on self-type
annotations
trait Translate extends Controller {
this: Translation => // Dependency
def greet(name: String) = Action {
// Usage of service
Ok(views.html.greet(translator.translate(s"Hello $name!")))
}
}
27.
CAKE PATTERN
EXPLANATION
Binding, relies on mixins of traits
object Translate extends Translate with FrenchTranslation
28.
RECOMMENDATIONS
WHEN TO USE (JAVA FRAMEWORKS)
Spring (definitely w/ Spring-Scala)
1. When you need more than DI
2. When you need to intergate with Java code
3. When you know Spring well
CDI
1. Only in JEE compiliant container, when your code depends
on container services
Guice
1. When you want to do only DI and do it well
2. When you need to integrate with Java code
29.
RECOMMENDATIONS
WHEN TO USE (SCALA DI)
SubCut
1. When you want to be hipster and rant with a new library
2. When you want pure Scala solution
Cake
1. Wnen you need additional type safety
2. When you want pure Scala solution
3. When you want very cohesive components/modules
30.
RECOMMENDATIONS
USAGE EXAMPLES
Java/Scala mixed project => Spring or Guice
Scala standalone project => Guice or Cake
Play! project => Guice or Cake
Domain or algorithm => Cake
31.
RECOMMENDATIONS
VERY SUBJECTIVE RANKING
Category Spring CDI Guice SubCut Cake
Idiomatic ** * ** *** ***
Simple testing *** * *** * ***
Good fit with Play! *** * *** ** ***
No steep learning curve ** ** *** *** *
Java integration *** *** *** n/a n/a
Be the first to comment