将Groovy MOP委派连接到视图 - StackOverflowError

时间:2014-03-20 15:33:52

标签: grails groovy delegation stack-overflow mop

我是Groovy和Grails的新手,并试图通过审阅这篇文章来努力实现授权:http://groovy.codehaus.org/Replace+Inheritance+with+Delegation

使用Netbeans中的默认生成视图,当我遵循继承和委派示例时,它创建了相应的表单字段,但在MOP示例中,它只创建了本地变量字段。如果我使用前面示例生成的表单,我会得到一个StackOverflowError。

2014-03-20 08:39:32,569 [http-bio-8080-exec-7] ERROR errors.GrailsExceptionResolver  - StackOverflowError occurred when processing request: [GET] /Delegation/attendee/create
Stacktrace follows:
Message: Error processing GroovyPageView: Error executing tag <g:form>: Error executing tag <g:render>: null
    Line | Method
->>  530 | doFilter  in C:\development\sandbox\Delegation\grails-app\views\attendee\create.gsp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Caused by GrailsTagException: Error executing tag <g:form>: Error executing tag <g:render>: null
->>   36 | doCall    in C:/development/sandbox/Delegation/grails-app/views/attendee/create.gsp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Caused by GrailsTagException: Error executing tag <g:render>: null
->>   31 | doCall    in C:/development/sandbox/Delegation/grails-app/views/attendee/create.gsp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Caused by StackOverflowError: null
->> 2037 | get       in java.util.Collections$SynchronizedMap
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|     11 | doCall    in delegation.Attendee$_hasLocalProperty_closure2
|     29 | getProperty in delegation.Attendee
|     30 | getProperty in     ''
....
|Compiling 1 source files

如何将视图连接到MOP示例?

更新:添加视图,域类和控制器类

域:

class Attendee {

  enum AttendeeRole {
    VENDOR, PRESENTER, STUDENT
  }

  private person = new Person()
  private hasLocalProperty(name) {
    metaClass.properties.collect{ it.name }.contains(name)
  }

  AttendeeRole role

  Attendee (Map map) {
    map.each{ k, v -> setProperty(k, v) }
  }

  void setProperty(String name, value) {
    if (hasLocalProperty(name)) this.@"$name" = value 
    else delegate.setProperty(name, value)
  }

  def getProperty(String name) {
    if (hasLocalProperty(name)) return this.@"$name"
    else return delegate.getProperty(name)
  }

}

人:

class Person {
  String firstName
  String lastName
  Integer age

  static constraints = {
    lastName blank: false
    firstName blank: false
    age min: 18
  }

  def describe() {"$firstName $lastName is $age"}
}

查看(在继承时生成):

<%@ page import="delegation.Attendee" %>

<div class="fieldcontain ${hasErrors(bean: attendeeInstance, field: 'lastName', 'has-error')} required form-group">
  <label for="lastName" class="control-label col-sm-2">
    <g:message code="attendee.lastName.label" default="Last Name" />
    <span class="required-indicator">*</span>
  </label>
  <div class="col-sm-3">
    <g:textField class="form-control" name="lastName" required="" value="${attendeeInstance?.lastName}"/>

  </div>
</div>

<div class="fieldcontain ${hasErrors(bean: attendeeInstance, field: 'firstName', 'has-error')} required form-group">
  <label for="firstName" class="control-label col-sm-2">
    <g:message code="attendee.firstName.label" default="First Name" />
    <span class="required-indicator">*</span>
  </label>
  <div class="col-sm-3">
    <g:textField class="form-control" name="firstName" required="" value="${attendeeInstance?.firstName}"/>

  </div>
</div>

<div class="fieldcontain ${hasErrors(bean: attendeeInstance, field: 'age', 'has-error')} required form-group">
  <label for="age" class="control-label col-sm-2">
    <g:message code="attendee.age.label" default="Age" />
    <span class="required-indicator">*</span>
  </label>
  <div class="col-sm-3">
    <g:field class="form-control" name="age" type="number" min="18" value="${attendeeInstance.age}" required=""/>

  </div>
</div>


<div class="fieldcontain ${hasErrors(bean: attendeeInstance, field: 'role', 'has-error')} required form-group">
  <label for="role" class="control-label col-sm-2">
    <g:message code="attendee.role.label" default="Role" />
    <span class="required-indicator">*</span>
  </label>
  <div class="col-sm-3">
    <g:select class="form-control" name="role" from="${delegation.Attendee$AttendeeRole?.values()}" keys="${delegation.Attendee$AttendeeRole.values()*.name()}" required="" value="${attendeeInstance?.role?.name()}" />

  </div>
</div>

使用MOP生成的视图:

<%@ page import="delegation.Attendee" %>

<div class="fieldcontain ${hasErrors(bean: attendeeInstance, field: 'role', 'has-error')} required form-group">
  <label for="role" class="control-label col-sm-2">
    <g:message code="attendee.role.label" default="Role" />
    <span class="required-indicator">*</span>
  </label>
  <div class="col-sm-3">
    <g:select class="form-control" name="role" from="${delegation.Attendee$AttendeeRole?.values()}" keys="${delegation.Attendee$AttendeeRole.values()*.name()}" required="" value="${attendeeInstance?.role?.name()}" />

  </div>
</div>

控制器类:

import static org.springframework.http.HttpStatus.*
import grails.transaction.Transactional

@Transactional(readOnly = true)
class AttendeeController {

    static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]

    def index(Integer max) {
        params.max = Math.min(max ?: 10, 100)
        respond Attendee.list(params), model:[attendeeInstanceCount: Attendee.count()]
    }

    def show(Attendee attendeeInstance) {
        respond attendeeInstance
    }

    def create() {
        respond new Attendee(params)
    }

    @Transactional
    def save(Attendee attendeeInstance) {
        if (attendeeInstance == null) {
            notFound()
            return
        }

        if (attendeeInstance.hasErrors()) {
            respond attendeeInstance.errors, view:'create'
            return
        }

        attendeeInstance.save flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.created.message', args: [message(code: 'attendeeInstance.label', default: 'Attendee'), attendeeInstance.id])
                redirect attendeeInstance
            }
            '*' { respond attendeeInstance, [status: CREATED] }
        }
    }

    def edit(Attendee attendeeInstance) {
        respond attendeeInstance
    }

    @Transactional
    def update(Attendee attendeeInstance) {
        if (attendeeInstance == null) {
            notFound()
            return
        }

        if (attendeeInstance.hasErrors()) {
            respond attendeeInstance.errors, view:'edit'
            return
        }

        attendeeInstance.save flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.updated.message', args: [message(code: 'Attendee.label', default: 'Attendee'), attendeeInstance.id])
                redirect attendeeInstance
            }
            '*'{ respond attendeeInstance, [status: OK] }
        }
    }

    @Transactional
    def delete(Attendee attendeeInstance) {

        if (attendeeInstance == null) {
            notFound()
            return
        }

        attendeeInstance.delete flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.deleted.message', args: [message(code: 'Attendee.label', default: 'Attendee'), attendeeInstance.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: 'attendeeInstance.label', default: 'Attendee'), params.id])
                redirect action: "index", method: "GET"
            }
            '*'{ render status: NOT_FOUND }
        }
    }
}

0 个答案:

没有答案