Using JSR 160 is very simple; the API is standard, so it does not matter if you use MX4J's JSR 160
         implementation or Sun's JSR 160 reference implementation.
         
         You can checkout the JSR 160 examples shipped with MX4J to understand how to use the JSR 160 API.
      
         JSR 160 connector servers are identified by a JMXServiceURL, represented by the class
         javax.management.remote.JMXServiceURL.
         
         A JMXServiceURL is a string of the form:
      
service:jmx: <protocol>://[[[ <host>]: <port>]/ <path>]
where protocol is a short string that represent the protocol such as "rmi", "iiop", "jmxmp" or "soap", while host, port and path are optional.
A JMXServiceURL can be seen as the "address" of a JMXConnectorServer, and it is the mean by which a JMXConnector can connect to a JMXConnectorServer.
         However, a JMXServiceURL is not sufficient to express the many possibile configurations of a
         JMXConnectorServer (for example, it would be difficult to use a JMXServiceURL to specify - for the
         RMIConnectorServer - the RMIClientSocketFactory and the RMIServerSocketFactory).
         
         For this reason JMXConnectorServers and JMXConnector make use of
         java.util.Maps to
         specify environment properties that a JMXConnectorServer or a JMXConnector may use to setup properly.
      
         A JMXConnectorServer is attached to an MBeanServer.
         
         This can be achieved by explicitely passing the MBeanServer to the JMXConnectorServer at the moment of
         creation, or by registering the JMXConnectorServer - an MBean itself - inside the target MBeanServer.
      
         Once a JMXConnectorServer is attached to an MBeanServer, it is not yet ready to accept incoming calls
         from clients: it must be
         started.
         
         After a JMXConnectorServer has been started successfully, it is ready to accept incoming calls from clients.
         
         Symmetrically, a JMXConnectorServer must be
         stopped in order to stop accepting incoming
         calls from clients. After a JMXConnectorServer has been stopped, it cannot be restarted, and should be
         tossed away.
      
The preferred way to create a JMXConnectorServer is by using the javax.management.remote.JMXConnectorServerFactory class:
Example 3.1. Creating and starting a standalone JMXConnectorServer
               
// The address of the connector server
JMXServiceURL address = new JMXServiceURL("service:jmx:rmi://host");
// The environment map, null in this case
Map environment = null;
// The MBeanServer to which the JMXConnectorServer will be attached to
MBeanServer server = MBeanServerFactory.createMBeanServer();
// Create the JMXCconnectorServer
JMXConnectorServer cntorServer = JMXConnectorServerFactory.newJMXConnectorServer(address, environment, server);
// Start the JMXConnectorServer
cntorServer.start();
               
            
         The example above creates a JMXConnectorServer attached to a freshly created MBeanServer.
         
         The JMXConnectorServer - itself an MBean - is however not registered in the MBeanServer.
      
The following code creates a JMXConnectorServer and registers it in a MBeanServer.
Example 3.2. Creating and starting an MBean JMXConnectorServer
               
// The address of the connector
JMXServiceURL address = new JMXServiceURL("service:jmx:rmi://host");
// The environment map, null in this case
Map environment = null;
JMXConnectorServer cntorServer = JMXConnectorServerFactory.newJMXConnectorServer(address, environment, null);
// The MBeanServer to which the JMXConnectorServer will be registered in
MBeanServer server = MBeanServerFactory.createMBeanServer();
// Register the JMXConnectorServer in the MBeanServer
ObjectName cntorServerName = ObjectName.getInstance("connectors:protocol=rmi");
server.registerMBean(cntorServer, cntorServerName);
// Start the JMXConnectorServer
cntorServer.start();
// An alternative way to start the JMXConnectorServer via the MBeanServer
server.invoke(cntorServerName, "start", null, null);
// Yet another way to start the JMXConnectorServer via the MBeanServer
Object proxy = MBeanServerInvocationHandler.newProxyInstance(server, cntorServerName, JMXConnectorServerMBean.class, true);
JMXConnectorServerMBean cntorServerMBean = (JMXConnectorServerMBean)proxy;
cntorServerMBean.start();
               
            
         Once a JMXConnectorServer is connected to an MBeanServer and once it has been started, it is possible to
         create a JMXConnector on a client host and connect it to the JMXConnectorServer.
         
         We already saw that the mean used by a JMXConnector to connect to a JMXConnectorServer is a JMXServiceURL.
      
         If a JMXConnectorServer is the server-side component that allows to interact with a MBeanServer,
         a JMXConnector is the client-side component that allows client code to contact a remote MBeanServer.
         
         A JMXConnector handles the details of registering notification listeners and receiving notifications from the
         remote MBeanServer, as well as providing a way to authenticate to the JMXConnectorServer, and eventually
         execute operations on behalf of a given
         javax.security.auth.Subject.
         
         Finally the JMXConnector allows client code to obtain an implementation of the
         javax.management.MBeanServerConnection interface that allows to interact with the
         remote MBeanServer as if it is local.
      
The preferred way to create a JMXConnector is to use the javax.management.remote.JMXConnectorFactory class:
Example 3.3. Connecting a JMXConnector
               
// The address of the connector server
JMXServiceURL address = ...;
// The environment map, null in this case
Map environment = null;
// Create the JMXCconnectorServer
JMXConnector cntor = JMXConnectorFactory.connect(address, environment);
// Obtain a "stub" for the remote MBeanServer
MBeanServerConnection mbsc = cntor.getMBeanServerConnection();
// Call the remote MBeanServer
String domain = mbsc.getDefaultDomain();
               
            
         JMXConnectors can be instantiated, but connected at a later time.
         
         Below is a code snippet that shows how to instantiate a JMXConnector and then connect it
         to the JMXConnectorServer.
         
         Note the use of two different environment Maps: one is used to specify creation parameters, the other
         to specify connection parameters.
      
Example 3.4. Creating and connecting a JMXConnector
               
// The address of the connector server
JMXServiceURL address = ...;
// The creation environment map, null in this case
Map creationEnvironment = null;
// Create the JMXCconnectorServer
JMXConnector cntor = JMXConnectorFactory.newJMXConnector(address, creationEnvironment);
// The connection environment map, null in this case
// May contain - for example - user's credentials
Map connectionEnvironment = null;
// Connect
cntor.connect(connectionEnvironment);
// Obtain a "stub" for the remote MBeanServer
MBeanServerConnection mbsc = cntor.getMBeanServerConnection();
// Call the remote MBeanServer
String domain = mbsc.getDefaultDomain();
               
            
         JSR 160 connectors are able to receive notifications emitted by a remote MBean.
         
         The details of the mechanism of how remote notifications are delivered depends on the protocol
         used by the connector; however, few general principles are explained below.
      
         To receive notifications, a client must register a listener by means of the
         javax.management.MBeanServerConnection.addNotificationListener(...) method.
         
         There are two overloaded versions of this method: one that takes an ObjectName as listener, and one that
         takes a NotificationListener as listener.
      
In the first case, the listener is remote (an MBean in the remote MBeanServer) and thus both the filter and the handback object are sent over the wire to the server (and of course both must be serializable).
         The more interesting case is the second, where the listener is local to the client code.
         
         In this case the listener that receives notifications emitted by a remote MBean always
         remains local to the client code that registered it. The NotificationListener object is never sent across
         the wire.
         
         NotificationListener objects are usually implemented with anonymous inner classes
         (that most of the times are not serializables), and client code should not make any particular attention
         on how to implement NotificationListeners that receive remote Notifications: anonymous inner classes are
         a good choice.
      
         On the other end, if the remote MBean sends custom subclasses of the Notification class, it must ensure that
         the custom Notification objects are
         serializable.
         
         The meaning of
         serializable depends on the protocol used; in case of RMI, it is the
         usual meaning of "Java serializable" (that is, it can be written to a
         java.io.ObjectOutputStream).
      
         NotificationFilters may or may not be sent over the wire, depending on the protocol used by the JMXConnector.
         
         It is a good choice to use the standard JMX NotificationFilters such as
         javax.management.NotificationFilterSupport,
         javax.management.AttributeChangeNotificationFilter and
         javax.management.relation.MBeanServerNotificationFilter to perform filtering of
         Notifications: these classes are serializable, and known to the server side.
         
         If you want to write your custom NotificationFilter, write it in such a way that will work no matter if it is
         run on client side or on server side, and be sure its class is known to the server side (for more
         details about server side classloading, refer to the JSR 160 specification).
      
The handback object always remains on client side.
         In the MX4J implementation, notifications are requested by the client to the server, and use a notification
         buffer as explained in the JSR 160 specification.
         
         Since it's the client that initiates the notification request, the mechanism can be seen as a polling
         mechanism. However, if the server does not have notifications to send to the client, it does not return
         an empty result, but instead holds the call for a configurable timeout until a notification is emitted
         or the timeout elapses.
         
         This allows to reduce the network traffic (since there is no continuous polling from the client to the
         server) and still have a fast reactivity to notification emitted by the server.
         
         Refer to the javadocs of the
         
            mx4j.remote.RemoteNotificationClientHandler
          and of the
         
            mx4j.remote.RemoteNotificationServerHandler
          for further details.
      
         Take also a look at the examples bundled with the MX4J distribution for code snippets on registering
         listeners to remote MBeans.
         
         Below, a quick example of how to register a listener to a remote MBean:
      
Example 3.5. Registering a NotificationListener to a remote MBean
               
// The address of the connector server
JMXServiceURL address = ...;
// The JMXConnector
JMXConnector connector = JMXConnectorFactory.connect(address);
// The MBeanServerConnection "stub"
MBeanServerConnection mbsc = connector.getMBeanServerConnection();
// The MBeanServerDelegate emits notifications about registration/unregistration of MBeans
ObjectName delegateName = ObjectName.getInstance("JMImplementation:type=MBeanServerDelegate");
NotificationListener listener = new NotificationListener()
{
   public void handleNotification(Notification notification, Object handback)
   {
      // Do something
   }
};
mbsc.addNotificationListener(delegateName, listener, null, null);