Grails 2.2.0
I am trying to create a custom constraint to force user to have only one master email. Here is the simplified code causing the error:
User domain class
class User {
static hasMany = [emails: Email]
static constraints = {
}
}
Email domain class
class Email {
static belongsTo = [user: User]
String emailAddress
Boolean isMaster
static constraints = {
emailAddress unique: ['user']
isMaster validator: { val, obj ->
return !val || Email.findByUserAndIsMaster(obj.user, true) == null
}
}
}
Integration test
class EmailTests {
@Before
void setUp() {
}
@After
void tearDown() {
// Tear down logic here
}
@Test
void testSomething() {
def john = (new User(login: 'johnDoe')).save(failOnError: true, flush: true)
assert (new Email(emailAddress: 'john@gmail.com', user: john, isMaster: true)).save(failOnError: true)
}
}
Running "grails test-app -integration" will cause:
| Failure: testSomething(webapp.EmailTests)
| org.hibernate.AssertionFailure: null id in webapp.Email entry (don't flush the Session after an exception occurs) at org.grails.datastore.gorm.GormStaticApi$_methodMissing_closure2.doCall(GormStaticApi.groovy:105) at webapp.Email$__clinit__closure1_closure2.doCall(Email.groovy:13) at org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener.onApplicationEvent(AbstractPersistenceEventListener.java:46) at webapp.EmailTests.testSomething(EmailTests.groovy:21)
If I change the unique constraint to be after the custom constraint the problem will not happen. What is happening here? I want to understand how is the order of the constraints of any relevance here?
To be clear this does NOT cause the problem:
static constraints = {
isMaster validator: { val, obj ->
return !val || Email.findByUserAndIsMaster(obj.user, true) == null
}
emailAddress unique: ['user']
}