How to use Spring Autowired (or manually wired) in Scala object?

axtavt's solution did not work for me, but combining different suggestions from the other answers I think this is the most elegant solution:

object User {
    @Autowired val repo: UserRepository = null

    def instance() = this
}

@Configuration
class CompanionsConfig {
    @Bean def UserCompanion = User.instance
}

<context:component-scan base-package="your-package" />

A few notes:

  • Using @Configuration ensures that your companion objects are eagerly autowired
  • Using @Bean def avoids having to deal with noisy names Scala gives to the class that implements the companion object
  • val works just fine, as mentioned by Dave Griffith
  • there is no need for Scala's @BeanProperty, Spring understands Scala properties out of the box (I'm using 3.2.2)

What I do is use AutowiredAnnotationBeanPostProcessor to inject the object at construction time.

For example:

object UserRest extends RestHelper {
    @Autowired
    var userRepository: UserRepository = _

    AppConfig.inject(this)
}

@Configuration
class AppConfig extends ApplicationListener[ContextRefreshedEvent] {

  // Set the autowiredAnnotationBeanPostProcessor when the Spring context is initialized
  def onApplicationEvent(event: ContextRefreshedEvent) {
    autowiredAnnotationBeanPostProcessor =
      event.applicationContext.
        getBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME).
          asInstanceOf[AutowiredAnnotationBeanPostProcessor]
  }
}

object AppConfig {
  var autowiredAnnotationBeanPostProcessor: AutowiredAnnotationBeanPostProcessor = null

  def inject(obj: AnyRef) {
    autowiredAnnotationBeanPostProcessor.processInjection(obj);
  }
}

Now you can use AppConfig.inject() to inject any object whose lifecycle is not controlled by Spring. For example, JPA Entities, etc.


Basically, you have two problems:

  • Property should be mutable, i.e. var rather than val

  • All methods of Scala object are static, whereas Spring expects instance methods. Actually Scala creates a class with instance methods named UserRest$ behind the scene, and you need to make its singleton instance UserRest$.MODULE$ available to Spring.
    Spring can apply configuration to preexisting singleton instances, but they should be returned by a method, whereas UserRest$.MODULE$ is a field. Thus, you need to create a method to return it.

So, something like this should work:

object UserRest extends RestHelper {
   @BeanProperty
   var userRepository: UserRepository = null;

   def getInstance() = this
   ...
}

.

<bean id="userRest" 
    class="com.abc.rest.UserRest" 
    factory-method = "getInstance">
    <property name="userRepository" ref="userRepository"/>
</bean>

You can replace <property> with @Autowired, but cannot replace manual bean declaration with @Service due to problems with singleton instance described above.

See also:

  • What is the Java equivalent of a Scala object?
  • 3.3.2.2 Instantiation with a static factory method

All that's actually necessary is that you define your object as a class, rather than an object. That way Spring will instantiate it.

 @Service
    object UserRest extends RestHelper {
        @Autowired
        @BeanProperty
        val userRepository: UserRepository = null;

        .....
    }
<beans>
         .....
         <bean id="userRest" class="com.abc.rest.UserRest" >
              <!--- this is my attempt to manually wire it --->
              <property name="userRepository" ref="userRepository"/>
         </bean>
    </beans>

Changing the "val" to "var" is unnecessary (Spring uses reflection, which ignores immutability). I'm pretty sure that that @BeanProperty is also unnecessary (Spring will assign to the underlying field, reflectively).