Chapter 6. Dynamic Services

This chapter addresses the notion that bundles and services can come and go throughout the lifetime of a running system. Dynamic behavior is one of the hallmarks of OSGi-based systems and is central to many of the design and implementation decisions you make. Here we present three mechanisms for dealing with the dynamic nature of services: OSGi’s Service Trackers, a third-party mechanism called the Service Activator Toolkit (SAT), and finally OSGi’s Declarative Services.

The goals of this chapter are to

• Modify the bundle activators in Toast to use OSGi Service Trackers so they can handle dynamic services

• Present the Service Activator Toolkit as a very simple way to write bundle activators that handle dynamic services

• Present OSGi’s Declarative Services and adopt it as the mechanism to be used throughout the remainder of Toast development

6.1 Introduction to Dynamic Services

At the end of Chapter 5, “Services,” we had Toast implemented in terms of services but noted that the system may not work depending on the order in which the bundles are started. Ironically, this is a symptom of the power of OSGi. OSGi systems are loosely coupled and may not have a central thread of control—they are composed of cooperating functional pieces, or services. These services have to discover each other and cannot depend on one being installed and started before the other.

While it is possible to use OSGi’s StartLevel service to control the order in which bundles are started, it is not a recommended practice. As the number of bundles in the application increases, the start order interdependencies become complex, and this approach becomes a maintenance nightmare. The StartLevel service is discussed in more detail in Section 21.7.1, “Start Levels.”

A better approach is to make our application independent of bundle start order altogether. OSGi provides several mechanisms for achieving this. First, the framework fires service events as bundles register and unregister services. Using service listeners, a bundle can receive these events and track the services it requires. When all the services are available, the activator can acquire them and start its operation—perhaps registering even more services. This approach requires a fair amount of complex code to handle concurrency and the varying order in which services come and go. As such we do not cover it in detail here.

The complexity of service listeners and the fact that this was the only option in early releases of OSGi gave rise to third-party frameworks such as the Service Activator Toolkit (SAT). SAT provides an abstract BundleActivator with a set of helper methods that listen and react to service events. Using SAT, an application inherits the complex functionality it needs to properly handle the coming and going of services.

Since those early days, OSGi has evolved two additional mechanisms for dealing with dynamic services: Service Trackers and Declarative Services. This chapter covers both of these mechanisms and gives you a chance to try them in the Toast sample application.

The Evolution of the OSGi Service Model

Services are an inherent part of the overall OSGi architecture and have been there from the beginning. Over time the facilities around services have evolved.

Release 1: service registration and event listening—The initial release of the OSGi specification provided service registration and listening APIs as the way to work with the OSGi service model. This typically required the bundle developer to create and register services in the bundle’s activator. A bundle requiring another service adds a service event listener and responds to service registration, unregistration, and modification events fired by the OSGi framework.

Release 2: Service Tracker—Release 2 of the OSGi specification introduced the Service Tracker. As the name implies, a Service Tracker tracks the addition, removal, and modification of services being used by a bundle and eliminates much of the duplicate listener code and race conditions.

Release 4: Declarative Services—Release 4 of the OSGi specification introduced Declarative Services, which makes handling the dynamic acquisition and release of services easier for bundle developers by eliminating all service management code. In addition, using Declarative Services makes using OSGi services more scalable by delaying class loading and object creation. See Chapter 15, “Declarative Services,” and Chapter 24, “Declarative Services Reference,” for coverage of Declarative Services.

6.2 Using Service Trackers

A Service Tracker, as the name implies, is a mechanism for tracking the comings and goings of services matching a specification. At any point you can ask a Service Tracker to give you the service objects it is tracking. Service Trackers are highly customizable and can be made to update the state of other services based on the changes they see. In this chapter we refactor the emergency monitor’s bundle activator to use Service Trackers and show how they are used to make Toast safely dynamic. We also examine the advantages and disadvantages of this approach.

In this section we suggest that you load the sample code for “Chapter 6.2 Service Tracker” using the Samples Manager and read along rather than trying to do the modifications manually. There are a number of changes and we are really just trying to illustrate the use of Service Trackers.

6.2.1 Modifying the Bundle Activator

All of the changes needed to use Service Trackers happen in the emergency monitor’s bundle activator in org.equinoxosgi.toast.client.emergency.bundle. The following code snippet shows the entire content of the new activator class. Following that is a description of the changes.

image

image

image

Notice that, as before, the start method begins by instantiating the EmergencyMonitor. Then, instead of trying to acquire the GPS and airbag services directly, it creates a ServiceTracker for each. When the required airbag and GPS services are available, the trackers call bind and the emergency monitor’s setGps, setAirbag, and startup methods. To be safe, bind and unbind are called from inside synchronized blocks to make sure that service changes are handled atomically.

The new stop method simply closes the two Service Trackers. Since a Service Tracker is implemented using service event listeners, it is important that they be closed. Failure to close the trackers results in listener leaks. See Chapter 22, “Dynamic Best Practices,” for more information on leaks and other issues as a result of dynamic behavior. Note that closing a tracker causes its tracked services to be removed and thus the emergency monitor to be unbound.

The big change in the activator comes in the creation of the ServiceTracker and ServiceTrackerCustomizer objects. The key here is in the ServiceTrackerCustomizers. These are a means of adding lifecycle functionality to the trackers. The customizers in this example react to IAirbag and IGps services coming and going by triggering the binding or unbinding of the emergency monitor as appropriate. A customizer has to handle special cases, for example, where there are multiple instances of the same service type. When unbinding one service instance, there may be alternative service implementations of the same type—the customizer should try to rebind to ensure uninterrupted execution. Similarly, it must ensure that it deactivates and unbinds the emergency monitor only when the service in use is removed, not just when services are removed.

The activator creates two Service Trackers, one for each of the IAirbag and IGps services, and each Service Tracker has its own customizer. Each Service Tracker is opened, causing it to start listening to the relevant events from the OSGi framework.

6.2.2 Launching

The Service Tracker–based version of Toast is ready to run:

• Select Run > Run Configurations... from the menu bar.

• Select the Toast run configuration from beneath OSGi Framework in the list at the left.

• Finally, click the Run button.

You should see the following output on the Console view, repeating every five seconds:

image

Toast runs every time now, regardless of the bundle start order, because the bundle activator uses Service Trackers to defer starting the emergency monitor until it has successfully acquired both the GPS and the airbag services. To play around with how this works, try manually stopping and restarting the various services in the application:

• In the Console view, press Enter to see the osgi> prompt. Then type the ss command to display a short status of the installed bundles. You should see the following output, although the bundle IDs and the order of the bundles might not be the same:

image

• Stop the airbag bundle by typing stop 4 at the prompt. (Note that the ID number for the airbag may be different for you.) Stopping the bundle triggers its activator’s stop method, causing it to stop and unregister the airbag service. As a result, the airbag no longer deploys every five seconds and the emergency monitor is unbound. To confirm that the services are gone, type bundle 4 and note that the list of registered services is empty.

• Restart the airbag bundle by typing start 4 at the prompt. The bundle’s activator starts and registers the airbag service, thus satisfying the dependencies of the emergency monitor bundle. As a result, an emergency monitor is created and registered as a listener of the airbag service. At this point you will see the airbag deploying again every five seconds. To confirm that the service is back, type bundle 4 and note the airbag service in the list of registered services.

• Stop the GPS bundle by typing stop 1. Here the GPS service is unregistered, in turn causing the emergency monitor to be unbound until a GPS service is reregistered. Note that the airbag service continues as usual, deploying and notifying its listeners every five seconds. Since the emergency monitor has removed itself as a listener, there is no response to the deployment of the airbag.

• Restart the GPS bundle by typing start 1. This causes a GPS service to be registered and the requirements of the emergency monitor to be satisfied. The emergency monitor starts up and adds itself again as a listener of the airbag. The emergency notifications start appearing again on the console.

• Terminate the OSGi framework by typing close at the prompt or by pressing the Stop button at the top of the Console view to terminate the OSGi framework.

6.2.3 Service Tracker Summary

Service Trackers are a nice abstraction of the service management requirements. Even with this relatively simple example, however, it is apparent that writing a customizer is quite complicated. In fact, while putting together the code for this section, the authors and other experts went through several iterations attempting to perfect the code. No matter what we did, a good balance of simplicity and scalability could not be found. For example, in the code presented here, acquiring more than just two services requires the addition of several conditionals across several methods. It’s very easy to get this code wrong, and testing, fixing, and verifying such changes is a chore.

Service Trackers can, however, be useful when getting and using services periodically throughout your code. Many OSGi developers use Service Trackers in an à la carte manner to acquire services whenever they may be needed—trackers help by doing all the accounting for you and giving you easy access to the service object. This is simple and useful but has the downside that it forces references to OSGi into your application’s domain logic. This in turn ties your implementation to OSGi such that it cannot be run or tested in a non-OSGi environment. In keeping with our POJO style, using Service Trackers outside the bundle activator is not a recommended practice.

All in all, Service Trackers are a somewhat less than optimal solution for handling dynamic bundles.

6.3 Using the Service Activator Toolkit

Long before OSGi provided Declarative Services or even the Service Tracker, listening to service events was the only way to handle dynamic services. A bundle activator that thoroughly handled dynamic services was an impressive, if difficult-to-maintain, piece of code. From this complexity the Service Activator Toolkit (SAT) was born.

SAT is not a framework, but rather it provides an abstract bundle activator that your bundle activator can subclass. This allows you to reuse the complex but well-tested service listener behavior rather than implementing and maintaining it yourself. SAT also provides some tooling for the initial construction of your bundle activators as well as for the runtime analysis of your bundles.

6.3.1 Installing SAT into the Target Platform

Before we can use SAT, we must add it to the target platform. If you followed our recommendation in Chapter 3, “Tutorial Introduction,” and loaded the predefined target, you can follow the steps given here. If you built your own target, we recommend you return to Chapter 3, “Tutorial Introduction,” and load the predefined target before continuing.

• Open the toast.target file in the ToastTarget project.

• On the Definition tab, click the Add... button to add a location.

• In the Add Content dialog, choose Directory from the list and click the Next button.

• Type ${workspace_loc}/ToastTarget/org.eclipse.soda.sat/eclipse as the location and click Finish.

• Save the contents of the editor.

• Click the Set as Target Platform link in the top right corner of the editor.

To apply the SAT approach to Toast, we need to tweak the bundle activators from Chapter 5, “Services,” to use the SAT abstract BaseBundleActivator and take advantage of its facilities. The following code snippets and explanations walk you through that process. The final code for this section is in the sample called “Chapter 6.3 SAT” in the Samples Manager. Note that to see the changes, you must compare this new code to that of Chapter 5, “Services,” as the changes here are not based on the Service Tracker work of the previous section.

6.3.2 Modifying the GPS Bundle Activator

As you may recall, the GPS bundle is at the bottom of the food chain. As such, all we have to do is create and supply the GPS service when the bundle is activated. Before we modify the bundle activator, however, we first need to make the core SAT bundle visible to the GPS bundle:

• Open the GPS bundle’s manifest and add org.eclipse.soda.sat.core to the list of bundles under Automated Management of Dependencies on the Dependencies tab.

• Save the bundle manifest editor.

• Now update the activator to match the following snippet:

image

• Run Organize Imports before saving this file.

The main change is the addition of the activate method. This method is called by SAT when the activator has acquired its required imported services. SAT hooks into the OSGi lifecycle by implementing start and stop and then calling activate when all the stated constraints are met and deactivate when the constraints cease to be satisfied. Since the GPS bundle is at the bottom of the food chain, there are no constraints, and activate can be called immediately.

6.3.3 Modifying the Airbag Bundle Activator

The airbag bundle activator is a little more interesting in that the airbag service needs to be started via its startup method so that it can deploy periodically and stopped via its shutdown method when the bundle is stopped. You’ll need to repeat the same steps listed in the preceding section to add the SAT core bundle to the airbag bundle’s dependencies. Then update the airbag activator to match the following snippet:

image

6.3.4 Modifying the Emergency Monitor Bundle Activator

Finally, the emergency monitor is at the top of the food chain and so needs to specify some service dependencies. These dependencies must be satisfied before the emergency monitor is started. Again, don’t forget to repeat the steps listed in the earlier GPS section to add the SAT core bundle to this bundle’s dependencies. Then update the activator as outlined here:

image

The key to this activator is the getImportedServiceNames method. This is called by the SAT infrastructure and must return an array containing the fully qualified type names of the services that the bundle requires. SAT then ensures that services matching these names are acquired from the service registry before calling activate. While the activate method is executing, you can be assured that all the required imported services are available.

Conversely, the deactivate method is called when one of the acquired services is being unregistered with the service registry. Upon returning from deactivate, the SAT infrastructure attempts to reacquire the lost service, which, if successful, will cause the activate method to be called once more.

In effect, these few methods replace the use of the ServiceTracker and the ServiceTrackerCustomizer from Section 6.2.

6.3.5 Launching

Running the SAT version of Toast is very much like all other cases. Here, of course, you must ensure that the SAT core bundle is in the launch configuration:

• Select Run > Run Configurations... from the menu bar.

• Select the Toast run configuration from beneath OSGi Framework in the list at the left.

• Add the bundles org.eclipse.osgi.services and org.eclipse.soda.sat.core to the launch. You’ll need to uncheck the Only show selected bundles option to add more bundles. Then you can find them under the Target Platform heading in the bundles list.

• Click the Run button.

You should see the familiar output on the Console view:

image

If you like, you can experiment with stopping and starting the various bundles as in the previous section. When you are done, remember to terminate the OSGi framework before moving on. Type the close command into the Console view or press the Stop button at the top of the view.

6.3.6 SAT Summary

As you can see, the bundle activator code is significantly simpler with SAT when compared to the original implementation or even the Service Tracker implementation. SAT does a rigorous job of safely activating and deactivating your application bundles based on the availability of the services they need to acquire.

Among its other benefits, SAT provides support for optional services, managed services, managed service factories, and even for delayed creation of domain logic using proxies. SAT comes with a rich set of tooling, including a bundle activator wizard that could have helped with the conversions you just did, as well as some useful runtime tooling to help you analyze the dependencies that bundles have on other bundles.

SAT does introduce some modest performance overheads. For example, it requires a certain amount of work per bundle at startup time. Specifically, even if a bundle’s required services are not available, SAT must still load and run the bundle activator to make that determination. Therefore, for very large applications with thousands of bundles, many of which are not active initially, SAT is less than optimal.

At the other end of the spectrum, developers of tiny systems may balk at adding more “utility” bundles to their configurations. SAT’s physical footprint is quite modest, and if you are going to write a well-behaved dynamic system of any complexity, you are going to have multiple copies of similar code. At a certain point you win by having just one general-purpose, well-tested implementation.

On the whole, SAT is quite useful and offers very real improvements over using Service Trackers. You should consider using SAT for systems with bundles numbering in the hundreds, especially those whose bundles are likely to be started anyway.

6.4 Using Declarative Services

Release 4 of the OSGi specification brought an altogether new way to solve the dynamic services issue—Declarative Services (DS). Having just read the SAT section of this chapter, you might consider DS to support a declarative form of the SAT getImportedServiceNames and addExportedService methods; that is, DS is a way for a bundle to declare, in an XML file, the services it provides and references. DS binds and unbinds these services at the appropriate time.

Because Declarative Services is—as the name implies—declarative, no bundle code needs to be loaded to determine whether a bundle’s prerequisites have been met. In fact, bundles that use DS generally do not need to have an activator at all.

Chapter 15, “Declarative Services,” and Chapter 24, “Declarative Services Reference,” discuss Declarative Services in detail. In this section we look at using DS in our prototype Toast application. As with the SAT example, start with the code from the sample for Chapter 5, “Services,” and for each of our three bundles update the activator and associated files. The final code for this section is in the sample called “Chapter 6.4 Declarative Services” in the Samples Manager. Note that to see the changes, you must compare this new code to that of Chapter 5, “Services,” as the changes here are not based on the Service Tracker or SAT work of the previous sections.

6.4.1 Modifying the GPS Bundle

The GPS bundle is a great place to start because it is the simplest of the bundles and it lies at the bottom of the food chain.

DS works in terms of components. A component is an entity that references zero or more services and provides zero or more services. A component consists of two parts: an XML file describing the DS component and the services that it references and provides, and a class that implements the component’s provided services and receives referenced services.

As a convention, the XML file that describes the component is called component.xml and is located in the bundle in a folder called OSGI-INF. Carry out the following steps to add the component specification to the GPS bundle:

• Select the GPS project and choose New > Other... from the context menu. Under Plug-in Development, select Component Definition and press Next.

• For the folder name, use org.equinoxosgi.toast.dev.gps/OSGI-INF. This creates a folder inside the project where the component.xml file will reside.

• Use the default file name of component.xml.

• Press the Browse... button, start typing FakeGps for the class of the component, select it once it appears in the list, and press Finish.

The tooling generates a file called component.xml in the OSGI-INF folder and opens an editor as show in Figure 6-1.

Figure 6-1 Declarative Services editor

image

Poke around in the editor and make the following modification to expose the bundle’s GPS implementation as a service:

• On the Services tab, press the Add... button in the Provided Services section, and type in IGps for the interface name. Press OK.

• Save the contents of the editor.

Now look on the Source tab of the editor where you can see the contents of the generated component.xml file. It should look like this:

image

Notice that the implementation class is the fully qualified name of the FakeGps class. Also notice that this bundle provides the IGps interface, given by its fully qualified name.

With the component.xml complete, all that remains is to update the bundle to delete the activator, tell DS where to find the component description file, and ensure that the new files are included in the build:

• Starting on the Overview tab of the bundle manifest editor for the GPS bundle, select and delete the previous bundle activator from the Activator field.

• On the Dependencies tab, remove org.eclipse.soda.sat.core.framework from the list of Imported Packages.

• Also remove org.eclipse.soda.sat.core from the list of Automated Management of Dependencies.

• On the MANIFEST.MF tab, notice that the DS tooling already added the Service-Component header to declare the location of the component.xml file.

• On the Build tab, in the Binary Build section, notice that the DS tooling already checked the box beside the OSGI-INF folder to include the component.xml in the build of the bundle.

• Save the contents of the manifest editor.

• Finally, delete the package that contains the old bundle activator: org.equinoxosgi.toast.internal.dev.gps.fake.bundle. The bundle no longer has any OSGi-specific code.

6.4.2 Modifying the Airbag Bundle

Updating the airbag bundle to use DS follows largely the same set of steps: Add the component.xml, create the component implementation of IAirbag, and update the manifest definition. These steps are detailed here:

• Select the airbag project and choose New > Other... from the context menu. Under Plug-in Development, select Component Definition and press Next.

• For the folder name, use org.equinoxosgi.toast.dev.airbag/OSGI-INF.

• Press the Browse... button, start typing FakeAirbag for the class of the component, select it once it appears in the list, and press Finish.

• Once the editor opens on component.xml, fill in startup and shutdown for the Activate and Deactivate fields, respectively.

• On the Services tab, press the Add... button in the Provided Services section, and type in IAirbag for the interface name. Press OK.

• Save the contents of the editor.

• Delete the package that contains the bundle activator, since it is no longer needed.

• Finally, remove the bundle activator reference from the bundle manifest itself on the Overview tab, and remove the two SAT references from the Dependencies tab.

Look on the Source tab of the editor where you can see the contents of the generated component.xml file. It should look like this:

image

Notice that the activate and deactivate attributes of this component refer to the startup and shutdown methods on FakeAirbag. In this case, the startup method is called by DS when another component requests the service provided by this component. The deactivate method is called when the bundle is stopped.

6.4.3 Modifying the Emergency Bundle

Finally, let’s adapt the emergency monitor bundle to use DS. The steps are for the most part the same as for the other two bundles, but because the emergency monitor bundle sits at the top of the food chain, there are a few differences:

• Select the emergency monitor project and choose New > Other... from the context menu. Under Plug-in Development, select Component Definition and press Next.

• For the folder name, use org.equinoxosgi.toast.client.emergency/OSGI-INF.

• Use the default file name of component.xml.

• Press the Browse... button, start typing EmergencyMonitor for the class of the component, select it once it appears in the list, and press Finish.

• Again, fill in startup and shutdown for the Activate and Deactivate fields, respectively.

• Flip over to the Services tab in the editor. In the Referenced Services section, press the Add... button, type in IAirbag, and press OK. Then, with IAirbag still highlighted, press the Edit... button. In the Name field, type in airbag. In the Bind field, type in setAirbag. This means that when the airbag becomes available to the emergency monitor component, DS calls the setAirbag method.

• Now repeat these steps to add a referenced service for the GPS. Use gps for the Name field. Use setGps for the Bind field so DS can link in the IGps service when it becomes available.

• Save the contents of the editor.

• Delete the package that contains the bundle activator, since it is no longer needed.

• Finally, remove the bundle activator reference from the bundle manifest itself on the Overview tab, and remove the two references to SAT from the Dependencies tab.

It’s worth taking a closer a look at the generated component.xml file for this component. Select the Source tab to see the content shown in the following snippet:

image

Naming Conventions

There are several things that need naming when working with DS: the component and its lifecycle methods, and the referenced services and their lifecycle methods.

Component name—The component name must be globally unique. This name is not particularly important, so we suggest deriving it from the name of the bundle contributing the component. For example, here we used org.equinoxosgi.toast.client.emergency.

Component lifecycle methods—By default, activate and deactivate methods are called on the component as it changes state. We prefer, and use here, the more generic startup and shutdown naming convention.

Referenced service names—As with all naming, we recommend semantic naming such as gps over type-based names when identifying referenced services. Using a type-based name implies a relationship that likely does not exist and a maintenance burden that is guaranteed to require work. Semantic names are more flexible and more clearly identify the role that the referenced service plays. Note that referenced service names are optional. A name is needed only for debugging purposes and when using the ComponentContext’s locateService and locateServices methods.

Referenced service lifecycle methods—We also recommend that you derive the bind and unbind method names from the semantics of the service being referenced and the role it plays in your component. This should relate to the referenced service name. So, if the referenced service name is gps, the bind and unbind method names should be setGps and clearGps.

There are a few interesting things to note in this component declaration. First, this component requires the GPS and airbag services to work. This is captured in the two <reference> elements. Here the interface must be the fully qualified name of the service interface, but the reference name, if specified, need be unique only within the component. Notice also that, unlike the other two cases, this component does not provide any services—it is at the top of the food chain.

The activation portion of the lifecycle for this component under DS matches the earlier implementation. The EmergencyMonitor expects that DS will invoke the setGps and setAirbag methods as those required services become available. Once all the required services are available and their corresponding bind methods have been invoked, it expects DS to invoke its startup method.

The deactivation portion of the lifecycle is now a mirror image of the activation. When any required service becomes unavailable, DS first invokes the shutdown method followed by the relevant unbind methods if specified.

6.4.4 Launching

With the three bundles refactored to use DS, let’s launch the application again:

• Select Run > Run Configurations... from the menu bar.

• Select the Toast run configuration from beneath OSGi Framework in the list at the left.

• Scroll down into the Target Platform bundles and check the box beside the bundles org.eclipse.equinox.ds and org.eclipse.equinox.util. These bundles are Equinox’s DS implementation and prerequisite.

• Also, remove the org.eclipse.soda.sat.core bundle from this list.

• On the Arguments tab, add this to the VM Arguments so we can see any DS errors on the console:

-Dequinox.ds.print=true

eclipse.ignoreApp and osgi.noShutdown

You’ll notice two VM arguments that are in the list by default:

-Declipse.ignoreApp=true -Dosgi.noShutdown=true

When the eclipse.ignoreApp argument is set to true, the main launching thread will not start the default application. This makes sense in our case because we are running a plain OSGi system rather than an Eclipse application.

Setting the osgi.noShutdown argument to true causes the OSGi framework to keep running even when the main thread has completed. In many cases, there is no work to be done on the main thread, so we need this option to make sure the framework stays alive.

When you click the Run button, you should see the familiar output on the Console view:

image

6.4.5 Declarative Services Summary

By making Toast run on Declarative Services, you learned how to declare, both in XML and using the DS tooling, the services that a bundle references and those that it provides. You did this for bundles both at the top and at the bottom of the food chain.

Moving from bundle activators to Declarative Services was not a difficult task. That ease of migration comes from the nature of DS but also in large part as a side effect of the principle maintained throughout Toast—keeping the domain logic separate from the plumbing and maintaining a unidirectional bundle dependency graph.

6.5 Summary

When the lifecycle and discovery of services are kept out of the domain logic, the domain logic can be used with Service Trackers, SAT, Declarative Services, and even in non-OSGi deployments. In fact, you might have noticed that in exploring all three dynamic service mechanisms, you barely modified the domain logic.

It’s also important to point out that a well-structured OSGi-based system can be written using any of the three approaches shown in this chapter. While all three approaches have their advantages and disadvantages, we don’t consider them equally useful in all situations. In fact, we don’t recommend basing your system on Service Trackers at all.

SAT works well for systems with bundles numbering in the hundreds or fewer, not in the thousands. The price SAT pays to determine if each bundle is ready to activate becomes insignificant if all your bundles end up getting started anyhow. SAT’s tooling makes it easy to create and refactor your bundles.

Declarative Services, because of its declarative nature, scales up to systems with thousands of bundles, and it shines particularly in systems where many of the bundles run only occasionally. Not relying on a bundle running code to determine whether it is ready has definite performance advantages. But those advantages come at a cost. Debugging is more difficult when using DS than when using SAT, although the tooling mitigates this to some degree. So while all three approaches are valid, we’ve chosen to implement the remainder of Toast using Declarative Services, as it offers the most benefits and the simplest programming model.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.28.80