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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22268158/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 14:37:50  来源:igfitidea点击:

Jersey2 Client throwing javax.ws.rs.NotFoundException

javarestjerseyjersey-2.0jersey-client

提问by Prasanth

I have written a sample REST service using Jersey2.

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

Here is my web.xml:

这是我的 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>

Here is my sample class:

这是我的示例类:

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

}

I have deployed it to Tomcat and am able to access the following URL:

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

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

I tried writing a unit test this way:

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

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

This class also throws the exception.

这个类也会抛出异常。

On executing this class, I am getting the following exception:

在执行这个类时,我收到以下异常:

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.access0(JerseyInvocation.java:90)
    at org.glassfish.jersey.client.JerseyInvocation.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)

I am sure I am missing some configuration stuff. I have browsed to see the root cause of the issue but to no avail. Can someone please let me know if I am missing something?

我确定我错过了一些配置的东西。我已浏览以查看问题的根本原因,但无济于事。如果我遗漏了什么,有人可以告诉我吗?

采纳答案by TondaCZE

Your service is mapped to (and you are saying you can access it): http://localhost:8080/jerseysample/rest/hellobut using your client you are calling http://localhost:8080/restserver/rest/hellowhich is different URL. What is the surprise?

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

Try

尝试

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

As for the second test, try calling getUri() on your WebTarget to see what URL you are actually calling, it should help you see where is the problem.

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

After your update:

更新后:

Well first thing is, you haven't specified (in terms of content negotiation) what content your client accepts (you did this in your previous example, which you deleted). But that should not be a problem since in that case server should send you any of implemented ones since by not specifying it you are stating you are supporting all kind of responses. But the problem probably is putting String.classinto get()method. There should go an entity you want Jersey to transform the response into. If you want to get String I would do something like this:

首先,您没有指定(在内容协商方面)您的客户接受哪些内容(您在之前的示例中已完成此操作,但已删除)。但这应该不是问题,因为在这种情况下,服务器应该向您发送任何已实现的响应,因为如果不指定它,则表明您支持所有类型的响应。但问题可能出String.classget()方法上。应该有一个您希望 Jersey 将响应转换为的实体。如果你想得到 String 我会做这样的事情:

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

But you can't tell for sure which one of your three method is going to be called since it is on the same PATH, so you should also specify the content by passing it to requestmethod.

但是您无法确定将调用三个方法中的哪一个,因为它在同一个 PATH 上,因此您还应该通过将内容传递给request方法来指定内容。

回答by kiran

There is an error in web.xml

web.xml 中有错误

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

please try below

请尝试以下

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

回答by jmoran

Hope this helps anyone who can be facing the same problem. In my case, I created my web service RESTful project with the Netbeans Wizard. By any reason, I didn't know why, it missed the ApplicationConfig.java class which contains the annotation @javax.ws.rs.ApplicationPath("webresources"). I don't know why when I generated the client it showed me the correct path that I was expecting.

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

So, the solution for me was to copy another ApplicationConfig.java from other project and add my facade to the resources.

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

回答by Alisson Gomes

if you don't config web.xml to lookup the rest classes you need use @ApplicationPathto indicate the classes that keep the Rest resources.

如果您不配置 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;
  }
}