Grails:在服务器重新启动时初始化spring安全性时出错

Grails:在服务器重新启动时初始化spring安全性时出错,grails,spring-security,Grails,Spring Security,我在生产服务器上有一种非常奇怪的行为 当我第一次启动服务器时,没有问题,但是当我想停止并重新启动它时,我得到以下错误: Configuring Spring Security Core ... ... finished configuring Spring Security Core 2013-10-31 12:03:08,156 [localhost-startStop-1] ERROR context.GrailsContextLoader - Error initializing th

我在生产服务器上有一种非常奇怪的行为

当我第一次启动服务器时,没有问题,但是当我想停止并重新启动它时,我得到以下错误:

Configuring Spring Security Core ...
... finished configuring Spring Security Core

2013-10-31 12:03:08,156 [localhost-startStop-1] ERROR context.GrailsContextLoader  - Error initializing the application: null
java.lang.NullPointerException
        at com.aftmevent.security.UserRole.create(UserRole.groovy:32)
        at BootStrap$_closure1.doCall(BootStrap.groovy:16)
        at grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:308)
        at grails.util.Environment.executeForEnvironment(Environment.java:301)
        at grails.util.Environment.executeForCurrentEnvironment(Environment.java:277)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:724)
2013-10-31 12:03:08,156 [localhost-startStop-1] ERROR context.GrailsContextLoader  - Error initializing Grails: null
java.lang.NullPointerException
        at com.aftmevent.security.UserRole.create(UserRole.groovy:32)
        at BootStrap$_closure1.doCall(BootStrap.groovy:16)
        at grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:308)
        at grails.util.Environment.executeForEnvironment(Environment.java:301)
        at grails.util.Environment.executeForCurrentEnvironment(Environment.java:277)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:724)
oct. 31, 2013 12:03:08 PM org.apache.catalina.core.StandardContext startInternal
这是我的BootStrap.groovy:

class BootStrap {

    def springSecurityService
    def init = { servletContext ->
        def existingAdminRole = Role.findByAuthority('ROLE_ADMIN')
        def existingUserRole = null
        def existingAdminUser = null
        if (existingAdminRole) {
            existingUserRole = UserRole.findByRole(existingAdminRole)
        }
        if (existingUserRole) {
            existingAdminUser = existingUserRole.user
        }
        if (!existingAdminUser) {
            def adminRole = new Role(authority: 'ROLE_ADMIN')
            def adminUser = new User(username: 'admin', password: 'admin', enabled: true)
            if (adminRole.validate()) {
                adminRole.save(flush: true, failOnError: true)
            }
            if (adminUser.validate()) {
                adminUser.save(flush: true, failOnError: true)
            }
            UserRole userRole = UserRole.create(adminUser, adminRole, true)
            if (userRole.validate()) {
                userRole.save(flush: true, failOnError: true)
            }
        }
    }
    def destroy = {
    }
}
下面是我的User.groovy添加可为null的约束并没有解决问题:

User.groovy:

class User {

    transient springSecurityService

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

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

    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)
    }
}
UserRole.groovy:

class Role {

    String authority

    static mapping = {
        cache true
    }

    static constraints = {
        authority nullable: true, blank: false, unique: true
    }
}
class UserRole implements Serializable {

    User user
    Role role

    boolean equals(other) {
        if (!(other instanceof UserRole)) {
            return false
        }

        other.user?.id == user?.id &&
            other.role?.id == role?.id
    }

    int hashCode() {
        def builder = new HashCodeBuilder()
        if (user) builder.append(user.id)
        if (role) builder.append(role.id)
        builder.toHashCode()
    }

    static UserRole get(long userId, long roleId) {
        find 'from UserRole where user.id=:userId and role.id=:roleId',
            [userId: userId, roleId: roleId]
    }

    static UserRole create(User user, Role role, boolean flush = false) {
        new UserRole(user: user, role: role).save(flush: flush, insert: true)
    }

    static boolean remove(User user, Role role, boolean flush = false) {
        UserRole instance = UserRole.findByUserAndRole(user, role)
        if (!instance) {
            return false
        }

        instance.delete(flush: flush)
        true
    }

    static void removeAll(User user) {
        executeUpdate 'DELETE FROM UserRole WHERE user=:user', [user: user]
    }

    static void removeAll(Role role) {
        executeUpdate 'DELETE FROM UserRole WHERE role=:role', [role: role]
    }

    static mapping = {
        id composite: ['role', 'user']
        version false
    }
}
这是我的DataSource.groovy文件,其中包含数据库设置:

environments {
    development {
        dataSource {
            dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate', ''
            driverClassName = 'com.mysql.jdbc.Driver'
            username = 'root'
            password = 'root'
            url = 'jdbc:mysql://localhost:3306/database?autoreconnect=true&useUnicode=true&characterEncoding=utf-8'
        }
    }
    test {
        dataSource {
            dbCreate = "update"
            url = "jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
        }
    }
    production {
        dataSource {
            dbCreate = 'create-drop'
            driverClassName = 'com.mysql.jdbc.Driver'
            username = 'root'
            password = 'root'
            url = 'jdbc:mysql://localhost:3306/database?autoreconnect=true&useUnicode=true&characterEncoding=utf-8'
        }
    }
}
我真的不知道发生了什么事。 我添加了可为null的constraint,试图将数据放入“createdrop”/“update”中

有趣的是:当我删除数据库,然后再次创建它时,第一次服务器启动是好的,但重启后崩溃

我尝试将println日志放入BootStrap.groovy,我可以在开发环境中看到它们,但不能在生产服务器中看到它们

所以我不确定我的引导程序是否更新了

我使用以下方法创建战争:

grails prod war target/my-new-war-0.0.x.war
谢谢你的阅读


Snite

我不确定你的代码到底出了什么问题,但是你的巨大代码块让我头疼,所以我不得不发布这篇文章

Role role = Role.findByAuthority("ROLE_ADMIN") ?: new Role(authority: "ROLE_ADMIN").save(flush: true, failOnError: true)

if (UserRole.countByRole(role) == 0) {
    User user = new User(username: 'admin', password: 'admin', enabled: true).save(flush: true, failOnError: true)
    UserRole.create(user, role, true)
}

嗯,这是一个零点异常:

ERROR context.GrailContextLoader-初始化应用程序时出错:null java.lang.NullPointerException 在com.aftmevent.security.UserRole.createUserRole.groovy:32 在BootStrap$\u closure1.doCallBootStrap.groovy:16

不确定粘贴的内容是否与您自己的行号完全匹配,您现在可以尝试通过四处查看并添加问号:

def existingAdminRole = Role.findByAuthority('ROLE_ADMIN')
        def existingUserRole = null
        def existingAdminUser = null
        if (existingAdminRole) {
            existingUserRole = UserRole.findByRole(existingAdminRole)
        }
        if (existingUserRole) {
            existingAdminUser = existingUserRole.user
        }
改为:

def existingAdminRole = Role?.findByAuthority('ROLE_ADMIN')
        def existingUserRole = null
        def existingAdminUser = null
        if (existingAdminRole) {
            existingUserRole = UserRole?.findByRole(existingAdminRole)
        }
        if (existingUserRole) {
            existingAdminUser = existingUserRole?.user
        }
您也可以尝试Findorsavehere,而不是尝试生成新记录:


您需要了解UserRole的第32行发生了什么,这将是您问题的开始,然后是第16行的引导。

谢谢您的回答,这些回答帮助我解决了我的问题

这很愚蠢,但在我的rundeck脚本中,在生产服务器上部署war时,使用的war版本已经过时-_-

因此,用正确的war版本手动执行它可以解决我的问题

谢谢你,因为你的建议帮助我阅读了关于grails框架的adequat文档,并帮助我在这里思考

干杯


Snite

我的猜测是缺少导入,这似乎是我从引导程序创建东西时最常见的问题。
 def n1=MyContinent.findOrSaveWhere(continentName: 'Asia')
                def n2=MyContinent.findOrSaveWhere(continentName: 'Europe')

                // Create countries and provde continent map value as above defs
                def c1 = MyCountry.findOrSaveWhere(mycontinent: n2, countryName:'United Kingdom',ccode:'GB',language:'')
                def c2 = MyCountry.findOrSaveWhere(mycontinent: n2, countryName:'France',ccode:'FR',language:'')
                def c3 = MyCountry.findOrSaveWhere(mycontinent: n1, countryName:'China',ccode:'CN',language:'')
                def c4 = MyCountry.findOrSaveWhere(mycontinent: n1, countryName:'India',ccode:'IN',language:'')