user2093576
user2093576

Reputation: 3092

restful webservice public constructor not found

I am trying to invoke restful webservice using a client web application(simple client request from JSF MB). I need to create an interface for the webservice and then invoke the method in it. But if i use @Path at interface, its giving an error - public constructor not found during Jboss deployment. But If i give give @Path at implementation class. It is invoking the service fine and is working properly. I need to have a Java interface between Rest client and Restful webservice impl classes. Can anyone help? can we have Rest interface or something?

Client side:

ClientRequest request = new ClientRequest("localhost:8080/RESTfulExample/json/...../"); 
ClientResponse<String> response = request.get(String.class);

RestInterface:

package com.nee.interfaces; 
import javax.ws.rs.Path; 
import javax.ws.rs.GET; 

@Path("/OrderManagementService") 
public interface OrderManagementServiceInterface { 
    @GET
    @Path("/GetListOfOrders") 
    void getListOfOrders(); 
}

IMPL:

package com.nee.implementations;
import com.nee.interfaces.OrderManagementServiceInterface;


public class OrderManagementServiceImpl implements OrderManagementServiceInterface {
    public void getListOfOrders() {
        System.out.println("am here");
    }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<context-param>
    <param-name>resteasy.resources</param-name>
    <param-value>
        com.nee.interfaces.OrderManagementServiceInterface
    </param-value>
</context-param>

<!-- this has to match with resteasy-servlet url-pattern -->

<context-param>
    <param-name>resteasy.servlet.mapping.prefix</param-name>
    <param-value>/rest</param-value>
</context-param>

<!-- to return data according to extension -->

<context-param>
    <param-name>resteasy.media.type.mappings</param-name>
    <param-value>json : application/json, xml : application/xml</param-value>
</context-param>

<listener>
    <listener-class>
        org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
    </listener-class>
</listener>

<servlet>
    <servlet-name>resteasy-servlet</servlet-name>
    <servlet-class>
        org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
    </servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>resteasy-servlet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>

Logs:

[org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/web]]
(MSC service thread 1-2) Exception sending context initialized event to listener instance of class
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap: java.lang.RuntimeException: Unable to find a public constructor for class com.seagate.interfaces.OrderManagementServiceInterface
at org.jboss.resteasy.plugins.server.resourcefactory.POJOResourceFactory.registered(POJOResourceFactory.java:35) [resteasy-jaxrs-2.3.3.Final-redhat-1.jar:2.3.3.Final-redhat-1]
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:120) [resteasy-jaxrs-2.3.3.Final-redhat-1.jar:2.3.3.Final-redhat-1]
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:106) [resteasy-jaxrs-2.3.3.Final-redhat-1.jar:2.3.3.Final-redhat-1]
at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:83) [resteasy-jaxrs-2.3.3.Final-redhat-1.jar:2.3.3.Final-redhat-1]
at org.jboss.resteasy.core.ResourceMethodRegistry.addPerRequestResource(ResourceMethodRegistry.java:72) [resteasy-jaxrs-2.3.3.Final-redhat-1.jar:2.3.3.Final-redhat-1]
at org.jboss.resteasy.spi.ResteasyDeployment.registration(ResteasyDeployment.java:383) [resteasy-jaxrs-2.3.3.Final-redhat-1.jar:2.3.3.Final-redhat-1]
at org.jboss.resteasy.spi.ResteasyDeployment.start(ResteasyDeployment.java:225) [resteasy-jaxrs-2.3.3.Final-redhat-1.jar:2.3.3.Final-redhat-1]
at org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap.contextInitialized(ResteasyBootstrap.java:28) [resteasy-jaxrs-2.3.3.Final-redhat-1.jar:2.3.3.Final-redhat-1]
at org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:3392) [jbossweb-7.0.16.Final-redhat-1.jar:]
at org.apache.catalina.core.StandardContext.start(StandardContext.java:3850) [jbossweb-7.0.16.Final-redhat-1.jar:]
at org.jboss.as.web.deployment.WebDeploymentService.start(WebDeploymentService.java:90) [jboss-as-web-7.1.2.Final-redhat-1.jar:7.1.2.Final-redhat-1]
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)[rt.jar:1.7.0_09]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [rt.jar:1.7.0_09]
at java.lang.Thread.run(Unknown Source) [rt.jar:1.7.0_09]

Upvotes: 2

Views: 4787

Answers (2)

user2093576
user2093576

Reputation: 3092

There is simple answer to the above problem. In web.xml, instead of interface, i just had to configure IMPL class instead of interface and continue setting @Path at interface

<context-param>
    <param-name>resteasy.resources</param-name>
    <param-value>
        com.seagate.implementations.OrderManagementServiceImpl
    </param-value>
</context-param>

AND IT WORKED :)...

Upvotes: 1

christian.vogel
christian.vogel

Reputation: 2147

I guess your mistake is that you give an interface to RestEasy and the framework is trying to create an instance of it via reflection. Something like that will never work. Instead of the interface you should only specify implementation classes as a value for the parameter resteasy.resources. If you want to to be more dynamically try a combination of OSGi and REST. I didn't tried the example in this blog for myself, but you can have a look on that.

UPDATE

As you want to use your service from third party classes as well, why not wrap another interface with your REST webservice and that wrapped interface could be used in your third party classes. The webservice is then only use to delegate requests to a specific implementation of this interface. You can inject the implementation via a Dependency Injection framework like Spring, Google Juice or something else. Here is what I mean:

Your interface as an abstraction for your implementations:

interface IExecutionService {
   void executeStuff();
}

Then your REST Service:

@Path("/OrderManagementService")
class ExectionServiceDelegator {

   private IExecutionService wrappedServiceInterface;

   /**
    * play around with some DI frameworks for injecting your implementation
    */
   public void setIExecutionService(IExecutionService service) {
      wrappedServiceInterface = service;    
   }

   @GET
   @Path("/GetListOfOrders") 
   public void doingSomething() {
      service.executeStuff();
   }
}

You can use the interface IExecutionService in combination with a specific DI framework in your third party interfaces as well. Hope it's clear what I'm trying to do with the code above?!

Upvotes: 1

Related Questions