Monday, July 8, 2013

How to shoot yourself in the foot with Scala traits and Spring

Suppose you have some class MyService configured as Spring bean:

@Component
class MyService extends MyBaseService {
  def myOperation() {
    ...
  }
}
Which is referenced somewhere in the project:

...
@Autowired
private var myService: MyService = _
...
So far this code works, and now you'd like to mix in some trait into your service to add common functionality:

@Component
class MyService extends MyBaseService with MyTrait {
  def myOperation() {
    ...
  }
}
And suddenly Spring can't find bean for autowiring. The problem is that if you use proxies for AOP functionality then Spring detects the only interface implemented by MyService - and it's MyTrait. Therefore there's no more MyService instance in application contect, there's only a proxy implementing MyTrait and forwarding calls of methods available in MyTrait to MyService instance. Without that trait Spring used subclassing to build proxy which worked find.