I'm developing a new application that needs to read existing db-tables in a legacy db. To do that I also have to have it work in the development environment too. But when I try to create a new record it fails with the following message:
URI
/roleType/save
Class
grails.web.mapping.mvc.exceptions.CannotRedirectException
Message
null
Caused by
Cannot redirect for object [com.mytrading.legacy.RoleType : (unsaved)] it is not a domain or has no identifier. Use an explicit redirect instead
To get the controllers and views I ran "grails generate-all".
The domain, where I removed some fields for clarity, look like this:
class RoleType {
int roleType
static mapping = {
table 'RoleType'
version false
id name: 'roleType', type:'int', generator:'assigned'
roleType column: 'RoleType'
}
}
I don't know what they mean with: "is not a domain or has no identifier" and what they mean with explicit redirect, what shall I redirect to? Is that the only solution - I can't believe in that.
The Controller:
import static org.springframework.http.HttpStatus.*
import grails.transaction.Transactional
import grails.plugin.springsecurity.annotation.Secured
@Secured(['ROLE_ADMIN','ROLE_SALES'])
@Transactional(readOnly = true)
class RoleTypeController {
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond RoleType.list(params), model:[roleTypeCount: RoleType.count()]
}
def show(RoleType roleType) {
respond roleType
}
def create() {
respond new RoleType(params)
}
@Transactional
def save(RoleType roleType) {
if (roleType == null) {
transactionStatus.setRollbackOnly()
notFound()
return
}
if (roleType.hasErrors()) {
transactionStatus.setRollbackOnly()
respond roleType.errors, view:'create'
return
}
roleType.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'roleType.label', default: 'RoleType'), roleType.id])
redirect roleType
}
'*' { respond roleType, [status: CREATED] }
}
}
def edit(RoleType roleType) {
respond roleType
}
@Transactional
def update(RoleType roleType) {
if (roleType == null) {
transactionStatus.setRollbackOnly()
notFound()
return
}
if (roleType.hasErrors()) {
transactionStatus.setRollbackOnly()
respond roleType.errors, view:'edit'
return
}
roleType.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message', args: [message(code: 'roleType.label', default: 'RoleType'), roleType.id])
redirect roleType
}
'*'{ respond roleType, [status: OK] }
}
}
@Transactional
def delete(RoleType roleType) {
if (roleType == null) {
transactionStatus.setRollbackOnly()
notFound()
return
}
roleType.delete flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.deleted.message', args: [message(code: 'roleType.label', default: 'RoleType'), roleType.id])
redirect action:"index", method:"GET"
}
'*'{ render status: NO_CONTENT }
}
}
protected void notFound() {
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'roleType.label', default: 'RoleType'), params.id])
redirect action: "index", method: "GET"
}
'*'{ render status: NOT_FOUND }
}
}
}
After adding code to the controller we get:
URI
/roleType/save
Class
java.lang.RuntimeException
Message
null
Caused by
org.grails.datastore.mapping.validation.ValidationErrors: 0 errors
Around line 30 of grails-app\controllers\com\torntrading\legacy\RoleTypeController.groovy
27: @Transactional
28: def save(RoleType roleType) {
29: roleType.validate()
30: throw new RuntimeException("${roleType.errors}")
31: if (roleType == null) {
32: transactionStatus.setRollbackOnly()
33: notFound()
The problem is your controller is using id
which you replaced with roleType
.