RITZ XAVI
RITZ XAVI

Reputation: 3799

java.lang.RuntimeException: Unable to instantiate @Form class. No no-arg constructor

I am writing a POJO as shown below.

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
    }
} 

When I deploy my application on JBOSS, I get the below error

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$000(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$1.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)

In order to solve this issue I have to include the no-args constructor as below.

public EndpointParams () {
}

Once I include this in my POJO, the deployment succeeds. What I want to know is, why do I need to explicitly include the no-args constructor even though I am not using it in my entire application ? I have several other POJOs in my application where I have NOT included the no-arg constructor and everything works well. I want to know under what circumstances, I should explicitly specify the no-arg constructor.

PS: I am using RestEasy, CDI, JBOSS.

Upvotes: 1

Views: 3760

Answers (2)

Val Bonn
Val Bonn

Reputation: 1199

You delegate the creation of the objects to resteasy, which uses Jackson or Jettison.

I guess these libraries are using reflection to instantiate the new objects, something like that :

EndpointParams object = Class.forName("EndpointParams").newInstance();

and then, it calls the setters with the parameters of your query (because of your annotation):

 object.setPageNum(xxx);
 object.setPageSize(yyy);

In fact, I do not know HOW resteasy would guess the values of pageNum and pageSize to use the constructor public EndpointParams (int pageNum, int pageSize). That's probably why a constructor with no parameter is mandatory for such kind of libraries.

And, as you defined a constructor with parameters, the default constructor (without parameters) is removed : The default constructor exists only if there is no other constructor defined in the class. In this case, you have to write explicitly the constructor without parameters, just as you did.

Upvotes: 0

Paul Samsotha
Paul Samsotha

Reputation: 209012

This is just how it works for @Form/@BeanParam. RESTEasy will try to construct it using the no-arg, and then populate the properties. It doesn't know how to call your custom constructor. It doesn't go through the same DI system like other services (with CDI) or even deserialization (with say Jackson). With either of these two, custom constructor creation is allowed. But these are different systems.

Upvotes: 4

Related Questions