Jersey2客户端抛出javax.ws.rs.NotFoundException

时间:2014-03-08 10:35:35

标签: java rest jersey jersey-2.0 jersey-client

我使用Jersey2编写了一个示例REST服务。

这是我的web.xml:

<web-app>
  <display-name>jerseysample</display-name>
    <servlet>
        <servlet-name>Jersey REST Service</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.adaequare.rest.config.JerseyResourceInitializer</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey REST Service</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>

这是我的示例课程:

package com.adaequare.resource;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class Hello {
    @GET
    @Produces(MediaType.TEXT_HTML)
    public String sayHtmlHello(){
        return "<html><title>Hello Jersey</title><body><h1>Hello Jersey</h1></body></html>";
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String sayPlainTextHello() {
        return "Hello Jersey";
    }

    // This method is called if XML is request
    @GET
    @Produces(MediaType.TEXT_XML)
    public String sayXMLHello() {
        return "<?xml version=\"1.0\"?>" + "<hello> Hello Jersey" + "</hello>";
    }

}

我已将其部署到Tomcat,并且能够访问以下URL:

http://localhost:8080/jerseysample/rest/hello

我尝试用这种方式编写单元测试:

package com.adaequare.client;

public class MyResourceTest {
    public static final URI BASE_URI = UriBuilder.fromUri("http://localhost").port(8080).build();
    private HttpServer server;
    private WebTarget target;

    @Before
    public void setUp() throws Exception {

        ResourceConfig rc = new ResourceConfig(Hello.class);
        server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, rc);

        server.start();
        Client c = ClientBuilder.newClient();
        target = c.target(BASE_URI);
    }

    @After
    public void tearDown() throws Exception {
        server.shutdownNow();
    }


    @Test
    public void testGetIt() {
        String responseMsg = target.path("jerseysample").path("rest").path("hello").request().get(String.class);
        System.out.println("I am here");
        assertEquals("Got it!", responseMsg);
    }
}

此类也会抛出异常。

执行此类时,我收到以下异常:

Exception in thread "main" javax.ws.rs.NotFoundException: HTTP 404 Not Found
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:917)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:770)
    at org.glassfish.jersey.client.JerseyInvocation.access$500(JerseyInvocation.java:90)
    at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:671)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:423)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:667)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:396)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:296)
    at com.adaequare.client.TestClient.main(TestClient.java:14)

我确信我缺少一些配置资料。我曾经浏览过这个问题的根本原因,但无济于事。如果我错过了什么,有人可以告诉我吗?

4 个答案:

答案 0 :(得分:2)

您的服务已映射到(并且您说您可以访问它):http://localhost:8080/jerseysample/rest/hello但是使用您的客户端,您正在调用http://localhost:8080/restserver/rest/hello,这是不同的网址。有什么惊喜?

尝试

WebTarget target = ClientBuilder.newClient().target("http://localhost:8080/jerseysample/rest/").path("hello");

至于第二个测试,尝试在WebTarget上调用getUri()来查看实际调用的URL,它应该可以帮助您查看问题所在。

更新后:

首先,您没有指定(就内容协商而言)您的客户接受哪些内容(您在之前的示例中执行了此操作,您删除了该内容)。但这应该不是问题,因为在这种情况下服务器应该向您发送任何已实现的服务器,因为通过不指定它您说明您支持所有类型的响应。但问题可能是将String.class放入get()方法。应该让你希望泽西岛的实体将响应转化为。如果你想获得String,我会做这样的事情:

Response response = target.path("jerseysample").path("rest").path("hello").
      request().get();
StringWriter responseCopy = new StringWriter();
IOUtils.copy((InputStream) response.getEntity(), responseCopy);

但是你无法确定将要调用哪三个方法,因为它位于同一个PATH上,所以你也应该通过将内容传递给request方法来指定内容。

答案 1 :(得分:0)

希望这有助于任何可能遇到同样问题的人。就我而言,我使用Netbeans向导创建了我的Web服务RESTful项目。出于任何原因,我不知道为什么,它错过了包含注释@javax.ws.rs.ApplicationPath(“webresources”)的ApplicationConfig.java类。我不知道为什么当我生成客户端时它向我展示了我期待的正确路径。

所以,我的解决方案是从其他项目中复制另一个ApplicationConfig.java并将我的外观添加到资源中。

答案 2 :(得分:0)

如果您没有配置web.xml来查找其余类,则需要使用@ApplicationPath来指示保留Rest资源的类。

@ApplicationPath("/rest")
public class AplicationRest extends Application
{
  @Override
  public Set<Class<?>> getClasses()
  {
      Set<Class<?>> resources = new java.util.HashSet<>();
      resources.add(com.acme.SomeRestService.class);
      return resources;
  }
}

答案 3 :(得分:-1)

web.xml中存在错误

    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>
            com.adaequare.rest.config.JerseyResourceInitializer
        </param-value>
    </init-param>

请尝试以下

    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>
            com.adaequare.resource.config.JerseyResourceInitializer
        </param-value>
    </init-param>