I have changed the design or structure somewhat. model/* is highly similar, api/controller is not.

                                         | business logic  |
      +---------------+                  |   multi-level   |
      |  net-facing   |         handle() |   handler       |
  --->|  protocol     |----\------------>| - tree          |
      |  handler      |     \            |     |           |     _____
      |          Q    |      \           |     |           |    /     \
      +---------------+    /----\        |   method()- - - |-->|\_____/|
                  ^       /      \       |     |     \- - -|<--|       |
                   \     |  Bird  |      |     /           |   | store |
                    \-----\ - - -/----<--| - -/            |   |       |
                           \----/  ok()  |                 |    \_____/
                                                    \    _____________
                                                     \--( tailfeather )

The Handler Calling convention

The calling into the handling code was done by means of something like:

       Controller.handleRequest(Request, Response);

Now it is by means of:


A Bird (we can pick another name) is an object (Interface) that knows about the request and the response, and can do that response. It hides the whole lot.

In this model, the single object is passed around from method to method until one method decides to deal with it. Then, that method does the work, and once done, it calls the result method within the Bird. Like this:

    void handlerOne(Bird b)
        if (b.isTypeBlue())
            handlerTwo(b);                    // no, not me, find another method
        else {
            String name = b.getName();        // handle some stuff
            String result = doRedCode(name);
            if (null != result)               // deliver the result
        // note, no returns nor exceptions

There are several advantages to this model:

  1. this sweeps away the assumptions inherent in request-response models. Now, the various alternatives can be hidden in a Bird derivative.
  2. For servlets, servlet/ServletBird will carry the response within.
  3. testing code can create a lightweight Bird, and the business logic won't know any different.
  4. the design does not involve clunky params calling in the forward direction.
  5. Also, it removes any response load direction on the code in the backwards direction. It drops the temptation to use Exception handling. There is no return or exception to send, you have to deliver the result directly into the Bird. End of story.

(This design evolved in my server code for payments systems when demands were made on it over time to do with messaging flows.)

The Handler design

The Handler's internal design is basically a big multi-layer tree switch that just selects on various pieces of info until it finds a method willing to do the job... It's not elegant or structured, but given the REST design, it seems difficult to do anything but. More or less the same as api/Controller was.

I could see for example a big table-driven approach. But that tends to be even less transparent. Hence, it opens questions as to security.

Quite why the handler wants to be a big object following a Handler interface, I am not sure. In my old project it was because there were several handlers doing different things, and one set of startup code ran the lot. So far, I don't see a need for several hendlers in this project, so maybe the need isn't there. But it's easier for me to think this way ;-)

The Store Object

Each handler needs to be given an object that acts as its store.

The benefit is that we can write a lightweight store like UnbackedStore which will simply hold data for the running of the program. This allows good automated testing.

This could be a bit like a Hibernate interface, in that the object can be switched under the handler code without any impact. But I'm not sure here, I've never used Hibernate.

The Store API

The uncertain part for me today is figuring out the store API.

These requirements:

  1. every entity has its own unique, persistent ID
  2. every referring entity holds the ID of any interesting entities (my member holds the ID list for all my assurances)

means that the entire database can be modelled as a network or graph. (We'd need some implementation details: a starting point, an object that is simply a list of references, such as "list of all members," and perhaps an index list, such as "all certs and their members.")

The implication of this is that we can use an object database that simply does that: store objects, and get them indexed by ID. This has quite solid advantages because it (a) matches the OO style, and (b) matches the REST style. And perhaps (c) it is what I did in my last project, and (d) I have an ODB (object database) that does precisely that.

It has the oddity that we can't do selects any more. Something to think about later.

But I'm a bit cautious of going too far along this path. At the moment I see the trick here is to design the store API such that it can reasonably easily handle both models: OO and SQL. Right now, store/ResourceInferface looks ODB only. Also, I'd like to see Hibernate modelled in code, so I can understand its assumptions.


The Model is mostly the same. There are two differences:

Firstly, I've changed the Id to be Rid, our own defined object. I'm pretty convinced we'll need to modify our Id in time... Currently, it is just "hasAString".

Import / Export

We need some way to recover and export the objects into text. Especially for REST, also for the storage in various forms (ODB, Tx and error logging), and for any internal messaging. Preferably this is the same way for all uses. If this is possible then the easiest way might be an interface with input / output in the BirdShackObject. If not, we need some mess of Factories, one for each layout, likely.

There appear to be these options:

  1. XML. Blech.
  2. JSON. OK.
  3. Serialize. Does not guarantee robust semantics over time, it's not meant for persistance, and can break between versions. It's also not easy to examine and prove, for security reasons.
  4. Externalize. Not sure?
  5. Custom. Has a higher load on clients, but ensures better security.

If we can agree on one method for external transport in REST, like JSON, then it might be simple. To that end, I've added an externalise paramater called prepareForFlight(). (Yes, the name can change.) Comes with a constructor like Class(String flight); But this all depends on above, I've not added any JSON code as yet (and don't know how..............).