java.lang.RuntimeException: 无法实例化@Form class。没有无参数构造函数
java.lang.RuntimeException: Unable to instantiate @Form class. No no-arg constructor
我正在写一个POJO
,如下所示。
public class EndpointParams implements Serializable {
private static final long serialVersionUID = -5269761907708414499L;
@QueryParam("pageNum") @DefaultValue("1") private int pageNum;
@QueryParam("pageSize") @DefaultValue("25") private int pageSize;
public EndpointParams (int pageNum, int pageSize) {
this.pageNum = pageNum;
this.pageSize = pageSize;
}
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
@Override
public boolean equals(Object obj) {
// logic here
}
@Override
public int hashCode() {
// logic here
}
}
当我在 JBOSS
上部署我的应用程序时,出现以下错误
10:12:30,321 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/cq/event-bus]] (ServerService Thread Pool -- 114) JBWEB000289: Servlet com.something.sdlc.rest.application.MyApplication threw load() exception: java.lang.RuntimeException: Unable to instantiate @Form class. No no-arg constructor.
at org.jboss.resteasy.core.FormInjector.<init>(FormInjector.java:32) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.InjectorFactoryImpl.createParameterExtractor(InjectorFactoryImpl.java:116) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.cdi.CdiInjectorFactory.createParameterExtractor(CdiInjectorFactory.java:51) [resteasy-cdi-3.0.8.Final.jar:]
at org.jboss.resteasy.core.MethodInjectorImpl.<init>(MethodInjectorImpl.java:42) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.InjectorFactoryImpl.createMethodInjector(InjectorFactoryImpl.java:76) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.cdi.CdiInjectorFactory.createMethodInjector(CdiInjectorFactory.java:57) [resteasy-cdi-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodInvoker.<init>(ResourceMethodInvoker.java:100) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodRegistry.processMethod(ResourceMethodRegistry.java:280) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodRegistry.register(ResourceMethodRegistry.java:251) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:221) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:193) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:179) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:156) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodRegistry.addPerRequestResource(ResourceMethodRegistry.java:75) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.spi.ResteasyDeployment.registration(ResteasyDeployment.java:430) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.spi.ResteasyDeployment.start(ResteasyDeployment.java:241) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.init(ServletContainerDispatcher.java:112) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.init(HttpServletDispatcher.java:36) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1194) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1100) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3591) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.catalina.core.StandardContext.start(StandardContext.java:3798) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.jboss.as.web.deployment.WebDeploymentService.doStart(WebDeploymentService.java:161) [jboss-as-web-7.4.0.Final-redhat-19.jar:7.4.0.Final-redhat-19]
at org.jboss.as.web.deployment.WebDeploymentService.access[=13=]0(WebDeploymentService.java:59) [jboss-as-web-7.4.0.Final-redhat-19.jar:7.4.0.Final-redhat-19]
at org.jboss.as.web.deployment.WebDeploymentService.run(WebDeploymentService.java:94) [jboss-as-web-7.4.0.Final-redhat-19.jar:7.4.0.Final-redhat-19]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [rt.jar:1.8.0_77]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [rt.jar:1.8.0_77]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_77]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_77]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_77]
at org.jboss.threads.JBossThread.run(JBossThread.java:122)
为了解决这个问题,我必须包括下面的无参数构造函数。
public EndpointParams () {
}
一旦我将其包含在我的 POJO
中,部署就会成功。
我想知道的是,为什么我需要显式包含无参数构造函数,即使我没有在整个应用程序中使用它?我的应用程序中还有其他几个 POJO,其中 NOT 包含无参数构造函数,并且一切正常。
我想知道在什么情况下,我应该明确指定无参数构造函数。
PS:我正在使用 RestEasy,CDI,JBOSS。
这就是 @Form
/@BeanParam
的工作原理。 RESTEasy 将尝试使用无参数构造它,然后填充属性。它不知道如何调用您的自定义构造函数。它不像其他服务(使用 CDI)甚至反序列化(使用 Jackson)一样通过相同的 DI 系统。使用这两者中的任何一个,都可以创建自定义构造函数。但这些是不同的系统。
您将对象的创建委托给resteasy,它使用Jackson 或Jettison。
我猜这些库正在使用反射来实例化新对象,类似的东西:
EndpointParams object = Class.forName("EndpointParams").newInstance();
然后,它使用您的查询参数调用设置器(由于您的注释):
object.setPageNum(xxx);
object.setPageSize(yyy);
其实我不知道resteasy是怎么猜测pageNum和pageSize的值来使用构造函数的public EndpointParams (int pageNum, int pageSize)
。这可能就是为什么对于此类库来说,不带参数的构造函数是强制性的。
并且,当您定义带参数的构造函数时,默认构造函数(不带参数)被删除:只有在 class 中没有定义其他构造函数时,默认构造函数才存在。在这种情况下,您必须像您所做的那样显式地编写不带参数的构造函数。
我正在写一个POJO
,如下所示。
public class EndpointParams implements Serializable {
private static final long serialVersionUID = -5269761907708414499L;
@QueryParam("pageNum") @DefaultValue("1") private int pageNum;
@QueryParam("pageSize") @DefaultValue("25") private int pageSize;
public EndpointParams (int pageNum, int pageSize) {
this.pageNum = pageNum;
this.pageSize = pageSize;
}
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
@Override
public boolean equals(Object obj) {
// logic here
}
@Override
public int hashCode() {
// logic here
}
}
当我在 JBOSS
上部署我的应用程序时,出现以下错误
10:12:30,321 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/cq/event-bus]] (ServerService Thread Pool -- 114) JBWEB000289: Servlet com.something.sdlc.rest.application.MyApplication threw load() exception: java.lang.RuntimeException: Unable to instantiate @Form class. No no-arg constructor.
at org.jboss.resteasy.core.FormInjector.<init>(FormInjector.java:32) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.InjectorFactoryImpl.createParameterExtractor(InjectorFactoryImpl.java:116) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.cdi.CdiInjectorFactory.createParameterExtractor(CdiInjectorFactory.java:51) [resteasy-cdi-3.0.8.Final.jar:]
at org.jboss.resteasy.core.MethodInjectorImpl.<init>(MethodInjectorImpl.java:42) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.InjectorFactoryImpl.createMethodInjector(InjectorFactoryImpl.java:76) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.cdi.CdiInjectorFactory.createMethodInjector(CdiInjectorFactory.java:57) [resteasy-cdi-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodInvoker.<init>(ResourceMethodInvoker.java:100) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodRegistry.processMethod(ResourceMethodRegistry.java:280) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodRegistry.register(ResourceMethodRegistry.java:251) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:221) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:193) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:179) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:156) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodRegistry.addPerRequestResource(ResourceMethodRegistry.java:75) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.spi.ResteasyDeployment.registration(ResteasyDeployment.java:430) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.spi.ResteasyDeployment.start(ResteasyDeployment.java:241) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.init(ServletContainerDispatcher.java:112) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.init(HttpServletDispatcher.java:36) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1194) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1100) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3591) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.apache.catalina.core.StandardContext.start(StandardContext.java:3798) [jbossweb-7.4.8.Final-redhat-4.jar:7.4.8.Final-redhat-4]
at org.jboss.as.web.deployment.WebDeploymentService.doStart(WebDeploymentService.java:161) [jboss-as-web-7.4.0.Final-redhat-19.jar:7.4.0.Final-redhat-19]
at org.jboss.as.web.deployment.WebDeploymentService.access[=13=]0(WebDeploymentService.java:59) [jboss-as-web-7.4.0.Final-redhat-19.jar:7.4.0.Final-redhat-19]
at org.jboss.as.web.deployment.WebDeploymentService.run(WebDeploymentService.java:94) [jboss-as-web-7.4.0.Final-redhat-19.jar:7.4.0.Final-redhat-19]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [rt.jar:1.8.0_77]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [rt.jar:1.8.0_77]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_77]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_77]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_77]
at org.jboss.threads.JBossThread.run(JBossThread.java:122)
为了解决这个问题,我必须包括下面的无参数构造函数。
public EndpointParams () {
}
一旦我将其包含在我的 POJO
中,部署就会成功。
我想知道的是,为什么我需要显式包含无参数构造函数,即使我没有在整个应用程序中使用它?我的应用程序中还有其他几个 POJO,其中 NOT 包含无参数构造函数,并且一切正常。
我想知道在什么情况下,我应该明确指定无参数构造函数。
PS:我正在使用 RestEasy,CDI,JBOSS。
这就是 @Form
/@BeanParam
的工作原理。 RESTEasy 将尝试使用无参数构造它,然后填充属性。它不知道如何调用您的自定义构造函数。它不像其他服务(使用 CDI)甚至反序列化(使用 Jackson)一样通过相同的 DI 系统。使用这两者中的任何一个,都可以创建自定义构造函数。但这些是不同的系统。
您将对象的创建委托给resteasy,它使用Jackson 或Jettison。
我猜这些库正在使用反射来实例化新对象,类似的东西:
EndpointParams object = Class.forName("EndpointParams").newInstance();
然后,它使用您的查询参数调用设置器(由于您的注释):
object.setPageNum(xxx);
object.setPageSize(yyy);
其实我不知道resteasy是怎么猜测pageNum和pageSize的值来使用构造函数的public EndpointParams (int pageNum, int pageSize)
。这可能就是为什么对于此类库来说,不带参数的构造函数是强制性的。
并且,当您定义带参数的构造函数时,默认构造函数(不带参数)被删除:只有在 class 中没有定义其他构造函数时,默认构造函数才存在。在这种情况下,您必须像您所做的那样显式地编写不带参数的构造函数。