简体   繁体   English

ArrayIndexOutOfBoundsException:在Grails域类的this()中为0

[英]ArrayIndexOutOfBoundsException: 0 in this() of Grails Domain Class

I am working on a split Grails-Project, see here: grails3 using a plugin for domain classes, specifically spring security User/Role 我正在研究一个拆分的Grails-Project,请参见此处: grails3,它使用域类插件,特别是spring security User / Role

Basically I am trying to put my Domain Classes into a plugin that can be used in multiple other projects. 基本上,我试图将我的域类放入一个可以在多个其他项目中使用的插件。

I am getting this Exception when trying to start my Server: 尝试启动服务器时出现此异常:

ERROR org.springframework.boot.SpringApplication - Application startup failed
java.lang.ArrayIndexOutOfBoundsException: 0
        at wcommon.WebsiteRole.<init>(WebsiteRole.groovy:15)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        at org.springsource.loaded.ri.ReflectiveInterceptor.jlrConstructorNewInstance(ReflectiveInterceptor.java:1075)
        at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
        at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
        at BootStrap$_closure1.doCall(BootStrap.groovy:9)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1426)
        at org.codehaus.groovy.ron.CachedMethod.invoke(CachedMethod.java:93)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
        at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1021)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1086)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1021)
        at groovy.lang.Closure.call(Closure.java:426)
        at groovy.lang.Closure.call(Closure.java:420)
        at grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:437)
        at grails.util.Environment.executeForEnvironment(Environment.java:430)
        at grails.util.Environment.executeForCurrentEnvironment(Environment.java:406)
        at org.grails.web.servlet.boostrap.DefaultGrailsBootstrapClass.callInit(DefaultGrailsBootstrapClass.java:62)
        at org.grails.web.servlet.context.GrailsConfigUtils.executeGrailsBootstraps(GrailsConfigUtils.java:65)
        at org.grails.plugins.web.servlet.context.BootStrapClassRunner.onStartup(BootStrapClassRunner.groovy:53)
        at grails.boot.config.GrailsApplicationPostProcessor.onApplicationEvent(GrailsApplicationPostProcessor.groovy:240)
        at grails.boot.config.GrailsApplicationPostProcessor.onApplicationEvent(GrailsApplicationPostProcessor.groovy)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:163)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:136)
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:381)
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:335)
        at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:855)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:140)
        at org.spmework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766)
        at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:55)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:365)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:354)
        at grails.boot.GrailsApp$run.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
        at webp.Application.main(Application.groovy:8)
:WebP:bootRun FAILED

I have no idea at all why this happens. 我完全不知道为什么会这样。 The line in question is a call to this() Why would that throw such an exception? 有问题的行是对this()的调用,为什么会抛出这样的异常? My initial reaction was to remove this() and add an empty default constructor to the class, but that apparently broke the Dependency Injection, which caused the issue described in the question I liked above. 我最初的反应是删除this()并向该类添加一个空的默认构造函数,但这显然破坏了依赖注入,这导致了我上面喜欢的问题中描述的问题。

Code involved from my side is: 我这边涉及的代码是:

package wcommon

import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString

@EqualsAndHashCode(includes='authority')
@ToString(includes='authority', includeNames=true, includePackage=false)
class WebsiteRole implements Serializable {

    private static final long serialVersionUID = 1

    String authority

    WebsiteRole(String authority) {
        **this();** // line 15
        this.authority = authority
    }

    static constraints = {
        authority blank: false, unique: true
    }

    static mapping = {
        cache true
    }
}


import grails.core.GrailsApplication
import wcommon.WebsiteUserWebsiteRole;

class BootStrap {

    GrailsApplication grailsApplication

    def init = { servletContext ->
        **WebsiteUserWebsiteRole.initDefaults(grailsApplication)** //line 9
    }
    def destroy = {
    }
}

And the initDefaults function looks like this: initDefaults函数如下所示:

**static def initDefaults(GrailsApplication grailsApplication) {
    def patientRole = new WebsiteRole("ROLE_PATIENT").save();
    def adminRole = new WebsiteRole("ROLE_ADMIN").save()
    def doctorRole = new WebsiteRole("ROLE_DOCTOR").save()
    def nurseRole = new WebsiteRole("ROLE_NURSE").save()
    def serverRole = new WebsiteRole("ROLE_SERVER").save()

    def user1 = new WebsiteUser("admin", "password").save()
    WebsiteUserWebsiteRole.create user1, adminRole, true

    def user2 = new WebsiteUser("doctor", "password").save()
    WebsiteUserWebsiteRole.create user2, doctorRole, true

    def user3 = new WebsiteUser("nurse", "password").save()
    WebsiteUserWebsiteRole.create user3, nurseRole, true


}**

EDIT: Using Grails Version 3.1.1 编辑:使用Grails 3.1.1版

java -version is 1.7.0_79 java -version是1.7.0_79

spring security plugin is 'org.grails.plugins:spring-security-core:3.0.3' 春季安全性插件是“ org.grails.plugins:spring-security-core:3.0.3”

I am not quite sure which Database version I am using, I am just using the by default included h2, the dependency just says: runtime "com.h2database:h2" 我不太确定我使用的是哪个数据库版本,默认情况下,我只是使用包括的h2,依赖项只是说:运行时“ com.h2database:h2”

The Project setup in general is that my Domain classes are in one project, which is a plugin project. 通常,项目设置是我的Domain类在一个项目中,这是一个插件项目。 The Project that has the issues includes the Domain classes via compile project(':WebCommon') in the dependencies. 有问题的项目在依赖项中包括通过编译项目(':WebCommon')的Domain类。 Compile works fine. 编译正常。

EDIT 2: So if I remove the this() and add a default constructor it does not throw the exception, however the dependency injection of the spring security service in this class does not work: 编辑2:因此,如果我删除this()并添加一个默认构造函数,它不会引发异常,但是在此类中,Spring Security服务的依赖项注入不起作用:

package wcommon

import grails.plugin.springsecurity.SpringSecurityService;
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString

@EqualsAndHashCode(includes='username')
@ToString(includes='username', includeNames=true, includePackage=false)
class WebsiteUser implements Serializable {

    private static final long serialVersionUID = 1

    public SpringSecurityService springSecurityService

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

    WebsiteUser() {

    }

    WebsiteUser(String username, String password) {
        this.username = username
        this.password = password
    }

    Set<WebsiteRole> getAuthorities() {
        WebsiteUserWebsiteRole.findAllByWebsiteUser(this)*.websiteRole
    }

    def beforeInsert() {
        encodePassword()
    }

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

    protected void encodePassword() {
        println springSecurityService // prints null
        password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password
    }

    static transients = ['springSecurityService']

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

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

After I changed the property from just def springSecurityService to public SpringSecurityService it told me that an indirect dependency to HttpServletRequest. 将属性从def springSecurityService更改为public SpringSecurityService后,它告诉我HttpServletRequest的间接依赖关系。 Adding these dependencies to the plugin project fixes that, but this doesn't change anything about the injection not working: 将这些依赖项添加到插件项目可以解决此问题,但这不会改变注入无效的任何内容:

compile "org.springframework.boot:spring-boot-starter-tomcat"
compile "org.grails:grails-web-boot"

I thought that my changes to the User and Role classes to fix the this() issue caused the dependency injection problem. 我认为我对User和Role类的更改以解决this()问题导致了依赖项注入问题。 But maybe I am wrong and both of the issues are caused by something else, probably related to my project setup. 但是也许我错了,这两个问题都是由其他原因引起的,可能与我的项目设置有关。 I dunno, this is all really confusing, been fighting with grails for since yesterday. 我不知道,这真是令人困惑,从昨天开始就一直在努力。

EDIT: To get it to work I now first fixed the Exception by removing this() and adding the default constructor and then I injected a springSecurityService into the Bootstrap of my main project that is used to set a static public field on the class in the plugin project that ssneeds the springSecurityService. 编辑:为了使其正常工作,现在我首先通过移除this()并添加默认构造函数来修复异常,然后将springSecurityService注入到我的主项目的Bootstrap中,该项目用于在该类中的类上设置静态公共字段ssneed springSecurityService的插件项目。 Ugly, but it works better than anything I've tried so far. 丑陋,但是它比我迄今为止尝试过的任何方法都好。 ... okay actually now this simple test of a controller: ...好吧,现在对控制器进行以下简单测试:

import grails.converters.JSON
import grails.plugin.springsecurity.annotation.Secured

@Secured(['ROLE_ADMIN', 'ROLE_SERVER'])
class ApiController {

    def index() {
        render getAuthenticatedUser() as JSON
    }
}

throws a MissingMethodException about getAuthenticatedUser() 抛出有关getAuthenticatedUser()的MissingMethodException

That Controller was added via create-controller I guess this whole "split the project into multiple parts" isn't working at all and broke something very very deep down that causes all these issues to show up. 那个Controller是通过create-controller添加的,我想这整个“将项目分成多个部分”根本无法正常工作,并且破坏了很深的东西,导致所有这些问题都出现了。 I think instead of trying to split my project I'll just make a single web-app project that is configured with a flag that tells it which functions to activate and deactivate.... 我认为,与其尝试拆分项目,不如创建一个单独的Web应用程序项目,该项目配置有一个标志,该标志指示其激活和停用的功能。

If somebody can tell me how to do a properly split grails project with common domain objects in a common library please see this question and post there: grails3 using a plugin for domain classes, specifically spring security User/Role 如果有人可以告诉我如何使用公共库中的公共域对象来正确地拆分grails项目,请参阅此问题并在此处发布: grails3使用域类插件,特别是spring security User / Role

You can safely remove all of the constructors from those classes (the WebsiteUser , WebsiteRole , and WebsiteUserWebsiteRole classes). 您可以安全地从这些类( WebsiteUserWebsiteRoleWebsiteUserWebsiteRole类)中删除所有构造函数。 This should also fix the bean injection problem. 这也应该解决bean注入问题。 Instead of calling them in your init, you can all the map style constructor. 无需在初始化中调用它们,而是可以使用所有地图样式构造函数。

static def initDefaults(GrailsApplication grailsApplication) { def patientRole = new WebsiteRole(authority: "ROLE_PATIENT").save(); ... def userX = new WebsiteUser(username:"nurse", password:"password").save() WebsiteUserWebsiteRole.create user3, nurseRole, true }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM