ManagedServiceFactory, creating instances of the
HotdogVendor class based on configurations provided by
ConfigurationAdmin. Each HotdogVendor
object will be registered with the OSGi framework as a
VendorService, along with properties that describe its
spiciness. The spiciness of the HotdogVendor will be
provided in the configuration's properties.
ManagedServiceFactory, creating instance of the
Customer class based on configurations provided by
ConfigurationAdmin. Each customer will import a
VendorService using an LDAP filter that ensures only
food of the correct spiciness is eaten. Each customer will
automatically start and stop eating food based on the availability
of an imported VendorService with the appropriate spiciness.
ManagedServiceFactoryBundleActivator and passed to the
IManagedServiceFactoryAdvisor as the
IBundleActivationManager parameter.
BundleContext for each
IBundleActivationManager is identical to that of the
bundle that registered the factory.
IBundleActivationManager is what SAT uses internally as
an implementation detail of the BaseBundleActivator.
An inner-bundle really does behave like a regular SAT bundle
activator for the configuration!
public class Activator extends ManagedServiceFactoryBundleActivator {
protected IManagedServiceFactoryAdvisor createAdvisor() {
return new HotdogVendorAdvisor();
}
}
ManagedServiceFactoryBundleActivator the
activator is automatically registered with the OSGi framework as a
ManagedServiceFactory.
createAdvisor() method
to create and return an implementation of the
IManagedServiceFactoryAdvisor interface that knows how to
manage configuration updates from ConfigurationAdmin.
BaseManagedServiceFactoryAdvisor provides an
abstract implementation of the
IManagedServiceFactoryAdvisor interface.
BaseManagedServiceFactoryAdvisor is
highly recommended since it provides a reasonable
implementation for most methods.
IManagedServiceFactoryAdvisor interface from scratch,
but needing to do this should be rare.
BaseManagedServiceFactoryAdvisor and must be implemented by
concreate subclasses.
void createImportedServiceFilters(String, Dictionary, Dictionary, IBundleActivationManager);
Object update(String, Object, Dictionary, Dictionary, IBundleActivationManager);
BaseManagedServiceFactoryAdvisor:
public class HotdogVendorAdvisor extends BaseManagedServiceFactoryAdvisor {
public Object create(String pid, Dictionary properties, IBundleActivationManager manager) {
HotdogVendor vendor = new HotdogVendor();
int spiciness = getSpiciness(properties);
vendor.setSpiciness(spiciness);
LogUtility.logInfo(pid, "Created " + vendor);
Dictionary props = new Hashtable(25);
props.put(VendorService.SPICINESS_PROPERTY_KEY, new Integer(spiciness));
manager.addExportedService(VendorService.SERVICE_NAME, vendor, props);
return vendor;
}
private int getSpiciness(Dictionary properties) {
Integer wrapper = (Integer) properties.get(VendorService.SPICINESS_PROPERTY_KEY);
int spiciness = wrapper.intValue();
return spiciness;
}
public Object update(String pid, Object object, Dictionary oldProperties, Dictionary properties, IBundleActivationManager manager) {
int oldSpiciness = getSpiciness(oldProperties);
int newSpiciness = getSpiciness(properties);
if (oldSpiciness != newSpiciness) {
HotdogVendor vendor = (HotdogVendor) object;
vendor.setSpiciness(newSpiciness);
LogUtility.logInfo(pid, "Updated " + vendor);
Dictionary props = manager.getExportedServiceProperties(VendorService.SERVICE_NAME, vendor);
props.put(VendorService.SPICINESS_PROPERTY_KEY, new Integer(newSpiciness));
manager.setExportedServiceProperties(VendorService.SERVICE_NAME, vendor, props);
}
return object;
}
}
ConfigurationAdmin.
IManagedServiceFactoryAdvisor interface, even
though it really is just an implementation detail of
ConfigurationAdmin and
ManageServiceFactory objects. The persistent ID is
useful for debugging and logging messages.
HotdogVendor class and sets its spiciness to the value
provided by the properties. The private method
getSpiciness(Dictionary) is used to get the spiciness
value.
HotdogVendor is then registered with the OSGi
framework as a VendorService, along with a
Dictionary of properties that describe its spiciness.
This is important since a bundle that import the
VendorService might wish to filter based on the
spiciness of the VendorService.
addExportedService(String, Object, Dictionary), that
registers the service with the OSGi framework, is done through the
IBundleActivationManager parameter. Remember the
IBundleActivationManager is the inner-bundle for the
configuration.
HotdogVendor object is returned.
The object returned by this method is cached by the
BaseManagedServiceFactoryAdvisor class in a Map keyed
by persistent ID. Later when the configuration is updated,
destroyed and deleted the object is retrieved from the
Map and passed to the appropriate
IManagedServiceFactoryAdvisor API.
ConfigurationAdmin.
update method queries the old and new properties
for the spiciness values and compares them. This
comparison is not strictly needed since spiciness is
the only property of the configuration. But nevertheless, this is
exactly what should be done to identify which properties need
updating.
update method. Since it is typed as an
Object it must be cast back to a
HotdogVendor before having its
setSpiciness(int) method called.
HotdogVendor object has been updated, its
registered exported properties are retrieved using the method
getExportedServiceProperties(String, Object), updated
and set using the method
setExportedServiceProperties(String, Object, Dictionary).
Again, it is important to note that this is all done via the
IBundleActivationManager parameter.
HotdogVendor object is returned.
Just as with the create method, the object returned by
this method will be cached by the
BaseManagedServiceFactoryAdvisor class in a
Map keyed by persistent ID. While typically this is
the same object as passed to the update method, this is not
necessarily the case. Returning a different object will cause the
previously cached object to be replaced.
public class Activator extends ManagedServiceFactoryBundleActivator {
protected IManagedServiceFactoryAdvisor createAdvisor() {
return new CustomerAdvisor();
}
}
ManagedServiceFactoryBundleActivator the
activator is automatically registered with the OSGi framework as a
ManagedServiceFactory.
createAdvisor() method
to create and return an implementation of the
IManagedServiceFactoryAdvisor interface that knows how to
manage configuration updates from ConfigurationAdmin.
BaseManagedServiceFactoryAdvisor:
public class CustomerAdvisor extends BaseManagedServiceFactoryAdvisor {
private static final String NAME_PROPERTY_KEY = "name";
public Object create(String pid, Dictionary properties, IBundleActivationManager manager) {
Customer customer = new Customer();
String name = getName(properties);
customer.setName(name);
VendorService vendor = (VendorService) manager.getImportedService(VendorService.SERVICE_NAME);
customer.setVendor(vendor);
LogUtility.logInfo(pid, "Created " + customer);
customer.startEating();
return customer;
}
public void createImportedServiceFilters(String pid, Dictionary oldProperties, Dictionary properties, IBundleActivationManager manager) {
int spiciness = getSpiciness(properties);
// LDAP Filter is "(spiciness=)"
StringBuffer buffer = new StringBuffer(15);
buffer.append('(');
buffer.append(VendorService.SPICINESS_PROPERTY_KEY);
buffer.append('=');
buffer.append(spiciness);
buffer.append(')');
String filter = buffer.toString();
try {
BundleContext context = manager.getBundleContext();
Filter newFilter = context.createFilter(filter);
Filter oldFilter = manager.getImportedServiceFilter(VendorService.SERVICE_NAME);
boolean equal = newFilter.equals(oldFilter);
if (equal == true) return; // Early return.
LogUtility.logInfo(pid, "Adding VendorService filter " + filter);
manager.addImportedServiceFilter(VendorService.SERVICE_NAME, filter);
} catch (InvalidSyntaxException exception) {
LogUtility.logError(this, "Failed to create imported service filter", exception);
}
}
public void destroy(String pid, Object object, Dictionary properties, IBundleActivationManager manager) {
Customer customer = (Customer) object;
customer.stopEating();
LogUtility.logInfo(pid, "Destroyed " + customer);$
}
private String getName(Dictionary properties) {
return (String) properties.get(NAME_PROPERTY_KEY);
}
private int getSpiciness(Dictionary properties) {
Integer wrapper = (Integer) properties.get(VendorService.SPICINESS_PROPERTY_KEY);
int spiciness = wrapper.intValue();
return spiciness;
}
public Object update(String pid, Object object, Dictionary oldProperties, Dictionary properties, IBundleActivationManager manager) {
String oldName = getName(oldProperties);
String newName = getName(properties);
if (oldName.equals(newName) == false) {
Customer customer = (Customer) object;
customer.setName(newName);
LogUtility.logInfo(pid, "Updated " + customer);
}
return object;
}
}
createImportedServiceFilters method is called when a
new configuration is created by ConfigurationAdmin.
createImportedServiceFilters method is an
opportunity for the advisor to create each of the LDAP filters to be
used to acquire its imported services.
Customer needs to create an LDAP filter to ensure
that it only acquires a VendorService with the appropriate
spiciness. The LDAP filter is created using the spiciness value
provided by the properties. The private method
getSpiciness(Dictionary) is used to get the spiciness
value.
createImportedServiceFilters method is called
whenever the imported service's properties change it is important
for the advisor to compare the LDAP filter it has created with a
previously created LDAP filter. The method terminates early if the
filters are found to be equal.
addImportedServiceFilter(String, Filter) on the
IBundleActivationManager. If the advisor had multiple
imported services that required LDAP filters this method would be
called for each imported service.
create method is called when a new configuration has
been created by ConfigurationAdmin.
Customer class and sets its name to the value provided
by the properties. The private method
getName(Dictionary) is used to get the name value.
Customer always needs a
VendorService the method
getImportedService(String) is called on the
IBundleActivationManager. A VendorService
matching the LDAP filter is guaranteed to be returned since the
create method is only called once all the imported services have
been acquired by the IBundleActivationManager. The
VendorService is set in the Customer by
calling its setVendor(VendorService) method.
VendorService has been set the method
startEating() is called on the Customer.
Customer object is returned. The
object returned by this method is cached by the
BaseManagedServiceFactoryAdvisor class in a
Map keyed by persistent ID. Later when the
configuration is updated, destroyed and deleted the object is
retrieved from the Map and passed to the appropriate
IManagedServiceFactoryAdvisor API.
IBundleActivationManager has lost one of its imported
services.
IBundleActivationManager will lose an imported
service if it is has been unregistered with the OSGi framework, or
if the imported service has had its exported service properties
changed such that they no longer match the LDAP filter specified by
the advisor.
Object parameter back to a
Customer and calls its stopEating()
method.
stopEating() method.
update method is called when the configuration's
properties have been changed by ConfigurationAdmin.
update method queries the old and new properties
for the name values and compares them. This comparison is not
strictly needed since the name is the only property of the
configuration that affects the Customer. But
nevertheless, this is exactly what should be done to identify which
properties need updating.
create method is passed back
into the update method. Since it is typed as an
Object it must be cast back to a Customer
before having its setName(String) method called.
Customer object is returned. Just
as with the create method, the object returned by this method will
be cached by the BaseManagedServiceFactoryAdvisor class
in a Map keyed by persistent ID. While typically this
is the same object as passed to the update method, this is not
necessarily the case. Returning a different object will cause the
previously cached object to be replaced.
Copyright © 2001, 2007 IBM Corporation and others. All Rights Reserved.