Grails 3.1.2 and Spring Security Core won't save User

186 views
Skip to first unread message

Chris Malan

unread,
Mar 3, 2016, 8:24:18 AM3/3/16
to Grails Dev Discuss
On trying to save a user (called SecUser in the code) the following happens:
object references an unsaved transient instance - save the transient instance before flushing: security.SecUser. Stacktrace follows:
java.lang.reflect.InvocationTargetException: null
at grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter.doFilter(GrailsAnonymousAuthenticationFilter.groovy:53) ~[spring-security-core-3.0.3.jar:na]
at grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter.doFilter(MutableLogoutFilter.groovy:62) ~[spring-security-core-3.0.3.jar:na] etc. and
Caused by: org.springframework.beans.InvalidPropertyException: Invalid property 'authorities' of bean class [security.SecUser]: Getter for property 'authorities' threw exception; nested exception is java.lang.reflect.InvocationTargetException
at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:96) ~[grails-core-3.1.2.jar:3.1.2]
 
This is caused by the middle line of this method in the User domain class generated by s2-quickstart:
 Set<SecRole> getAuthorities() {
SecUserSecRole.findAllBySecUser(this)*.secRole
}

Apparently the User is not persisted to the database at this stage.  The save is save(flush: true).

This method has been in the User domain class for some time and didn't create problems in earlier versions.  I thought maybe Hibernate is responsible and used Hibernate5 as well.  No change. 

It's a brand new project with only Spring Security Core added as a dependency and controllers and gsp pages generated.  If one tries to do it in Bootstrap.groovy the result is the same.

How can one get past this?

Thanks.

Chris

Chris Malan

unread,
Mar 4, 2016, 12:05:13 AM3/4/16
to Grails Dev Discuss
Some progress.  Changing getAuthorities to the following:

Set<SecRole> getAuthorities() {
if(!this.id){
println "The username: ${this.username}"
println "The password: ${this.password}"
}
return [] as Set
//SecUserSecRole.findAllBySecUser(this)*.secRole
}
sees to it that the user gets saved.  The printout is the following:
The username: jackson
The password: password
The username: jackson
The password: password
The username: jackson
The password: password
The username: jackson
The password: password
The username: jackson
The password: $2a$10$VRakfS5Zp2LUyLqf3zNunuBdlnmrfjTshK1fVV8i3JcnfmdiFVxk.
The username: jackson
The password: $2a$10$VRakfS5Zp2LUyLqf3zNunuBdlnmrfjTshK1fVV8i3JcnfmdiFVxk.
That's how many times this method gets called with one save() and one show().

Trying to save(flush: true) 'this' if it has no id (transient) results in a loop.  Top (Linux command) shows it uses two cores of the CPU fully and one partially.  Memory usage for just this process is about 25% at the time.   

So, this is far from a solution, but a pointer indicating the cause of the problem.  I'm very sure everyone will run into this using Grails 3.1.2 and Spring Security Core.  Give it time.  Grails 3.1.2 has been out only days.  This has to be resolved.

Hopefully the solution is easy.  

Chris

drog...@gmail.com

unread,
Mar 4, 2016, 1:07:51 AM3/4/16
to Grails Dev Discuss

It’s a bug on 3.1.2. You can migrate to 3.1.3 or make this method `transient` or add `static transients = [‘authorities’]` to fix it.

See https://github.com/grails/grails-core/issues/9749 for details

Chris Malan

unread,
Mar 4, 2016, 1:49:25 AM3/4/16
to Grails Dev Discuss
Changing getAuthorities() to the following also works:
Set<SecRole> getAuthorities() {
if(this.id){
return SecUserSecRole.findAllBySecUser(this)*.secRole
}
else{
return [] as Set
}
}
Reply all
Reply to author
Forward
0 new messages