Search code examples
springsecuritygrailsgroovygrails-orm

Adding UserProfile to User with Grails and Spring Security. Parameter #7 is not set


I'm having trouble extending the Spring Security User class to include a profile class. The profile class is simple and just holds a list of Strings. When I go to run the application, I'm thrown the following error, Parameter 7 is not set:

| Error 2014-03-20 22:33:26,751 [localhost-startStop-1] ERROR util.JDBCExceptionReporter  - Parameter "#7" is not set; SQL statement:
insert into user (id, version, account_expired, account_locked, enabled, "password", password_expired, user_profile_id, username) values (null, ?, ?, ?, ?, ?, ?, ?, ?) [90012-173]
| Error 2014-03-20 22:33:26,815 [localhost-startStop-1] ERROR context.GrailsContextLoader  - Error initializing the application: Hibernate operation: could not insert: [ibm_cd_dashboard.User]; uncategorized SQLException for SQL [insert into user (id, version, account_expired, account_locked, enabled, "password", password_expired, user_profile_id, username) values (null, ?, ?, ?, ?, ?, ?, ?, ?)]; SQL state [90012]; error code [90012]; Parameter "#7" is not set; SQL statement:
insert into user (id, version, account_expired, account_locked, enabled, "password", password_expired, user_profile_id, username) values (null, ?, ?, ?, ?, ?, ?, ?, ?) [90012-173]; nested exception is org.h2.jdbc.JdbcSQLException: Parameter "#7" is not set; SQL statement:
insert into user (id, version, account_expired, account_locked, enabled, "password", password_expired, user_profile_id, username) values (null, ?, ?, ?, ?, ?, ?, ?, ?) [90012-173]
Message: Hibernate operation: could not insert: [ibm_cd_dashboard.User]; uncategorized SQLException for SQL [insert into user (id, version, account_expired, account_locked, enabled, "password", password_expired, user_profile_id, username) values (null, ?, ?, ?, ?, ?, ?, ?, ?)]; SQL state [90012]; error code [90012]; Parameter "#7" is not set; SQL statement:
insert into user (id, version, account_expired, account_locked, enabled, "password", password_expired, user_profile_id, username) values (null, ?, ?, ?, ?, ?, ?, ?, ?) [90012-173]; nested exception is org.h2.jdbc.JdbcSQLException: Parameter "#7" is not set; SQL statement:
insert into user (id, version, account_expired, account_locked, enabled, "password", password_expired, user_profile_id, username) values (null, ?, ?, ?, ?, ?, ?, ?, ?) [90012-173]
    Line | Method
->>   28 | ensureSave                       in BootStrap
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|     14 | doCall                           in BootStrap$_closure1
|    308 | evaluateEnvironmentSpecificBlock in grails.util.Environment
|    301 | executeForEnvironment            in     ''
|    277 | executeForCurrentEnvironment . . in     ''
|    262 | run                              in java.util.concurrent.FutureTask
|   1145 | runWorker . . . . . . . . . . .  in java.util.concurrent.ThreadPoolExecutor
|    615 | run                              in java.util.concurrent.ThreadPoolExecutor$Worker
^    744 | run . . . . . . . . . . . . . .  in java.lang.Thread

Caused by JdbcSQLException: Parameter "#7" is not set; SQL statement:
insert into user (id, version, account_expired, account_locked, enabled, "password", password_expired, user_profile_id, username) values (null, ?, ?, ?, ?, ?, ?, ?, ?) [90012-173]
->>  331 | getJdbcSQLException              in org.h2.message.DbException
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    171 | get                              in     ''
|    148 | get . . . . . . . . . . . . . .  in     ''
|     80 | checkSet                         in org.h2.expression.Parameter
|    163 | checkParameters . . . . . . . .  in org.h2.command.Prepared
|     78 | update                           in org.h2.command.CommandContainer
|    235 | executeUpdate . . . . . . . . .  in org.h2.command.Command
|    154 | executeUpdateInternal            in org.h2.jdbc.JdbcPreparedStatement
|    140 | executeUpdate . . . . . . . . .  in     ''
|     28 | ensureSave                       in BootStrap
|     14 | doCall . . . . . . . . . . . . . in BootStrap$_closure1
|    308 | evaluateEnvironmentSpecificBlock in grails.util.Environment
|    301 | executeForEnvironment . . . . .  in     ''
|    277 | executeForCurrentEnvironment     in     ''
|    262 | run . . . . . . . . . . . . . .  in java.util.concurrent.FutureTask
|   1145 | runWorker                        in java.util.concurrent.ThreadPoolExecutor
|    615 | run . . . . . . . . . . . . . .  in java.util.concurrent.ThreadPoolExecutor$Worker
^    744 | run                              in java.lang.Thread
| Error 2014-03-20 22:33:27,071 [Thread-13] ERROR hbm2ddl.SchemaExport  - schema export unsuccessful
Message: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-173]
    Line | Method
->>  331 | getJdbcSQLException in org.h2.message.DbException
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    171 | get                 in     ''
|    148 | get . . . . . . . . in     ''
|    137 | get                 in     ''
|   1413 | checkClosed . . . . in org.h2.jdbc.JdbcConnection
|   1388 | checkClosed         in     ''
|    428 | getAutoCommit . . . in     ''
^    744 | run                 in java.lang.Thread

User Profile:

class UserProfile {

    static hasOne = [user:User]
    static belongsTo = User

    static constraints = {
    }

    static mapping = {
    }

    List<String> projects
}

User is basically the standard spring class:

class User {

transient springSecurityService
static hasOne = [userProfile:UserProfile]


String username
String password
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired

static transients = ['springSecurityService']

static constraints = {
    username blank: false, unique: true
    password blank: false
    userProfile unique:true, nullable: true

}

static mapping = {
    password column: '`password`'
}

Set<Role> getAuthorities() {
    UserRole.findAllByUser(this).collect { it.role } as Set
}

def beforeInsert() {
    encodePassword()
}

def beforeUpdate() {
    if (isDirty('password')) {
        encodePassword()
    }
}

protected void encodePassword() {
    password = springSecurityService.encodePassword(password)
}

}

Bootstrap:

def init = { servletContext ->
    def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
    def userRole = new Role(authority: 'ROLE_USER').save(flush: true)

    def testUser = new User(username: 'me', password: 'password', userProfile: null)
    ensureSave(testUser)
    testUser.userProfile = new UserProfile(projects: null, version: null, user: testUser)
    ensureSave(testUser)

    UserRole.create testUser, adminRole, true

    assert User.count() == 1
    assert Role.count() == 2
    assert UserRole.count() == 1
}

def ensureSave(domainObject) {
  if(!domainObject.save(flush:true)) {
    throw new Exception("not saved successfully: $domainObject");
  }
  domainObject
}

Removing the associations between the User and UserProfile class allows the application to run normally. Playing around wiht the code I've also gotten "Parameter #4 is not set". Any help appreciated.


Solution

  • I was able to successfully resolve this issue using the help of the comments posted by other users. Here is the updated code.

    Bootstrap class BootStrap {

    def init = { servletContext ->
        def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
        def userRole = new Role(authority: 'ROLE_USER').save(flush: true)
    
        def testUser = new User(username: 'me', password: 'password', userProfile: new UserProfile(projects: null, version: null))
        testUser.save(flush: true, failOnError: true)
        UserRole.create testUser, adminRole, true
    
        assert User.count() == 1
        assert Role.count() == 2
        assert UserRole.count() == 1
    }
    def destroy = {
    }
    }
    

    UserProfile

    class UserProfile {
    
    static belongsTo = [user:User]
    
    static constraints = {
    }
    
    static mapping = {
    
    }
    
    List<String> projects
    }
    

    User Class:

    class User {
    
    transient springSecurityService
    static hasOne = [userProfile:UserProfile]
    
    
    String username
    String password
    boolean enabled = true
    boolean accountExpired
    boolean accountLocked
    boolean passwordExpired
    
    static transients = ['springSecurityService']
    
    static constraints = {
        username blank: false, unique: true
        password blank: false
        userProfile unique:true, nullable: true
    
    }
    
    static mapping = {
        password column: '`password`'
    }
    
    Set<Role> getAuthorities() {
        UserRole.findAllByUser(this).collect { it.role } as Set
    }
    
    def beforeInsert() {
        encodePassword()
    }
    
    def beforeUpdate() {
        if (isDirty('password')) {
            encodePassword()
        }
    }
    
    protected void encodePassword() {
        password = springSecurityService.encodePassword(password)
    }
    }