我在 rest-api
下生成了 Controller grails 应用程序配置文件。 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
编译器有可能知道左边的是类名,右边的是实例变量,因为这些标记没有其他有效的解释。
在第三行中,不清楚是否正在检查类或实例变量是否为空,但我在本地尝试过,它是实例变量。TSCell.hasErrors()
可以解释为对类的静态方法调用或对实例的调用,但由于该方法不是静态的,Groovy 会在实例上调用它并成功。相同的逻辑必须应用于 save
调用,但同样因为它不是静态方法,所以它调用实例并成功。
然后在方法的最后一行,kaboom,你的运气在四次成功调用后用完了。 respond
有一些重载方法,你最终调用 respond(Object, Map)
, 这对 TSCell
都有效类(class),或 TSCell
TSCell
的实例类(class)。 Groovy 选择了一个不是您想要的和一个在 respond
中不受支持的。方法。
Groovy 共享 Java 的变量和类命名约定,即类名以大写字母开头,实例变量名以小写字母开头。只是告诉人们这是一种好方法是一回事,但是像这样的示例使使用大写实例变量名称的坏主意变得更加明显(您应该能够查看变量而不需要查看它的声明以了解它是类名还是 var 名)以及为什么使用与类相同的名称更糟糕。
关于rest - 为什么默认的 Controller 实现会发送带有内部错误的崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40256099/