A Scala Spring Framework dependency injection example

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.

Back to top

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

Back to top

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.

Back to top

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.

Back to top

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.

Back to top

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
Back to top

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
Back to top

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.

Back to top

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.

Back to top

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.

Back to top

Spring and Scala work great. We're using them together in quite a few projects.

Please note, however, that how you're using Spring was normal for 10 years ago. There's seldom any need for XML any more. (Look at Spring Boot, for example.) Secondly, I don't use setter injection in either Java or Scala: Use @Autowired on constructors, which works fine in Scala. That way you can have immutability and there's nothing unidiomatic about your Scala for use with Spring.

Regards
Rod

Add new comment

The content of this field is kept private and will not be shown publicly.

Anonymous format

  • Allowed HTML tags: <em> <strong> <cite> <code> <ul type> <ol start type> <li> <pre>
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.