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!
精彩评论