开发者

Use Spring @Transactional in Scala

We have a mixed Java and Scala project, which uses Spring transaction management. We are using the Spring aspects to weave the files with @Transactional annotated methods.

The problem is, that the Scala classes aren't woven with the Spring开发者_运维技巧 transaction aspects. How can I configure Spring to regard the transaction in Scala?


Spring needs your transaction boundary to begin with Spring-managed beans, so this precludes @Transactional Scala classes.

It sounds like the simple solution is to make service facades which are @Transactional Java classes instantiated as Spring beans. These can delegate to your Scala service/core code.


A Scala-only solution is to use Eberhard Wolff's closure that creates a manual transaction. Usage:

transactional() {
// do stuff in transaction
}

https://github.com/ewolff/scala-spring/blob/master/src/main/scala/de/adesso/scalaspring/tx/TransactionManagement.scala

https://github.com/ewolff/scala-spring/blob/master/src/main/scala/de/adesso/scalaspring/tx/TransactionAttributeWithRollbackRules.scala

Found here: http://www.slideshare.net/ewolff/scala-and-spring (slide 41)

License: Apache


There is nothing special about Spring's @Transactional support in Scala and you can use it without any Java code. Just make sure that you have "pure" traits for beans, which implementations would use @Transactional annotation. You should also declare a bean with PlatformTransactionManager type (if you are using .xml-based Spring configuration, you should use "transactionManager" for bean name, see EnableTransactionManagement's JavaDoc for details). Also, if you are using annotation-based configuration classes, be sure that these classes are placed in their own dedicated files, i.e. don't place any other classes (companion object is OK) in the same file. Here is simple working example:

SomeService.scala:

trait SomeService {
  def someMethod()
}

// it is safe to place impl in the same file, but still avoid doing it
class SomeServiceImpl extends SomeService {
  @Transactional
  def someMethod() {
    // method body will be executed in transactional context
  }
}

AppConfiguration.scala:

@Configuration
@EnableTransactionManagement
class AppConfiguration {
  @Bean
  def transactionManager(): PlatformTransactionManager = {
    // bean with PlatformTransactionManager type is required
  }

  @Bean
  def someService(): SomeService = {
    // someService bean will be proxied with transaction support
    new SomeServiceImpl
  }
}

// companion object is OK here
object AppConfiguration {
  // maybe some helper methods  
}

// but DO NOT place any other trait/class/object in this file, otherwise Spring will behave incorrectly!
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜