Using UriBuilder to DRY

UriBuilder can allow you to construct URIs without duplicating the strings you use in the annotations.

 

Suppose you have a public endpoint that exposes customer data based on an id.  Suppose further that some of that customer's data is information about electricity usage for various electric meters the customer may have.  You don't wish to include this (potentially huge amount of) data with the customer meta-data, but want to provide links for each meter's data (and you wish to keep these links out of your API so you can change them later, if you want).

 

Without UriBuilder, you have to repeat various string elements of your URIs across potentially several classes.  UriBuilder can introspect your annotations and do it for you, as follows:

 

 

@Path("meter")
public class ElectricMeter {

  @GET
  @Path("{meter_id}/reads")
  public String getMeterReads(@PathParam String meterId) {
  }
}

@Path("customer")
public class Customer {
  @GET
  @Path("{customer_id}")
  public String getCustomer(@PathParam String customerId) {
    Customer c = getCustomerInfo();
    foreach (String meterId: c.getMeters()) {

      // This initializes the path you are building to the path
      // of the ElectricMeter class
      UriBuilder uriBuilder = UriBuilder.fromResource(ElectricMeter.class);

      // This says to append to this path the pat needed to
      // call the getMeterReads method of the Electric meter class
      uriBuilder.path(ElectricMeter.class,"getMeterReads");

      // The previous call has a URI that has, essentially, the
      // "{meter_id}" placeholder in it; this call
      // substitutes "meterId" for that value; this results
      // in a usable URL to pass back
      String uri = uriBuilder.build(meterId).toString();

      c.getMeterLinks().put(meterId,uri);
    }
    // or whatever you are doing
    return converToJSON(c);
  }
}