Table of Contents
In my Java days I used the Spring Framework (Spring) all the time for different things, primarily involving dependency injection (DI) and pretty much anything related to a database. I became curious how Spring would work with Scala, so I created a small Scala/Spring dependency injection example project, which I'm sharing here.
The short answer is that Scala worked just fine with Spring, but it also showed me that I still have plenty to learn about inheritance in Scala.
My Spring applicationContext.xml file
I copied a Spring applicationContext.xml file from another project, then whittled it down to these bare essentials:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="dog" class="scalaspring.Dog"> <constructor-arg value="Fido" /> </bean> <bean id="cat" class="scalaspring.Cat"> <constructor-arg value="Felix" /> </bean> </beans>
You can't tell it from there, but both the Dog
and Cat
classes extend an Animal
class that I created. (More on that in a few moments.)
My Scala object with a main method
Next, I created a simple Scala object with a main method to test everything:
package scalaspring import org.springframework.context.support.ClassPathXmlApplicationContext object ScalaSpringExample { def main(args: Array[String]) { // open/read the application context file val ctx = new ClassPathXmlApplicationContext("applicationContext.xml") // instantiate our dog and cat objects from the application context val dog = ctx.getBean("dog").asInstanceOf[Animal] val cat = ctx.getBean("cat").asInstanceOf[Animal] // let them speak dog.speak cat.speak } }
As you can see from the code, I loaded the applicationContext.xml file, created my dog
and cat
instances by getting their bean definitions from the application context, then executed their speak methods.
One note here: Using the Scala asInstanceOf method is not considered "good practice", but I think it's very concise, particularly for a simple example like this.
My Spring-injected Scala classes
I defined my Dog
and Cat
classes, as well as a parent abstract class named Animal
, in a file named Animals.scala:
package scalaspring abstract class Animal(name: String) { def speak:Unit } class Dog(name: String) extends Animal(name) { override def speak { println(name + " says Woof") } } class Cat(name: String) extends Animal(name) { override def speak { println(name + " says Meow") } }
As you can see, all three classes have a speak method, which is implemented differently in the Dog
and Cat
classes. I've also defined the classes using a one-argument constructor, and if you look back at the application context file, you'll see that I pass in the names "Fido" and "Felix" in my Spring bean definitions.
Note that I didn't have to make things this complicated, but I wanted to make sure that the Spring Framework was really working with Scala as expected.
My log4j.properties file
Spring wouldn't run without a logger configuration, so I copied this Log4j properties file from another project, then whittled it down to these lines:
log4j.rootLogger=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p | %d{HH:mm:ss} | %m | %F | %L%n log4j.logger.org.springframework=INFO log4j.logger.org.springframework.context.support.ClassPathXmlApplicationContext=INFO
I don't need all those lines, but I haven't used Log4j in a while, and didn't feel like fooling around with it, so I left it as is.
Jar files needed
I needed these jar files to get everything to run:
commons-logging-1.1.1.jar log4j-1.2.14.jar spring-2.5.5.jar
My project directory structure
I used the Scala sbt tool to compile and run my project, and therefore I created my directory structure like this:
./build.sbt ./lib ./lib/commons-logging-1.1.1.jar ./lib/log4j-1.2.14.jar ./lib/spring-2.5.5.jar ./project ./src ./src/main ./src/main/config ./src/main/java ./src/main/resources ./src/main/resources/applicationContext.xml ./src/main/resources/log4j.properties ./src/main/scala ./src/main/scala/scalaspring ./src/main/scala/scalaspring/Animals.scala ./src/main/scala/scalaspring/ScalaSpringTest.scala ./src/test ./src/test/java ./src/test/resources ./src/test/scala ./target
Running my Scala / Spring Framework example
Finally, when I ran my Scala / Spring Framework dependency injection example, I got this very exciting output:
Fido says Woof Felix says Meow
I actually got more output than that from both sbt and Log4j, but that was the important part.
As you can see, Scala and the Spring Framework seem to play well together. These lines of code from my Scala main method:
val ctx = new ClassPathXmlApplicationContext("applicationContext.xml") val dog = ctx.getBean("dog").asInstanceOf[Animal] val cat = ctx.getBean("cat").asInstanceOf[Animal]
are very similar to the lines of code I used in a similar Java Spring Framework dependency injection example, and the Spring applicationContext.xml file and the Log4j configuration file were identical to what they'd look like in a regular Java application.
My Scala inheritance problems
One thing I learned in tackling this project is that I need to learn more about Scala inheritance, in particular, overriding constructor methods that accept fields/parameters. If you look back at my applicationContext.xml file, you'll see that I passed the names "Fido" and "Felix" in using the Spring bean "constructor-arg" parameter. I choose this route because I got tired of trying to get my class "setter" methods to work.
What I mean by that is that I wanted to define my Spring beans like this:
<bean id="dog" class="scalaspring.Dog"> <property name="name" value="Fido"/> </bean>
but because I haven't worked with Scala inheritance much yet, I didn't know the proper way to define the "name" field in my Animal, Dog, and Cat classes for this "setter" syntax to work. I'll update this article after I take the time to learn that.
Scala Spring Framework example - Summary
Other than that last caveat, I hope this Scala and Spring Framework dependency injection example have been helpful. As you have seen, working with the Spring Framework in Scala is very similar to working with it in Java.