Re: Alternate API proposition

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Wed, 25 Apr 2007 19:11:17 +0200

Jerome Louvel wrote:
> Hi all,
> As promised, I've worked on a sample application (based on BlinkSale API)
> that illustrates some of the ideas I have in mind for this JSR API.
> The Javadocs and source code should be self explaining, but I can detail
> more if needed.

Quick question: is the use of @ResourceRef with the Account and Invoice
classes a mistake? namely is it part of an old design, or is it
something you intended?

The reason i ask is if it is indeed intended then i think it a mistake
:-) but i don't want to send unnecessarily detailed emails saying why i
think this the case if this is part of an old design.

> The idea is to provide a sketch that can illustrates my point of view and
> triggers some discussions. It doesn't pretend to be a complete solution, but
> it does seem to provide the main pieces to implement an API such as
> BlinkSale. Note that I haven't fully covered the BlinkSale resources yet,
> but the design pattern should be obvious.

In the interests of comparing i have included POJOs for clients/client
(at the end of the email) that follow the same pattern as the previous
one for invoice/invoices (which are also included). I also included a
base resource to obtain the account ID.

AFAICT the main differences in terms of resource POJOs are:

1) the degree of separation between resource and representation POJOs;

2) static vs. dynamic for recursive matching based on URI templates;

3) the inheritance rules for HTTP methods of resource POJOs;

4) the explicit/implicit declaration of HTTP methods of resource POJOs;

In further separate emails (most likely not today!) i will try and pick
out some of the differences in more detail.


public abstract class BaseResource {
     protected String accountId;

     private @HttpContext UriInfo info;

     public BaseResource() {
         this.accountId = getAccountId(info.getUri().getHost());

     private String getAccountId(String host) {
         return host.substring(0, host.indexOf("."));

class ClientsResource extends BaseResource {

    public Collection<Client> getClients() { ... }

    public Response post(Client client) { ... }


public class ClientResource extends BaseResource {

    int clientId;

    public ClientResource(@UriParam("client_Id") int clientId) {
       this.clientId = clientId;
       if (clientId > 0)
          throw new NotFoundException("Client ID not found");

    public Client getClient() { ... }

    public void delete() { ... }

    public void put(Client client) { ... }

    public PeopleResource getPeopleResource () {
        return new PeopleResource(accountId, clientId);

class InvoicesResource extends BaseResource {

     Date start, end;
     String status, tags;

     public InvoicesResource(
          @QueryParam("start") Date start,
          @QueryParam("end") Date end,
          @QueryParam("status") String status,
          @QueryParam("tags") String tags)

     Collection<Invoice> getInvoices() { ... }

     Feed getInvoicesAsFeed() { ... }

     Calendar getInvoicesAsCalendar() { ... }

     Response postInvoice(Invoice i) { ... }

class InvoiceResource extends BaseResource {

     int id;

     public InvoiceResource(
          @UriParam("invoice_Id}" int id) {
        if (id not recognized)
          throw NotFoundException(...); = id;

     Invoice getInvoice() { ... }

     Entry getInvoiceAsEntry() { ... }

     void putInvoice(Invoice i) { ... }

     void deleteInvoice() { ... }

     DeliveriesResource getDeliveriesResource () {
         return new DeliveriesResource(accountId, i);

     PaymentsResource getPaymentsResource () {
         return new PaymentsResource(accountId, i);

| ? + ? = To question
    Paul Sandoz