我在rest-api grails应用程序配置文件下生成了 Controller 。 Controller 没有任何改变,仅添加了一些println调用。

对于调用curl -X PUT -d name=petr2 -d phone=338 localhost:8080/TSCell/3,我有{"message":"Internal server error","error":500}响应。在调试中,我可以看到,该错误在最终respond TSCell, [status: OK, view:"show"]调用之后发生。

更新方法代码:

@Transactional
def update(TSCell tSCell) {
    println "in update method"
    if (tSCell == null) {
        transactionStatus.setRollbackOnly()
        render status: NOT_FOUND
        return
    }

    if (tSCell.hasErrors()) {
        transactionStatus.setRollbackOnly()
        respond tSCell.errors, view:'edit'
        return
    }

    tSCell.save flush:true

    respond tSCell, [status: OK, view:"show"]
}

和堆栈跟踪
ERROR org.grails.web.errors.GrailsExceptionResolver - IllegalArgumentException occurred when processing request: [PUT] /TSCell/3
Model variable [TSCell] of with value [class zcrm.api.TSCell] type [java.lang.Class] is not of the correct type [zcrm.api.TSCell]. Stacktrace follows:
java.lang.reflect.InvocationTargetException: null
    at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:210)
    at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:187)
    at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:883)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
    at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
    at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
    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:745)
Caused by: grails.views.ViewRenderException: Error rendering view: Model variable [TSCell] of with value [class zcrm.api.TSCell] type [java.lang.Class] is not of the correct type [zcrm.api.TSCell]
    at grails.views.AbstractWritableScript.writeTo(AbstractWritableScript.groovy:33)
    at grails.views.mvc.GenericGroovyTemplateView.renderMergedOutputModel(GenericGroovyTemplateView.groovy:71)
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303)
    at grails.views.mvc.renderer.DefaultViewRenderer.render(DefaultViewRenderer.groovy:105)
    at grails.artefact.controller.RestResponder$Trait$Helper.internalRespond(RestResponder.groovy:188)
    at grails.artefact.controller.RestResponder$Trait$Helper.respond(RestResponder.groovy:98)
    at zcrm.api.TSCellController$$EQ0icN2W.$tt__update(TSCellController.groovy:64)
    at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:96)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
    at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:93)
    at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:96)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
    at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:93)
    ... 14 common frames omitted
Caused by: java.lang.IllegalArgumentException: Model variable [TSCell] of with value [class zcrm.api.TSCell] type [java.lang.Class] is not of the correct type [zcrm.api.TSCell]
        at grails.views.WritableScriptTemplate.make(WritableScriptTemplate.groovy:138)
    at grails.plugin.json.view.api.internal.DefaultGrailsJsonViewHelper.prepareWritable(DefaultGrailsJsonViewHelper.groovy:736)
    at grails.plugin.json.view.api.internal.DefaultGrailsJsonViewHelper$7.writeTo(DefaultGrailsJsonViewHelper.groovy:713)
    at grails.plugin.json.view.JsonViewTemplate.json(JsonViewTemplate.groovy:126)
    at grails.plugin.json.view.JsonViewTemplate.json(JsonViewTemplate.groovy:149)
    at zcrm_api_TSCell_show_gson.run(zcrm_api_TSCell_show_gson:7)
    at grails.plugin.json.view.JsonViewTemplate.doWrite(JsonViewTemplate.groovy:35)
    at grails.views.AbstractWritableScript.writeTo(AbstractWritableScript.groovy:30)
    ... 26 common frames omitted

提前致谢。

最佳答案

该代码不应该编译,但是Groovy有时过于“有用”,因此无法通过。您为实例变量命名与其类TSCell相同,这真是一个有趣的代码块,以了解Groovy如何处理实例和静态方法调用之间的歧义。

对于第一行,由于您具有TSCell TSCell,因此编译器有可能知道左侧的是类名,而右侧的是实例变量,因为没有其他有效的解释这些标记。

在第三行中,不清楚是否正在检查类或实例变量是否为null,但是我在本地尝试了此操作,它是实例变量。
TSCell.hasErrors()可以解释为对类的静态方法调用或对实例的调用,但是由于该方法不是静态的,因此Groovy在实例上对其进行调用并成功。必须对save调用应用相同的逻辑,但是由于它不是静态方法,因此再次在实例上调用并成功。

然后在方法的最后一行,kaboom,您的运气在四个成功的调用之后就用光了。 respond方法有一些重载,您最终调用respond(Object, Map),这对于TSCell类或TSCell TSCell类的实例都有效。 Groovy选择了一种不是您想要的和respond方法内不支持的。

Groovy共享Java的变量和类命名约定,即类名以大写字母开头,实例变量名以小写字母开头。只是告诉人们这是一种好方法,这是一回事,但是像这样的例子使使用大写实例变量名的一个不好的主意变得更加显而易见(您应该能够查看变量,而无需查看其声明以了解它是一个类还是var名称),以及为什么使用与该类相同的名称更糟糕。

07-25 22:58