The Properties Facet

4 min read

4 min read

4 min read

2 min read

2 min read

2 min read

4 min read

2 min read

4 min read

An administrator may find it useful to be able to view or modify the configuration properties of a remote Ice application. For example, the IceGrid administrative tools allow you to query and update the properties of active servers. The Properties facet supplies this functionality.

The Ice::PropertiesAdmin interface provides access to the communicator's configuration properties:

Slice
module Ice
{
interface PropertiesAdmin
{
string getProperty(string key);
PropertyDict getPropertiesForPrefix(string prefix);
void setProperties(PropertyDict newProperties);
}
}

The getProperty operation retrieves the value of a single property, and the getPropertiesForPrefix operation returns a dictionary of properties whose keys match the given prefix.

The setProperties operation merges the entries in newProperties with the communicator's existing properties. If an entry in newProperties matches the name of an existing property, that property's value is replaced with the new value. If the new value is an empty string, the property is removed. Any existing properties that are not modified or removed by the entries in newProperties are retained with their original values. If the Ice.Trace.Admin.Properties property is enabled, Ice logs a message if a call to setProperties results in any changes to the property set.

setProperties applies the usual property validation when adding, changing, or removing an entry. A rejected entry makes the call fail, and the entries applied before it stay in place.

We already showed how to obtain a proxy for a remote administrative facet, but suppose you want to interact with the facet in your local address space. The code below shows the necessary steps:

C++
// It's nullptr when the facet is not enabled
Ice::NativePropertiesAdminPtr propertiesAdmin =
communicator->findAdminFacet<Ice::NativePropertiesAdmin>("Properties");

As shown here, the facet is registered with the name Properties and the servant class is NativePropertiesAdmin. This servant class implements the skeleton class generated by the Slice compiler for PropertiesAdmin.

The Ice runtime can notify an application whenever its properties change due to invocations of the setProperties operation on the PropertiesAdmin interface.

addUpdateCallback accepts a std::function<void(const Ice::PropertyDict&)> and returns a function that unregisters the callback:

C++
auto removeCallback = propertiesAdmin->addUpdateCallback(
[](const Ice::PropertyDict& changes) { /* Apply application settings. */ });
// When notifications are no longer needed:
removeCallback();

The callback receives added and changed entries with their new values, and removed entries with empty values. A successful setProperties call invokes the registered callbacks even when it changed nothing; the dictionary is then empty. Direct calls to Properties.setProperty do not invoke these callbacks.

We already showed how to obtain a proxy for a remote administrative facet, but suppose you want to interact with the facet in your local address space. The code below shows the necessary steps:

C#
if (communicator.findAdminFacet("Properties") is
Ice.NativePropertiesAdmin propertiesAdmin)
{
...
}
// else, the facet is not enabled

As shown here, the facet is registered with the name Properties and the servant class is NativePropertiesAdmin. This servant class implements the skeleton class generated by the Slice compiler for PropertiesAdmin.

The Ice runtime can notify an application whenever its properties change due to invocations of the setProperties operation on the PropertiesAdmin interface.

Register an Action<Dictionary<string, string>> with addUpdateCallback. Retain the delegate to unregister it with removeUpdateCallback:

C#
Action<Dictionary<string, string>> callback = changes => { /* Apply application settings. */ };
propertiesAdmin.addUpdateCallback(callback);
// When notifications are no longer needed:
propertiesAdmin.removeUpdateCallback(callback);

The callback receives added and changed entries with their new values, and removed entries with empty values. A successful setProperties call invokes the registered callbacks even when it changed nothing; the dictionary is then empty. Direct calls to Properties.setProperty do not invoke these callbacks.

We already showed how to obtain a proxy for a remote administrative facet, but suppose you want to interact with the facet in your local address space. The code below shows the necessary steps:

Java
com.zeroc.Ice.Object obj = communicator.findAdminFacet("Properties");
if (obj != null) { // It's null when the facet is not enabled
var propertiesAdmin = (com.zeroc.Ice.NativePropertiesAdmin)obj;
...
}

As shown here, the facet is registered with the name Properties and the servant class is NativePropertiesAdmin. This class implements the PropertiesAdmin interface generated by the Slice compiler.

The Ice runtime can notify an application whenever its properties change due to invocations of the setProperties operation on the PropertiesAdmin interface.

Register a Consumer<Map<String, String>> with addUpdateCallback. Retain the callback to unregister it with removeUpdateCallback:

Java
java.util.function.Consumer<java.util.Map<String, String>> callback =
changes -> { /* Apply application settings. */ };
propertiesAdmin.addUpdateCallback(callback);
// When notifications are no longer needed:
propertiesAdmin.removeUpdateCallback(callback);

The callback receives added and changed entries with their new values, and removed entries with empty values. A successful setProperties call invokes the registered callbacks even when it changed nothing; the dictionary is then empty. Direct calls to Properties.setProperty do not invoke these callbacks.

Use a PropertiesAdmin proxy to access another communicator's Properties facet remotely.

We already showed how to obtain a proxy for a remote administrative facet, but suppose you want to interact with the facet in your local address space. The code below shows the necessary steps:

Python
propertiesAdmin = communicator.findAdminFacet("Properties")
if propertiesAdmin is not None:
assert isinstance(propertiesAdmin, Ice.NativePropertiesAdmin)
...

The facet is registered with the name Properties. findAdminFacet returns a NativePropertiesAdmin wrapper that provides access to the C++ facet's update callbacks.

The Ice runtime can notify an application whenever its properties change due to invocations of the setProperties operation on the PropertiesAdmin interface.

addUpdateCallback accepts a callable that takes a dict[str, str] and returns None. Retain the callable to unregister it with removeUpdateCallback:

Python
def onUpdate(changes: dict[str, str]) -> None:
"""Apply updated application settings."""
...
propertiesAdmin.addUpdateCallback(onUpdate)
# When notifications are no longer needed:
propertiesAdmin.removeUpdateCallback(onUpdate)

The callback receives added and changed entries with their new values, and removed entries with empty values. A successful setProperties call invokes the registered callbacks even when it changed nothing; the dictionary is then empty. Direct calls to Properties.setProperty do not invoke these callbacks.

We already showed how to obtain a proxy for a remote administrative facet, but suppose you want to interact with the facet in your local address space. The code below shows the necessary steps:

Swift
if let propertiesAdmin = communicator.findAdminFacet("Properties") as?
NativePropertiesAdmin {
...
}

As shown here, the facet is registered with the name Properties and the servant is a NativePropertiesAdmin value. This structure conforms to the PropertiesAdmin protocol generated by the Slice compiler.

The Ice runtime can notify an application whenever its properties change due to invocations of the setProperties operation on the PropertiesAdmin interface.

addUpdateCallback(_:) accepts a (PropertyDict) -> Void closure and returns a PropertiesAdminRemoveCallback closure that unregisters it:

Swift
let removeCallback = propertiesAdmin.addUpdateCallback { changes in
// Apply application settings.
}
// When notifications are no longer needed:
removeCallback()

The callback receives added and changed entries with their new values, and removed entries with empty values. A successful setProperties call invokes the registered callbacks even when it changed nothing; the dictionary is then empty. Direct calls to Properties.setProperty do not invoke these callbacks.