Hi, Here's a new proposal for SLING-490, for a service that helps find out when a Sling system is ready to accept requests after startup.
Last discussion (http://markmail.org/thread/4bwmuwj6qnytmrfw) provided some good ideas, but I think this is much better, with low coupling and a possibility for bundles to declare additional required services before they become active, making it easier to have a well defined startup behavior. The idea is to add an implementation of the ServiceWatchdog interface shown below, to the sling engine bundle. See details of the ServiceWatchdog interface below. The sling engine bundle activator calls ServiceWatchdog.addRequiredServices based on configuration values read from BundleContext.getProperty, useful for repository-less setups. The SlingMainServlet calls ServiceWatchdog.getMissingServices(), and returns HTTP status 503 if that's not null. That's the only place where this info is used by Sling itself. As soon as the repository becomes available, before making it available as a SlingRepository service, the AbstractSlingRepository reads an optional list of additional required services from a well-known location in the repository, under /system/required-services for example, I think this solves our previous concerns w.r.t possible race conditions at startup depending on which configuration mechanisms are used: client bundles are free to get the "required services" info from wherever makes sense for them, and the ServiceWatchdog reacts immediately to addRequiredServices calls, by clearing its internal state to force it to be recomputed on the next getMissingServices call. The ServiceWatchdog implementation listens to service events and bundle events, to recompute the list of missing services when needed, and caches that info as long as no such events are received. WDYT? -Bertrand /** Service that watches a specified set of services, * to check that they are all present. */ public interface ServiceWatchdog { /** True if all specified services are present. * That info is cached, so calling this is cheap * unless relevant services and/or bundles events * have been received, causing this to be recomputed. * * @return null if all required services are present. * If services are missing, returns a formatted * string like * <pre> * ID:COUNT:CLAZZ:FILTER * ID:COUNT:CLAZZ:FILTER * ... * </pre> * Where each ID:CLAZZ:FILTER line indicates a set of * services registered with {...@link addRequiredServices) * for which BundleContext.getServiceReferences does not * return the expected number of services. * */ String getMissingServices(); /** Add one or several services to the list of services to watch. * The watchdog calls BundleContext.getServiceReferences with * the specified parameters to find out if the corresponding * services are present. * * @param bundleId clazz and filter are tied to this bundle, * if it is stopped or uninstalled, the corresponding * clazz/filter values are removed from our list. * @param count expected size of the array returned by * BundleContext.getServiceReferences * @param clazz used to call BundleContext.getServiceReferences * @param filter used to call BundleContext.getServiceReferences */ void addRequiredServices(long bundleId, int count, String clazz, String filter); }
