So, I'm coming up to speed on Jersey and have a "best practice" question. How strict should keep the resources self contained in one file. Should one resource class reference another class if needed?
An example:
I have a Person resource and an Appointment Resource. (ie: /Person/1 & /appointment/1234开发者_如何转开发5). I can also do something like /Person/1/Appointments to list all the appointments for person 1.
So, my question is should I implement a method getPersonAppointments() in the Person Resource class, or just someone get a reference to the Appointment resource class and call that method, keeping all the methods which return "Appointments" together.
I don't know that there is a right or a wrong way.
Since an appointment has multiple people, and a person has multiple appointments, the situation is symmetric and you have to pierce the barrier between the Persons and the Appointments.
Your REST API should simplify access to resources. One of the principles of REST is the idea of "Hypermedia as the Engine of Application State," which prefers to direct clients to related resources by their URIs so that the client doesn't need to know about how to construct URIs to certain resources a priori.
More information on that here: http://en.wikipedia.org/wiki/HATEOAS
The request to /person/1 should return information about that person, including a collection of appointment URIs. The client can then request any of those URIs to get information about each of those appointments. Implementing /person/1/appointments is redundant.
In your scenario I would put the logic for loading the appointments for person in one Resource and make it accessible from another Resource (in other words delegating the resource, what I'm assuming you doing already). The actual logic is stored in AppointmentService, so you can use it with your getPersonAppointments().
This way you can call it:
- /person/1/appointments
- /appointments?personId=1
Both resulting into same Response. This is maybe not the best practise, but the logic is in one place and makes it more readable and reusable.
@Path("person")
public class PersonResource {
@GET
@Path("{personId: [0-9]+}/appointments")
public AppointmentsResource loadAppointmentsForPerson(@PathParam("personId") Long personId) {
return new AppointmentsResource(personId);
}
}
@Path("apointments")
class AppointmentResource {
private AppointmentService service;
private Long personId;
public AppointmentResource() {
}
public AppointmentResource(Long personId) {
this.personId = personId;
}
@GET
public Response loadAppointmentsForPerson(@QueryParam("personId") Long personId) {
Long personIdToUse = null;
if (this.personId != null) {
personIdToUse = this.personId;
} else if (personId != null) {
personIdToUse = personId;
} else {
//no input, bad request
}
List<Appointment> appointments = service.getPersonAppointments(personIdToUse)
//create your response from appointments
}
}
Of course in your AppointmentResource, you'll then have another stuff, like loading the appointment by specific ID.
精彩评论