I've recently been working on SWITCHYARD-1500, part of which includes the addition of lifecycle (i.e. start/stop) and metrics (i.e. performance data) support to gateways/bindings. The specific changes can be found in my SWITCHYARD-1500 branches on github (links below), but here's a brief summary:
- start()/stop() have been pushed into a new interface, Lifecycle, which ServiceHandler now extends
- getState() has been added to Lifcycle
Provides the following lifecycle methods:
- start() - re/starting the service handler.
- stop() - stopping the service handler.
- getState() - returns the current state of the service handler.
To start things off, I've choosen the following states:
- NONE - no state, stopped.
- STARTING - the service handler is in the process of starting
- STARTED - the service handler has been started and is capable of Exchange processing
- STOPPING - the service handler is in the process of stopping
- start()/stop() update the state accordingly (e.g. setState(STARTING); setState(STARTED)).
- getState() is implemented.
- a protected setState() is provided so that extenders can update the state appropriately.
Specialized ServiceHandler Implementations: (existing)
Specific component implementations of ServiceHandler update their state within their implementations of start() and stop().
- I'm not sure if we actually need all of these states and I would be happy to reduce the set accordingly.
- I don't believe all component handlers are implemented to be restarted. I'm not sure if I should go through these one by one and update them, or leave the components as they are.
- There is some asymmetry in how some of the component service handlers are implemented (e.g. some components perform some initializtion in the constructor, some in start() and all the teardown in stop(), which prevents restarting).
- Currently it is the responsibility of the extension to update the state as part of their start()/stop() implementation. I would like to consider applying a simple strategy implementation in BaseServiceHandler which does something like: preStart(), doStart(), postStart(), so the components don't have to worry about state management in start stop. I think this would also better support call chaining through the class hierarchy (e.g. super.doStart()), without having to worry about state management.
For metrics support, I've simply injected a GATEWAY_NAME property into the Exchange context. If specified, the ExchangeCompletedEvent handler resolves the named binding on the producer service (or consumer reference) and forwards the event to the binding for inclusion in its aggregated metrics. The problem with this approach is that it requires all inbound handlers to set this property when they create the exchange and it requires all outbound handlers to set this property in handleMessage() (where their processing occurs). I don't particularly like delegating that down into the extensions, but the approach is simple and works (i.e. crude, but effective). Opinions?
I've added a name field to BindingModel, which will be defaulted during Deployment if a name has not already been specified. The format for the default binding name is: _<serviceName.getLocalPart()>_<bindingType>_<index>, e.g. _OrderService_soap_1. In the near future, there will be support within the tools which will allow the user to specify a binding name. (Note, name is already declared as an attribute on sca:Binding, so there were no schema changes required.)
Here are the links to my branches on github: