0

In REST, if you want to retrieve a resource, you use something like: http://www.blabla.com/api/movies/1234 where 1234 is the unique identifier of the movie in the database. The question I have how do you retrieve entities from the database that are identified by 2 attributes? Maybe something like: http://www.blabla.com/api/grade/1234/764334532 (identified by the combination of user and exam id) Or perhaps I have to model the database or resources in other way, like adding an id to grades in the database. What do you think? Thanks.

Wain
  • 118,658
  • 15
  • 128
  • 151
Ricardo
  • 2,831
  • 4
  • 29
  • 42

3 Answers3

1

If your exam id is globally unique you can just use that in the URI. no need to reference the user:

http://www.blabla.com/api/exams/123

if the exam id is only locally unique to a user, then you need to include both, as follows:

http://www.blabla.com/api/users/456/exams/123
gilsho
  • 921
  • 7
  • 11
  • Thanks for the suggestion. Problem is that when using that (http://www.blabla.com/api/users/456/exams/123) I don't see very clear that the entity I'm retrieving is a Grade instead of an Exam or User. Does the rest standard say anything about this case? Thanks, is the best answer I have at the moment. – Ricardo May 18 '14 at 10:41
  • REST only instructs you to use resources in your design. The hard part is actually figuring out how to break down your problem domain into these resources. You can decide that a user has exams, and exams have grades, but I doubt that grades will have enough "meat" to justify their own resources. Similarly you can decide that a user has a resource called a reportCard, which displays all of his or her grades for each exam (and this resource would then have links to the exams). If you provide more details about your domain space perhaps I can assist more – gilsho May 18 '14 at 10:45
1

You need to take care that your ressources are addressed uniquely. Below there is an example (JAX-RS) of a customer service which enables users to insert and retrieve recensions to or from a specific product.

/**
 * Abstract service customer. Contains methods for retrieving and persisting
 * data in database.
 */
@Path("/customers")
public interface ServiceCustomer extends Service<Customer, Integer> {

    /**
     * Adds a customers {@link Recension} to a product
     * 
     * @param recension
     *            The new created {@link Recension} by the customer
     * @param customerId
     *            Identifier of the customer as Integer who has created the
     *            recension
     * @param productId
     *            Identifier of the product as Integer which should be
     *            associated with the new created recension
     * @return {@link Response}
     */
    @POST
    @Path("{id}/productId/{prodId}/recension")
    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    public Response insertRecension(Recension recension,
            @PathParam("id") Integer customerId,
            @PathParam("prodId") Integer productId);

    /**
     * Retrieves all customers {@link Recension}(s)
     * 
     * @param customerId
     *            Identifier of the {@link Customer} as int
     * @return {@link Response}, containing a {@link List} of all created
     *         {@link Recension}(s) by the customer
     */
    @GET
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    @Path("{id}/recension")
    public Response getRecensions(@PathParam("id") int customerId);

    /**
     * Retrieves a single {@link Recension} of a {@link Product} which was
     * created by a specific {@link Customer}
     * 
     * @param productID
     *            Identifier of the {@link Product}
     * @param customerID
     *            Identifier of the {@link Customer}
     * @return {@link Response}, which contains the {@link Recension} of the
     *         {@link Product} created by the user. Assuming the user has
     *         created a recension.
     */
    @GET
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    @Path("{id}/productId/{prodId}/recension")
    public Response getRecensionOfProductByCustomer(
            @PathParam("prodId") int productID, @PathParam("id") int customerID);
}
  1. The first method insertRecension is used by a customer to create a recension to a specific product. Hereby you need to define two identifiers, the id of the customer who is creating the recension for the product with the specific id.

    @Path("{id}/productId/{prodId}/recension")

  2. The second method getRecensions is used by a customer to retrieve all his created recensions. For this purpose, the rest- endpoint just needs to know a single identifier, the customers id.

    @Path("{id}/recension")

  3. The last method getRecensionOfProductByCustomer retrieves the recension of a specific product, created by a specific user. Notice, that this rest- endpoint takes two identifiers too!

    @Path("{id}/productId/{prodId}/recension")

My-Name-Is
  • 4,814
  • 10
  • 44
  • 84
0

It's hard to say without more information, but I'd consider a lightweight /grades URI, where each grade is the intersection of an exam and a user:

GET /grades?exam=3&userId=bob
{
    "id": 343,
    "self": "/grades/343",
    "exam": "/exams/3",
    "user": "/users/bob",
    "value": 88
}

You can then easily find all the grades for an exam or a user by only specifying one of the two query parameters.

Eric Stein
  • 13,209
  • 3
  • 37
  • 52