我是grails的新手,我使用grails 3.1.11编写使用spring security 3.1.1保护的API。我正在使用Document DB来保存数据。
使用插件命令我创建了域类
grails s2-quickstart com.documentstore.domain User Role
在所需的包中生成了User.groovy,Role.groovy,UserRole.groovy和application.groovy类。我修改了Bootstrap.groovy如下:
import com.documentstore.domain.Role
import com.documentstore.domain.User
import com.documentstore.domain.UserRole
class BootStrap {
def init = { servletContext ->
def role = new Role(authority: 'ROLE_USER')
role.save()
def me = new User(username : 'vamsi', password : 'password')
me.save()
UserRole.create(me, role)
UserRole.withSession {
it.flush()
it.clear()
}
}
def destroy = {
}
}
当我尝试运行应用程序时,我得到了域类无法识别的错误:
ERROR org.springframework.boot.SpringApplication - Application startup failed
java.lang.IllegalStateException: Either class [com.documentstore.domain.Role] is not a domain class or GORM has not been initialized correctly or has already been shutdown. If you are unit testing your entities using the mocking APIs
at org.grails.datastore.gorm.GormEnhancer.stateException(GormEnhancer.groovy:161)
at org.grails.datastore.gorm.GormEnhancer.findInstanceApi(GormEnhancer.groovy:167)
at org.grails.datastore.gorm.GormEnhancer.findInstanceApi(GormEnhancer.groovy)
at org.grails.datastore.gorm.GormEntity$Trait$Helper.currentGormInstanceApi(GormEntity.groovy:1322)
at org.grails.datastore.gorm.GormEntity$Trait$Helper.save(GormEntity.groovy:98)
at org.grails.datastore.gorm.GormEntity$Trait$Helper$save.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:125)
at com.documentstore.domain.Role.save(Role.groovy)
at com.documentstore.domain.Role.save(Role.groovy)
at org.grails.datastore.gorm.GormEntity$save.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:117)
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.codehaus.groovy.reflection.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:1024)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1089)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1024)
at groovy.lang.Closure.call(Closure.java:414)
at groovy.lang.Closure.call(Closure.java:408)
代码有问题吗?怎么解决这个问题?
指定build.gradle和插件生成的代码以供参考:
Build.gradle
dependencies {
compile "org.springframework.boot:spring-boot-starter-logging"
compile "org.springframework.boot:spring-boot-autoconfigure"
compile "org.grails:grails-core"
compile "org.springframework.boot:spring-boot-starter-actuator"
compile "org.springframework.boot:spring-boot-starter-tomcat"
compile "org.grails:grails-dependencies"
compile "org.grails:grails-web-boot"
compile "org.grails.plugins:cache"
compile "org.grails.plugins:scaffolding"
console "org.grails:grails-console"
compile "org.grails.plugins:spring-security-core:3.1.1"
// https://mvnrepository.com/artifact/com.microsoft.azure/azure-storage
compile group: 'com.microsoft.azure', name: 'azure-storage', version: '4.3.0'
// https://mvnrepository.com/artifact/com.microsoft.azure/azure-documentdb
compile group: 'com.microsoft.azure', name: 'azure-documentdb', version: '1.8.1'
profile "org.grails.profiles:web"
runtime "com.bertramlabs.plugins:asset-pipeline-grails:2.8.2"
//runtime "com.h2database:h2"
// https://mvnrepository.com/artifact/com.microsoft.azure/azure-documentdb
runtime group: 'com.microsoft.azure', name: 'azure-storage', version: '4.3.0'
// https://mvnrepository.com/artifact/com.microsoft.azure/azure-storage
testCompile "org.grails:grails-plugin-testing"
testCompile "org.grails.plugins:geb"
testRuntime "org.seleniumhq.selenium:selenium-htmlunit-driver:2.47.1"
testRuntime "net.sourceforge.htmlunit:htmlunit:2.18"
}
Role.groovy
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
@ToString(includes='authority', includeNames=true, includePackage=false)
class Role implements Serializable {
private static final long serialVersionUID = 1
String authority
static constraints = {
authority blank: false, unique: true
}
static mapping = {
cache true
}
}
User.groovy
package com.documentstore.domain
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
@EqualsAndHashCode(includes='username')
@ToString(includes='username', includeNames=true, includePackage=false)
class User implements Serializable {
private static final long serialVersionUID = 1
transient springSecurityService
String username
String password
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired
User(String username, String password) {
this()
this.username = username
this.password = password
}
Set<Role> getAuthorities() {
UserRole.findAllByUser(this)*.role
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
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`'
}
}
UserRole.groovy
package com.documentstore.domain
import grails.gorm.DetachedCriteria
import groovy.transform.ToString
import org.apache.commons.lang.builder.HashCodeBuilder
@ToString(cache=true, includeNames=true, includePackage=false)
class UserRole implements Serializable {
private static final long serialVersionUID = 1
User user
Role role
UserRole(User u, Role r) {
this()
user = u
role = r
}
@Override
boolean equals(other) {
if (!(other instanceof UserRole)) {
return false
}
other.user?.id == user?.id && other.role?.id == role?.id
}
@Override
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) {
criteriaFor(userId, roleId).get()
}
static boolean exists(long userId, long roleId) {
criteriaFor(userId, roleId).count()
}
private static DetachedCriteria criteriaFor(long userId, long roleId) {
UserRole.where {
user == User.load(userId) &&
role == Role.load(roleId)
}
}
static UserRole create(User user, Role role, boolean flush = false) {
def instance = new UserRole(user: user, role: role)
instance.save(flush: flush, insert: true)
instance
}
static boolean remove(User u, Role r, boolean flush = false) {
if (u == null || r == null) return false
int rowCount = UserRole.where { user == u && role == r }.deleteAll()
if (flush) { UserRole.withSession { it.flush() } }
rowCount
}
static void removeAll(User u, boolean flush = false) {
if (u == null) return
UserRole.where { user == u }.deleteAll()
if (flush) { UserRole.withSession { it.flush() } }
}
static void removeAll(Role r, boolean flush = false) {
if (r == null) return
UserRole.where { role == r }.deleteAll()
if (flush) { UserRole.withSession { it.flush() } }
}
static constraints = {
role validator: { Role r, UserRole ur ->
if (ur.user == null || ur.user.id == null) return
boolean existing = false
UserRole.withNewSession {
existing = UserRole.exists(ur.user.id, r.id)
}
if (existing) {
return 'userRole.exists'
}
}
}
static mapping = {
id composite: ['user', 'role']
version false
}
}
答案 0 :(得分:1)
这是因为spring security和spring security rest插件依赖于hibernate,ehcache和h2数据库jar。因为我使用的是不同的数据库,所以我删除了这些jar依赖项。在我将这些jar包含为运行时依赖项并修改application.yml以包含这些数据源的默认配置之后,所有内容都按预期工作正常。