Kotlin 中的 Wicket NumberTextField 在提交时抛出 ClassCastException
Wicket NumberTextField in Kotlin throws ClassCastException when submitted
我在使用 Kotlin (1.1.0) 中的 Wicket (8.0.0-M4) NumberTextField 时遇到一些问题。
我的精简表格如下所示:
class Test : AbstractWebPage() {
val housenumberModel: Model<Int> = Model<Int>()
val housenumber = NumberTextField<Int>("housenumberModel", housenumberModel)
val form: Form<Unit> = object : Form<Unit>("adressForm") {}
override fun onInitialize() {
super.onInitialize()
form.add(housenumber.setRequired(false))
form.add(object : SubmitLink("submit") {
override fun onSubmit() {
super.onSubmit()
println(housenumberModel.`object`) // this is line 28
}
})
add(form)
}
}
提交表单后,我得到以下堆栈跟踪:
java.lang.ClassCastException: java.lang.String cannot be cast to
java.lang.Number
at com.mycompany.test.pages.Test$onInitialize.onSubmit(Test.kt:28)
at org.apache.wicket.markup.html.form.Form.delegateSubmit(Form.java:1312)
at org.apache.wicket.markup.html.form.Form.process(Form.java:979)
at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:802)
at org.apache.wicket.markup.html.form.Form.onRequest(Form.java:715)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.internalInvoke(ListenerRequestHandler.java:301)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.invoke(ListenerRequestHandler.java:250)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.invokeListener(ListenerRequestHandler.java:210)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.respond(ListenerRequestHandler.java:203)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:912)
at org.apache.wicket.request.RequestHandlerExecutor.execute(RequestHandlerExecutor.java:65)
at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:283)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:253)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:221)
at org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:262)
at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:204)
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:286)
[...]
如果我使用
val housenumberModel: Model<Int> = Model.of(0)
而不是
val housenumberModel: Model<Int> = Model<Int>()
一切正常。但是因为我的 NumberTextField 是可选的,所以我不想用 0 预初始化它。
我和我的同事们试图以我们能想到的各种方式更改模型的类型签名,但没有找到解决方案。一位同事建议编写一个自定义 Wicket 转换器,因为 Kotlins Int 被表示为原始类型(来自文档:"On the JVM, non-nullable values of this type are represented as values of the primitive type int.")尽管我还不知道这是否可行,但对我来说似乎有点矫枉过正.
我能想到的另一个 hack:写一些 JavaScript 来从输入字段中删除零。也不是我真正想做的事情。
问题:有没有简单的方法可以解决我的问题?
(作为奖励问题:已经有人用 Kotlin 编写了更大的 Wicket 应用程序,并且可以告诉我这种组合是否已准备好在黄金时间使用此堆栈开发关键项目,或者我的问题只是提示的冰山?)
[编辑]
svenmeier 指出的解决方案:
使用
val housenumber = NumberTextField<Int>("housenumberModel", housenumberModel, Int::class.java)
有效。
或者作为替代:
val housenumbervalue: Int? = null
val housenumberModel: IModel<Int> = PropertyModel<Int>(this, "housenumbervalue")
val housenumber = NumberTextField<Int>("housenumberModel", housenumberModel)
由于类型擦除,您的 NumberTextField 无法检测到模型的通用类型参数。由于您的模型对象为空,因此也不能用于派生类型。
在这种情况下,Wicket 假定一个 String 模型对象类型 :/.
要么显式地为 NumberTextField 提供类型,要么使用保留其通用信息的模型,例如一个 PropertyModel。
有一种方法可以告诉 wicket 您想要的类型,方法是在构造函数中添加类型。更多 here.
在 Java 中看起来像这样:
new NumberTextField<Integer>("housenumberModel", housenumberModel, Integer.class);
我在使用 Kotlin (1.1.0) 中的 Wicket (8.0.0-M4) NumberTextField 时遇到一些问题。
我的精简表格如下所示:
class Test : AbstractWebPage() {
val housenumberModel: Model<Int> = Model<Int>()
val housenumber = NumberTextField<Int>("housenumberModel", housenumberModel)
val form: Form<Unit> = object : Form<Unit>("adressForm") {}
override fun onInitialize() {
super.onInitialize()
form.add(housenumber.setRequired(false))
form.add(object : SubmitLink("submit") {
override fun onSubmit() {
super.onSubmit()
println(housenumberModel.`object`) // this is line 28
}
})
add(form)
}
}
提交表单后,我得到以下堆栈跟踪:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number at com.mycompany.test.pages.Test$onInitialize.onSubmit(Test.kt:28) at org.apache.wicket.markup.html.form.Form.delegateSubmit(Form.java:1312) at org.apache.wicket.markup.html.form.Form.process(Form.java:979) at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:802) at org.apache.wicket.markup.html.form.Form.onRequest(Form.java:715) at org.apache.wicket.core.request.handler.ListenerRequestHandler.internalInvoke(ListenerRequestHandler.java:301) at org.apache.wicket.core.request.handler.ListenerRequestHandler.invoke(ListenerRequestHandler.java:250) at org.apache.wicket.core.request.handler.ListenerRequestHandler.invokeListener(ListenerRequestHandler.java:210) at org.apache.wicket.core.request.handler.ListenerRequestHandler.respond(ListenerRequestHandler.java:203) at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:912) at org.apache.wicket.request.RequestHandlerExecutor.execute(RequestHandlerExecutor.java:65) at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:283) at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:253) at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:221) at org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:262) at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:204) at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:286) [...]
如果我使用
val housenumberModel: Model<Int> = Model.of(0)
而不是
val housenumberModel: Model<Int> = Model<Int>()
一切正常。但是因为我的 NumberTextField 是可选的,所以我不想用 0 预初始化它。
我和我的同事们试图以我们能想到的各种方式更改模型的类型签名,但没有找到解决方案。一位同事建议编写一个自定义 Wicket 转换器,因为 Kotlins Int 被表示为原始类型(来自文档:"On the JVM, non-nullable values of this type are represented as values of the primitive type int.")尽管我还不知道这是否可行,但对我来说似乎有点矫枉过正.
我能想到的另一个 hack:写一些 JavaScript 来从输入字段中删除零。也不是我真正想做的事情。
问题:有没有简单的方法可以解决我的问题?
(作为奖励问题:已经有人用 Kotlin 编写了更大的 Wicket 应用程序,并且可以告诉我这种组合是否已准备好在黄金时间使用此堆栈开发关键项目,或者我的问题只是提示的冰山?)
[编辑]
svenmeier 指出的解决方案:
使用
val housenumber = NumberTextField<Int>("housenumberModel", housenumberModel, Int::class.java)
有效。
或者作为替代:
val housenumbervalue: Int? = null
val housenumberModel: IModel<Int> = PropertyModel<Int>(this, "housenumbervalue")
val housenumber = NumberTextField<Int>("housenumberModel", housenumberModel)
由于类型擦除,您的 NumberTextField 无法检测到模型的通用类型参数。由于您的模型对象为空,因此也不能用于派生类型。
在这种情况下,Wicket 假定一个 String 模型对象类型 :/.
要么显式地为 NumberTextField 提供类型,要么使用保留其通用信息的模型,例如一个 PropertyModel。
有一种方法可以告诉 wicket 您想要的类型,方法是在构造函数中添加类型。更多 here.
在 Java 中看起来像这样:
new NumberTextField<Integer>("housenumberModel", housenumberModel, Integer.class);