The ServiceAccess Class and Zeroconf Discovery
Overview
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
The 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 relativity_adminservice
.
To be a delegate of the ROZeroConfBrowser class, the ServiceAccess
class needs to implement the following methods zeroConfBrowser:didFindService:moreComing
and 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:
method.
registerServer
then creates an RORemoteService
object which is stored in an internal dictionary of custom servers kept by ServiceAccess
. The 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.