JAX-RS exception: Annotated with GET of resource,

2020-03-25 06:52发布

问题:

I am using the jersey implementation of JAX-RS for the web service. I am very new to this JAX-RS.

I am trying to add a method in the service which accept an Employee object and returns the employee Id based on the Employee object values (there is a DB hit for this).

Following the Restful principles, I made the method as @GET and provided the url path as shown below:

@Path("/EmployeeDetails")
public class EmployeeService {
@GET
@Path("/emp/{param}")
public Response getEmpDetails(@PathParam("param") Employee empDetails) {

    //Get the employee details, get the db values and return the Employee Id. 

    return Response.status(200).entity("returnEmployeeId").build();

}
}

For testing purpose, I wrote this Client:

public class ServiceClient {

public static void main(String[] args) {

    ClientConfig config = new DefaultClientConfig();
    Client client = Client.create(config);
    WebResource service = client.resource(getBaseURI());

    Employee emp = new Employee();
    emp.name = "Junk Name";
    emp.age = "20";
    System.out.println(service.path("rest").path("emp/" + emp).accept(MediaType.TEXT_PLAIN).get(String.class));

}

private static URI getBaseURI() {
    return UriBuilder.fromUri("http://localhost:8045/AppName").build();
}

}

When I run it, I am getting the error: Method, public javax.ws.rs.core.Response com.rest.EmployeeService.getEmpDetails(com.model.Employee), annotated with GET of resource, class com.rest.EmployeeService, is not recognized as valid resource method.

Edit:

Model:

package com.model;

public class Employee {

public String name;
public String age;

}

Please let me know where is the issue, I am a beginner in this and struggling to understand the concepts :(

回答1:

JAX-RS cannot automatically convert a @PathParam (which is a string value), into an Employee object. Requirements for objects that can be automatically created from a @PathParam are:

  1. String (defacto, because the data is already a string)
  2. Objects with a constructor that accepts a (single) string as argument
  3. Objects with a static valueOf(String) method

For cases 2 & 3 the object would be required to parse the string data and populate its internal state. This is not normally done (because it forces you to make assumptions about the content type of the data). For your situation (just beginning to learn JAX-RS), its best to just accept the incoming @PathParam data as a String (or Integer, or Long).

@GET
@Path("/emp/{id}")
public Response getEmpDetails(@PathParam("id") String empId) {
    return Response.status(200).entity(empId).build();
}

Passing a complex object representation to a REST service in a GET method doesn't make much sense, unless its being used, eg, as a search filter. Based on your feedback, that is what you are trying to do. I've actually done this on a project before (generic implementation of search filters), the one caveat being that you need to strictly define the format of the search data. So, lets define JSON as the accepted format (you can adapt the example to other formats as needed). The 'search object' will be passed to the service as a query parameter called filter.

@GET
@Path("/emp")
public Response getEmployees(@QueryParam("filter") String filter) {
    // The filter needs to be converted to an Employee object. Use your
    // favorite JSON library to convert. I will illustrate the conversion
    // with Jackson, since it ships with Jersey
    final Employee empTemplate = new ObjectMapper().readValue(filter, Employee.class);

    // Do your database search, etc, etc
    final String id = getMatchingId(empTemplate);

    // return an appropriate response
    return Response.status(200).entity(id).build();
}

And in your client class:

final String json = new ObjectMapper().writeValueAsString(emp);
service
    .path("rest")
    .path("emp")
    .queryParam("filter", json)
    .accept(emp, MediaType.TEXT_PLAIN)
    .get(String.class)


回答2:

I got the same issue but I just fixed it jersey jars used in your application should have same versions.



回答3:

It's quite strange that you want to serialize an entity (Employee) into an url path segment. I'm not saying it's impossible, but strange, and then you have to make sure that the Employee class satisfies the following criteria (which is from the javadoc of @PathParam)

The type of the annotated parameter, field or property must either:
... (irrelevant part)
Have a constructor that accepts a single String argument.
Have a static method named valueOf or fromString that accepts a single String argument (see, for example, Integer.valueOf(String)).

You might want to pass the Employee object in the request body raher than in a path param. To chieve this, annotate the Employee class with @XmlRootElement,remove the @PathParam annotation from the method's empDetails argument, and change @GET to @POST.