The ServiceAccess Class and Zeroconf Discovery
A common feature of many of the Data Abstract for Cocoa samples is that they make use of Zeroconf to discover any instances of Relativity Server that are running on the local network. However as this is not directly related to demonstrating a particular feature of the Data Abstract SDK, the sample documentation doesn't cover what the
ServiceAccess class is doing. The purpose of this document is to give you an overview of how the
ServiceAccess class works so that you can potentially take advantage of this feature in your own or a customers environment.
If you haven't come across Zero Configuration Networking (Zeroconf) before, you may know it under the name that Apple uses for it; Bonjour. The purpose of Zeroconf is to automatically create a usable computer network where computers and other network capable devices are connected together without the user of the machine or devices having to do any manual configuration. Zeroconf is available out of the box on Mac OS X, on Linux/Unix you can use Avahi and on Windows you need to install iTunes1 or Bonjour Print Services2.
The Remoting SDK, that Data Abstract is built upon, provides built-in support for Zeroconf on all the platforms the SDK is available for and a Zeroconf service is installed on. The Remoting SDK implementation of Zeroconf is known as ROZeroConf and is based on the available open standards for Zeroconf.
ROZeroConf provides two major features: * Automated discovery of services running on the local network, without the need for any central infrastructure or discovery service. Simply be running ROZeroConf enabled services, they will be discoverable by clients. * registration and discovery of services globally across the internet with minimal configuration and a properly set up DNS server.
Using the ROZeroConfBrowser class all that is required is a few short lines to discover services running on the network that match a particular identifier. Enabling discoverability in your custom Data Abstract servers is even easier though its beyond the scope of this article.
You see an example of ROZeroConf in action any time you manage an instance of Relativity Server with the Server Explorer (Mac) or Relativity Admin Tool (Win) tools. When Relativity Server is run it automatically broadcasts to the network that it is available for discovery with the service name
relativity_adminservice. The admin tools search for that service identifier and automatically display any server that is discovered on the local network.
Exploring the ServiceAccess class
ServiceAccess class works in conjunction with the
DataAccess and the
AppDelegate classes to provide effortless discovery of instances of the Relativity Server running on the local network, so that when you are running one of the samples you can focus on understanding what the sample is doing rather than concerning yourself with establishing a link to a running server. Although if needed, the samples also provide a means of supplying an address manually if you need to use an instance of Relativity Server that is running on a machine that doesn't have the Zeroconf service available.
When sample starts the
applicationDidFinishLaunching method of
AppDelegate creates an singleton instance of the
DataAccess class which in turn creates an instance of the
ServiceAccess class. The
AppDelegate registers itself as a delegate for the
DataAccess class and then registers itself as handling the three notifications related to the discovery of a service (NOTIFICATION_FOUND_SERVICE), the disappearance of a service (NOTIFICATION_LOST_SERVICE) and that a connection to a service is established (NOTIFICATION_SERVICE_CONNECTED). Finally it calls the
startBrowsing method of
ServiceAccess which tells ROZeroConfBrowser] to start browsing the network for a particular service identifier.
Discovering a Server with Zeroconf
Looking a little more closely at
ServiceAccess, the first time the
zcBrowser property is accessed it creates an instance of the ROZeroConfBrowser class and assigns itself as the delegate for the ROZeroConfBrowser object (ROZeroConfBrowserDelegate). The init method (
initWithServiceType) of ROZeroConfBrowser takes a string identifier of the service that is to be sought on the network. Here we pass
RELATIVITY_SERVICE_NAME which in reality is simply
To be a delegate of the ROZeroConfBrowser class, the
ServiceAccess class needs to implement the following methods
zeroConfBrowser:didRemoveService:moreComing. Those are called when a server is discovered on or disappears from the network.
Once a service is discovered the
zeroConfBrowser:didFindService:moreComing method is called which posts a notification (
NOTIFICATION_FOUND_SERVICE) that generally the
AppDelegate class listens for and it is used to populate a UI element with the service name. (If there is only one discovered server and
AUTO_CONFIGURE_FOR_FIRST_SERVICE is set to true, then it calls the ServiceAccess delegate's
setupConnectionByIdentifier: method. However this isn't typically used)
Likewise when a service disappears the
zeroConfBrowser:didRemoveService:moreComing method is called which posts the
NOTIFICATION_LOST_SERVICE notification that generally the
AppDelegate class listens for, so that particular service can be removed from the UI element's list of available servers.
When a service is selected from the UI, the ServiceAccess method
setupConnectionByIdentifier is called passing in the name of the selected service. This name is converted into an identifier (either pulled from the list that
ROZeroConfBrowser holds internally, or from those added manually by the user) that is passed to the
setupConnectionWithService method of
DataAccess which creates both a login and data service (using RORemoteService) and passes them to the DataAccess class's DARemoteDataAdapter. Control is then returned to
setupConnectionByIdentifier which posts a
NOTIFICATION_SERVICE_CONNECTED notification that (typically) the AppDelegate listens and uses to highlight the connected service in some way (like in a popup).
At this point the Sample has a DARemoteDataAdapter that is fully configured to work with an instance of Relativity Server.
NOTE: If you change
AUTO_CONFIGURE_FOR_FIRST_SERVICE (defined at the top of
ServiceAccess.m) to YES rather than NO, then the
zeroConfBrowser:didFindService:moreComing method will call
setupConnectionWithService on the first discovered service to immediately establish a connection to that service.
Manually registering a Server
The samples also provide a means for the user to manually specify an address for the server. The UI for this is not the same in the samples, but internally once the user has entered an address it is passed to the
registerServerName method of the
ServiceAccess class. This method ensures that the address adheres to the correct URL format and passes this url to the
registerServer then creates an
RORemoteService object which is stored in an internal dictionary of custom servers kept by
NOTIFICATION_SERVICE_CONNECTED notification is then posted and the connection to the server is immediately created by calling
setupConnectionByIdentifier. (The assumption being that if the user is adding a url manually that they wish to connect to it now)
Some samples (those for iOS) use the
unRegisterServer method of
ServiceAccess to remove a manual address, that has been removed from a table of available servers.
NOTE: While the
ServiceAccess class in the provided samples contains a
serviceWithURL class method, it is not used by any samples. It demonstrates an alternative means of creating a RORemoteService class.