简体   繁体   中英

How does Jersey / Jax-RS picks the right method in a resource

I am using latest version of Jersey for an API server. I defined the next resource:

@javax.ws.rs.Path("/myPath")
public class MyResource {

  @GET
  @Consumes({MediaType.WILDCARD, MediaType.TEXT_PLAIN, MediaType.TEXT_HTML})
  @Produces(MediaType.TEXT_PLAIN)
  public Response method1(@Context Request request) {
  }

  @GET
  @Consumes(MediaType.APPLICATION_JSON)
  @Produces(MediaType.APPLICATION_JSON)
  public MyObject method2() {}

}

Now lets say I am calling this resource with the next header:

<header>
    <name>Accept</name>
    <value>text/html, application/xhtml+xml, */*</value>
</header>

How does Jersey knows which one to match to in this case where no method Producer annotation is matching? I am asking because one time the server responded to the method2 and after restarting it, it responded to method1.

<header>
    <name>Accept</name>
    <value>text/html, application/xhtml+xml, */*</value>
</header>

I don't know what that it; headers aren't sent in XML, but assuming you sent the header correctly, here's how it's broken down.

@Produces handles the Accept header, and @Consumes handles the client Content-Type header, when the client sends data. So let's look at your two @Produces annotations, against the Accept header

@Produces(MediaType.TEXT_PLAIN)
public Response method1() {}

@Produces(MediaType.APPLICATION_JSON)
public MyObject method2() {}

text/html, application/xhtml+xml, */*

So neither of them have text/html , so cross that out. Neither of them have application/xhtml+xml , so cross that out. That only leaves */* , which means "send me whatever". So Jersey is free to choose which one. The results are unpredictable. You can't make any assumptions about it. And that's the client's fault. Not ours. The client should send the correct header. Or maybe we should do a better job documenting our API, so the client knows what types we can produce :-)

I ran into the same issue, where I have to methods with a specific @Produces() annotations. This trick works:

@Produces(MediaType.APPLICATION_JSON)
public Response method1() {}

@Produces({MediaType.TEXT_PLAIN, "*/*;q=0"})
public Response method2() {}

When using MIME types, you can add the q property, which indicates priority (0 to 1). The absence of the q property implies 1, but apparently the q=0 tricks Jersey to use the other function.

It's kind of a hack, so I don't know if it will remain working, but helped me out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM