BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage Articles Scala & Spring: Combine the best of both worlds

Scala & Spring: Combine the best of both worlds

This item in japanese

Bookmarks

Introduction

Scala is a great programming language combining a concise and legible syntax with a seamless fusion of the object-oriented and functional programming paradigm that is fully compatible with Java. The latter makes it possible to combine Scala with Java APIs and frameworks that Java developers are familiar with. By doing so, the usage of existing Java frameworks can be improved and simplified. In addition to that, the threshold to learn Scala is also lowered because it can easily easily be integrated with the “well-known world of Java”.

In this article I will show how Spring, one of the most popular frameworks, can be leveraged by means of Scala. Spring not only offers effective programming paradigms such as Dependency Injection (DI) and Aspect Oriented Programming (AOP) but also provides lots of handy glue code to interface with popular frameworks such as Hibernate, Toplink and the like, as well as the JEE environment. Especially the latter grants Scala smooth access to the enterprise, which is the place its success will inevitably depend on.

In order to demonstrate how Scala compliments Spring this article is based on a simple sample application. This application uses a Scala, Spring and Hibernate/JPA stack with the following domain model:

The domain model resembles a mini version of a social networking application. Simply put, it lets persons be linked to other persons.

Step 1

Based on this domain model, first of all, this article shows how to implement a generic Data Access Object (DAO) and a concrete DAO for the Person entity in Scala making use of Hibernate/JPA. The result will be a PersonDao on which CRUD operations can be executed. For example:

val p1 = new Person(“Rod Johnson”) 
val p2 = dao.findByName(“Martin Odersky”) 
p1.link(p2)
personDao.save(p1)

Step 2

Then the article outlines what it takes to transform the Person entity into a “rich” domain object, which internally uses a NotificationService to perform additional logic when the link method is called. This service will be ‘magically’ injected on demand. At this point the following can be achieved:

val p1 = Person(“Martin Odersky”) //the omission of the ‘new’ keyword is intentional 
val p2 = dao.findByName(“Rod Johnson”) 
p1.link(p2) //magic happens here
personDao.save(p1) 

Step 3

Finally, the article explains how Spring can benefit from Scala’s advanced concept of ‘traits’. Traits can leverage the rich Person domain object to a full-fledged OO class, which can fulfill all possible responsibilities inclusive CRUD operations. Example:

Person(“Martin Odersky”).save 

Step 1: DAO with Scala, Spring and Hibernate/JPA

Requirements

Naturally, the DAO design should consist of a generic DAO and a concrete DAO for the Person entity. The generic DAO should contain features to perform the basic CRUD methods, like save, remove, findById and findAll. Because it is generic, it should deal with types rather than a concrete implementation of an entity. As a summary, it should adhere to the following interface definition:

trait GenericDao[T] {
      def findAll():List[T]
      def save(entity:T):T 
      def remove(entity:T):Unit
      def findById(id:Serializable):T
}

The concrete DAO for the Person entity class should add finder methods that are specific to the Person entity:

trait PersonDao extends GenericDao[Person] {
  def findByName(name:String):List[Person]
  //more finders here…
} 

In order to benefit from the productive features Scala offers, more implementation details have to be taken into account:

  • Considering collections: The DAO interfaces return Scala collection types (scala.List) rather than Java collections types (java.util.List), even though the underlying JPA implementation has no notion of Scala collections. Since Scala collections are considerably more powerful than Java collections it is very desirable for the caller of the DAO methods to have Scala collections returned. Therefore, we need to find a slick way to convert Java collections returned by JPA into Scala collections.
  • Considering callbacks: Most of Spring’s glue code to other frameworks like JPA, JMS etc. is based on the template pattern, such as JpaTemplate, JmsTemplate etc. Even though these templates hide the complexity of the underlying framework to some extent by means of convenience methods, it is unavoidable in many cases to access the underlying implementation classes such as EntityManager, JmsSession etc. directly. In that case Spring provides Callback classes, like the JpaCallback. The only parameter of the callback’s doIn…(..) method contains a reference to the desired implementation class, such as an EntityManager. The following example illustrates this programming model:
    jpaTemplate.execute(new JpaCallback() {
    	public Object doInJpa(EntityManager em) throws PersistenceException {
    	//… do something with the EntityManager
    	return null;
    }
    });

    Two things are worth mentioning when considering this code: First, the instantiation of an anonymous inner callback class requires a great amount of boilerplate code. Second, we have to live with the restriction that all parameters outside the scope of the anonymous JpaCallback class need to be final. When looking at the callback pattern from a Scala perspective what we actually see is a cumbersome implementation of a ‘function’. What we really want is direct access to that EntityManager, without the fuss of an anonymous inner callback class with its single doInJpa(…) method implementation. In other words what we want is a one-liner:
    jpaTemplate.execute((em:EntityManager) => em.createQuery(…)// etc. ); 

    The question is how this can be achieved in an elegant fashion.
  • Considering getters and setters: A class that uses a Spring bean needs to provide at least a setter method, which corresponds to the name of the particular bean. Again, these setters are framework induced boilerplate code. Wouldn’t it be nice if they could be avoided without the need to use Constructor injection everywhere?

Implementation

The Scala implementation of the generic and the person DAO, which provides an answer to all the nice-to-have features stated above, looks as follows:

object GenericJpaDaoSupport {
 
   implicit def jpaCallbackWrapper[T](func:(EntityManager) => T) = {
    new JpaCallback {
      def doInJpa(session:EntityManager ) = func(session).asInstanceOf[Object]}
    } 
}

import Scala.collection.jcl.Conversions._
class GenericJpaDaoSupport[T](val entityClass:Class[T]) extends JpaDaoSupport with GenericDao[T] {

      def findAll():List[T] = { 
            getJpaTemplate().find("from " + entityClass.getName).toList.asInstanceOf[List[T]]
      }

      def save(entity:T) :T = {
        getJpaTemplate().persist(entity)
        entity
      }

      def remove(entity:T) = {
        getJpaTemplate().remove(entity);        
      }

      def findById(id:Serializable):T = {
        getJpaTemplate().find(entityClass, id).asInstanceOf[T];
      }
}

class JpaPersonDao extends GenericJpaDaoSupport(classOf[Person]) with PersonDao {
     
        def findByName(name:String) = { getJpaTemplate().executeFind( (em:EntityManager) => {
            val query = em.createQuery("SELECT p FROM Person p WHERE p.name like :name");
            query.setParameter("name", "%" + name + "%");
            query.getResultList();
      }).asInstanceOf[List[Person]].toList
      }
}

Usage:

class PersonDaoTestCase extends AbstractTransactionalDataSourceSpringContextTests {
    @BeanProperty var personDao:PersonDao = null
    
    override def getConfigLocations() = Array("ctx-jpa.xml", "ctx-datasource.xml")
 
    def testSavePerson {
        expect(0)(personDao.findAll().size)
        personDao.save(new Person("Rod Johnson"))
        val persons = personDao.findAll()
        expect(1)( persons size)
        assert(persons.exists(_.name ==”Rod Johnson”))
    }
}

The following is an explanation of how the desired features were implemented:

Considering collections

Scala 2.7.x provides a handy Java to Scala collections converter class, which relies on implicit conversions. In the example above we turn a Java list to a Scala list as follows:

  1. Import all methods of the Scala.collection.jcl.Conversions class:
    import Scala.collection.jcl.Conversions._ 
    This class provides implicit conversion methods that convert a Java collection into a corresponding Scala collection ‘wrapper’. With respect to java.util.List Scala creates a Scala.collection.jcl.BufferWrapper.
  2. Call the toList() method on the BufferWrapper in order to have an instance of Scala.List collection returned.

This usage scenario of the example above is shown in the following line of code:

def findAll() : List[T]  = { 
    getJpaTemplate().find("from " + entityClass.getName).toList.asInstanceOf[List[T]]
}

It might somehow be disturbing to always have to manually call ‘toList’ for a collection conversion. Fortunately, Scala 2.8, which is not final at the time of writing, is expected to solve this imperfection and transparently convert Java to Scala conversions, by means of the scala.collection.JavaConversions class.

Considering callbacks

Converting whatever Spring callback into a Scala function can easily be achieved with an implicit conversion as the one defined in the GenericJpaDaoSupport object:

implicit def jpaCallbackWrapper[T](func:(EntityManager) => T) = {
    new JpaCallback {
def doInJpa(session:EntityManager ) = func(session).asInstanceOf[Object]}
}

With this conversion in scope it is possible to call the execute method of the JpaTemplate with a function instead of an anonymous inner JPACallback class, allowing you to work with the object you are truly interested in directly:

jpaTemplate.execute((em:EntityManager) => em.createQuery(…)// etc. );

By doing so, another source of boilerplate code is eliminated.

Considering getters and setters

By default the Scala compiler does not generate getters and setters that comply with the JavaBeans convention. However, Scala provides an annotation that tells the compiler to generate JavaBeans-like getter and setter methods for instance variables for which this annotation is declared. The following example is taken from the PersonDaoTestCase further above:

import reflect._
@BeanProperty var personDao:PersonDao = _

The @BeanProperty annotation tells the Scala compiler to generate a setPersonDao(…) and a getPersonDao() method, which is needed by Spring for dependency injection. This simple construct saves another three to six lines of code for each instance variable, where a getter and/or a setter method is required.

Step 2: Rich Domain Objects with on-demand dependency injection

What we have achieved so far is a lean and mean implementation of a DAO pattern which allows the persistence of ‘state-only’ entities. The entity itself is not a smart object. Its responsibility is reduced to a state holder. For the advocates of Domain-Driven Design (DDD) such simple entities are insufficient to cope with the challenges faced in a complex domain. For an entity to be considered a rich domain object it should not only contain state but also be able to call business services. In order to achieve that there should be a mechanism to transparently inject services into domain objects, no matter where in the code they are instantiated.

Scala combined with Spring makes it quite easy to transparently inject services into all kind of objects instantiated at runtime. The mechanism for that, as will be explained further below, lays the technical foundation for DDD and allows entities to be promoted to rich domain objects in an elegant way.

Requirements

In order to illustrate on-demand dependency injection the sample application introduces a new requirement: When the link method of the Person entity is called, it not only should link the linkee but also call a NotificationService to notify the linker and linkee. This additional requirement is depicted in the code below:

class Person {
   @BeanProperty var notificationService:NotificationService = _
   def link(relation:Person) = {
     relations.add(relation)
     notificationService.nofity(PersonLinkageNotification(this, relation))
   }
   //other code omitted for readability
 }

Naturally, the NotificationService should be available immediately after a Person entity is instantiated or retrieved from the database without the need to manually set it.

The handle to Spring’s autowiring facilities

For this to happen we use the autowire features of Spring, which are made accessible in a self designed Java singleton class called RichDomainObjectFactory:

public class RichDomainObjectFactory implements BeanFactoryAware {

    private AutowireCapableBeanFactory factory = null;
        
    private static RichDomainObjectFactory singleton = new RichDomainObjectFactory();
    
    public static RichDomainObjectFactory autoWireFactory() {
        return singleton;
    }
    
    public void autowire(Object instance) {
        factory.autowireBeanProperties(instance) 
    }

    public void setBeanFactory(BeanFactory factory) throws BeansException {
        this.factory = (AutowireCapableBeanFactory) factory;
    }
    
}

By declaring this RichDomainObjectFactory as a Spring bean, the Spring Container makes sure that AutowireCapableBeanFactory is set when the container is initialized:

<bean class="org.jsi.di.spring.RichDomainObjectFactory" factory-method="autoWireFactory"/>

Instead of letting the Spring Container create its own instance of a RichDomainObjectFactory, the factory-method attribute is used in the bean definition, which forces Spring to use the reference returned by the autoWireFactory() method, which is the singleton itself. By doing so, the singleton instance of the RichDomainObjectFactory gets the AutowireCapableBeanFactory injected. Since a singleton can be accessed from everywhere in the same classloader scope, every class in that scope can make use of the RichDomainObjectFactory, which exposes the autowire features of Spring in a non-intrusive, loosely coupled manner. Needless to say that Scala code can access the RichDomainObjectFactory singleton as well and use its autowire function.

With this autowiring factory in place the next step is to define the hooks in the code/framework where it needs to be applied. Basically, two places can be identified:

  • In the ORM layer where entities are loaded from the database;
  • In custom code where new entities are created ‘manually’, meaning instantiated in application code.

Domain object autowiring in the ORM layer

Since the code example of this article uses JPA/Hibernate, the facilities these frameworks offer need to be used to hook in the RichDomainObjectFactory when entities are loaded. JPA/Hibernate provides an interceptor API by which loading of entities, among other things, can be intercepted and customized. In order to autowire freshly loaded entities, the following interceptor implementation needs to be provided:

class DependencyInjectionInterceptor extends EmptyInterceptor {
    override def onLoad(instance:Object, id:Serializable, propertieValues:Array[Object],propertyNames:Array[String], propertyTypes:Array[Type]) = {
      RichDomainObjectFactory.autoWireFactory.autowire(instance)
      false
   }
}

The only task this interceptor needs to perform is to pass the loaded entity to the autowire method of the RichDomainObjectFactory. Considering the sample application, the implementation of the onLoad method ensures that the NotificationService is injected into the Person entity each time it is retrieved from the database.

Additionally, this interceptor needs to be registered in the persistence context of JPA by means of the hibernate.ejb.interceptor property:

<persistence-unit name="ScalaSpringIntegration" transaction-type="RESOURCE_LOCAL">
     <provider>org.hibernate.ejb.HibernatePersistence</provider>
     <property name="hibernate.ejb.interceptor"                             value="org.jsi.domain.jpa.DependencyInjectionInterceptor" /> 
     </properties>
     <!-- more properties here-->
</persistence-unit>

This DependencyInjectionInterceptor is a powerful mechanism to equip rich entities with services configured in Spring each time they are loaded from the database. But how about entities which are instantiated in application code rather than a framework like JPA?

Autowiring ‘manually’ instantiated domain objects

The easiest but rather clumsy way to autowire entities that are instantiated in application code would be to autowire them explicitly by means of the RichDomainObjectFactory. Since this approach would tightly couple the RichDomainObjectFactory class to all areas in the code where entities are created it is not an advisable strategy. Fortunately, Scala provides the construct of ‘companion objects’ which are designated to take on factory responsibilities, where constructor logic such as autowiring neatly fits in.

In the sample application the Person companion object is implemented as follows in order to ‘automagically’ provide autowire functionality:

import org.jsi.di.spring.RichDomainObjectFactory._
object Person {
    def apply(name:String) = {
       autoWireFactory.autowire(new Person(name))
    }
}

The import statement imports all static methods of the RichDomainObjectFactory, namely the autoWireFactory() method, which offers a handle to the singleton instance of the RichDomainObjectFactory.

Another handy construct for Scala objects is the apply() method. The rules state that every object that has an apply method can be called with the .apply() omitted. Consequently, Scala automatically forwards all calls to Person() to Person.apply(), making the apply() method the ideal place for the autowiring code.

With this construct in place a simple call to Person(), without the keyword ‘new’, suffices to have a new entity returned, which has all necessary services injected ready to perform its ‘rich’ DDD job.

With the addition described in this section we are now able to use rich domain objects which are persistable and can make use of services whenever needed:

val p1 = Person(“Martin Odersky”)
val p2 = personDao.findUniqueByName(“Rod Johnsen”)
p1.link(p2) 
personDao.save(p1)

Before moving on to a more advanced usage it needs to be explained why the RichDomainObjectFactory is implemented in Java and not Scala. The reason for that has to do with the way Scala treats statics. Scala intentionally provides no static keyword, since statics collide with the composite OO/functional paradigm. The only static feature the Scala language offers is (companion) objects, whose counterparts in Java are singletons. The lack of static methods in Scala makes it impossible for Spring to get a handle to a factory object such as the RichDomainObjectFactory by means of the factory-method property as described further above. As a result, injecting Spring’s AutowireCapableBeanFactory directly into the Person companion object is not possible. Therefore, a Java implementation is used to provide access to Spring’s autowire facilities instead of a Scala one, which bridges the static gap thoroughly.

Step 3: Full-fledged Domain Object with Scala traits

So far so good. For the OO purists Scala has even more to offer. Using DAOs to persist entities slightly collides with pure OO principles. In the widely used traditional DAO/Repository pattern, DAOs have the responsibility to perform persistence operations, which are purely behavioral, and entities are supposed to hold state. Pure OO objects on the contrary should be able to combine behavior and state.

Using entities with services as shown in the previous section, equips them with behavioral responsibilities except for the persistence part. So why not give an entity all behavioral and state responsibilities, thus including the responsibility to perform persistence operations, as advocated by OO purists? Indeed, this is a matter of taste. However, using Java it is rather hard to make entities persist themselves in an elegant way. Such a design would have to depend heavily on inheritance, where persistence methods would be implemented in superclasses. Such an approach is rather clumsy and lacks flexibility. Java simply lacks the conceptual foundation to implement such logic in a well-designed way. Not so in Scala because Scala offers traits.

Simply put, traits are interfaces, which can contain an implementation. They are comparable to C++ multiple inheritance constructs but omit the nasty side-effect known as the diamond syndrome. By encapsulating DAO code in a trait all persistence methods provided by this DAO trait are automatically available to all implementing classes. This approach perfectly epitomizes the DRY (Don’t Repeat Yourself) principle, since the persistence logic is implemented once and mixed in domain classes as many times as needed.

For the sample application the DAO trait looks as follows:

trait JpaPersistable[T] extends JpaDaoSupport  {
   def getEntity:T;

   def findAll():List[T] = { 
        getJpaTemplate().find("from " + getEntityClass.getName).toList.asInstanceOf[List[T]]   
   }

   def save():T = {
       getJpaTemplate().persist(getEntity)
       getEntity
   }

   def remove() = {
       getJpaTemplate().remove(getEntity);        
   }
      
   def findById(id:Serializable):T = {
        getJpaTemplate().find(getEntityClass, id).asInstanceOf[T];
   }
   //…more code omitted for readability      
}

As a traditional DAO this trait extends Spring’s JpaDaoSupport. Instead of providing save, update and delete methods, which take the entity as argument, this trait defines an abstract method getEntity, which needs to be implemented by the domain object that wants persistence functionality. The JpaPersistable trait uses the getEntity method in its internal implementation to save, update or delete the particular entity, as depicted in the snippet below.

trait JpaPersistable[T] extends JpaDaoSupport  {
def getEntity:T
      
def remove() = {
   getJpaTemplate().remove(getEntity);        
}
//…more code omitted for readability
)

The domain object implementing this trait only has to provide the getEntity implementation, in which it simply returns a reference to itself:

class Person extends JpaPersistable[Person] with java.io.Serializable {

  def getEntity = this
  //…more code omitted for readability
}

That’s all. Consequently, all domain objects, which want persistable behavior, only need to implement the JpaPersistable trait and off they go. The result is a full-fledged domain object that combines state and behavior in the purest sense of OO programming:

Person(“Martin Odersky”).save 

No matter whether you are an advocate of pure OO principles or not, this example illustrates that Scala, and in particular the concept of traits, makes it remarkably easy to implement a pure OO design.

Conclusion

The examples in this article show that Scala and Spring neatly compliment one another. Scala’s conciseness and powerful paradigms, such as functions and traits combined with Spring’s dependency injection, AOP and integration with state of the art Java APIs offers a variety of interesting possibilities which can be implemented with more expressiveness and less code compared to Java.

Assuming a background in Spring and Java the learning curve is moderate since only a new language has to be learned, rather than a new language inclusive of a myriad of new APIs.

The impressive possibilities Scala and Spring offer make this combination an interesting candidate for the adoption of Scala in the enterprise. All in all it can be said that switching to a significantly more powerful programming paradigm comes at a low price.

About the Author

Urs Peter is a Senior Consultant with Xebia, specialized in enterprise Java and Agile software development. He has 9 years of experience in the IT industry. In his IT career he has fulfilled many roles ranging from developer, software architect, teamlead and Scrum Master. Currently he is working in the role of Scrum Master for the next generation information system of the Dutch Railways, which is partly implemented in Scala. He is an active member of Xebia’s Scala evangelists and the Dutch Scala usergroup.

Sources

The complete source code can be downloaded at http://github.com/upeter/Scala-Spring-Integration using git: git clone git://github.com/upeter/Scala-Spring-Integration.git and built with maven.

 

Rate this Article

Adoption
Style

BT