I am in the process of learning Spring Integration and using it to implement a basic email service in Grails. What I want to be able to do is call my email service but only have the email be sent if the transaction trying to send the email is successful. Although this is being done in Grails, it really shouldn't be different from a regular Spring app except for using the BeanBuilder DSL instead of the XML configuration.
Anyway, here is my configuration for the channel:
beans = {
xmlns integration:'http://www.springframework.org/schema/integration'
integration.channel(id: 'email')
}
Here is my service:
class MailService {
@ServiceActivator(inputChannel = "email")
MailMessage sendMail(Closure callable) {
//sending mail code
}
}
Now what I expect to happen is that when I inject this MailService into another service and call send mail, that will place a message on the email channel, which will only get published if my transaction completes. What leads me to believe this is the section on UserProcess here: http://docs.spring.io/spring-integration/reference/html/transactions.html, which states that a user started process will have all the transactional properties that Spring provides.
I am attempting to test this with an integration test:
void "test transactionality"() {
when:
assert DomainObject.all.size() == 0
DomainObject.withNewTransaction { status ->
DomainObject object = buildAndSaveNewObject()
objectNotificationService.sendEmails(object) //This service injects emailService and calls sendMail
throw new Exception()
}
then:
thrown(Exception) // This is true
DomainObject.all.size() == 0 // This is true
greenMail.receivedMessages.length == 0 // This fails
}
What this does is create and save an object and send emails all within the same transaction. I then throw an exception to cause that transaction to fail. As expected, none of my domain objects are persisted. However, I still receive emails.
I am quite new to Spring Integration and Spring in general, so it's possible I'm misunderstanding how this is all supposed to work, but I would expect the sendMail message to never be placed on the email channel.