Provides implementations of the {@linkplain net.jini.event.EventMailbox} service. Three implementations are available for use with the {@link org.apache.river.start} package:

- `org.apache.river.mercury.ActivatableMercuryImpl` - an activatable, persistent implementation, suitable for use with {@link org.apache.river.start.SharedActivatableServiceDescriptor}
- `org.apache.river.mercury.NonActivatableMercuryImpl` - a non-activatable, persistent implementation, suitable for use with {@link org.apache.river.start.NonActivatableServiceDescriptor}
- `org.apache.river.mercury.TransientMercuryImpl` - a transient implementation, also suitable for use with {@link org.apache.river.start.NonActivatableServiceDescriptor}

The JAR file `mercury.jar`, included in the `lib` subdirectory of the Apache River release installation, contains the classes for the three Mercury service implementations. The `mercury-dl.jar` and `jsk-dl.jar` files in the `lib-dl` subdirectory contain the classes needed in the codebase for its downloaded proxies. None of the JAR files include classes from `jsk-platform.jar`, which are included by the service starter's `start.jar` JAR file, and need to be included in the codebase of clients.

The object returned by the {@link net.jini.admin.Administrable#getAdmin Administrable.getAdmin} method on a Mercury service proxy implements {@link net.jini.admin.JoinAdmin} and {@link org.apache.river.admin.DestroyAdmin}.

This document provides the following information about Mercury:

- Configuring Mercury
- Access Control Permission Targets
- Logging
- Examples for Running Mercury

## Configuring Mercury

The Mercury service implementation obtains its configuration by calling {@link net.jini.config.ConfigurationProvider#getInstance(String[], ClassLoader) ConfigurationProvider.getInstance} with the specified configOptions and the class loader for the implementation class.

The implementation supports the following configuration entries, with component `org.apache.river.mercury`:

• | `activationIdPreparer`
--- | ---
| Type: | {@link net.jini.security.ProxyPreparer}
| Default: | `new {@link net.jini.security.BasicProxyPreparer}()`
| Description: | The proxy preparer for the service's activation ID. The value should not be `null`. This entry is obtained at service start and restart. This entry is only used by the activatable implementation. Clients call the {@link java.rmi.activation.ActivationID#activate activate} method on instances of {@link java.rmi.activation.ActivationID} when they need to reactivate the service.

• | `activationSystemPreparer`
--- | ---
| Type: | {@link net.jini.security.ProxyPreparer}
| Default: | `new {@link net.jini.security.BasicProxyPreparer}()`
| Description: | The proxy preparer for the proxy for the activation system. The value should not be `null`. This entry is obtained at service start and restart. This entry is only used by the activatable implementation. The service calls the {@link java.rmi.activation.ActivationSystem#unregisterObject unregisterObject} method on the {@link java.rmi.activation.ActivationSystem} when the service is destroyed.

• | `discoveryManager`
--- | ---
| Type: | {@link net.jini.discovery.DiscoveryManagement}
| Default: |
    new {@link net.jini.discovery.LookupDiscoveryManager}(
        groups,   // current group set
        locators, // current locator set
        null,     // listener
        this)     // config
| Description: | Supplies an object used to discover the lookup services with which this service should register. The value should not be `null`. The object returned must also implement {@link net.jini.discovery.DiscoveryGroupManagement} and {@link net.jini.discovery.DiscoveryLocatorManagement}, and should be configured initially to discover no groups or specific lookup services. This entry is obtained at service start and restart.

• | `initialLookupAttributes`
--- | ---
| Type: | `{@link net.jini.core.entry.Entry}[]`
| Default: | `new Entry[0]`
| Description: | Entries to include in the set of attributes the service supplies when registering with lookup services, in addition to {@link net.jini.lookup.entry.ServiceInfo} and {@link org.apache.river.lookup.entry.BasicServiceType} instances provided by the service. An empty array or `null` specifies that only the service-provided attributes should be added. The array must not contain `null` elements. This entry is obtained and used when the service is first started. Following initial startup, the set of attributes is controlled though the service's {@link net.jini.admin.JoinAdmin} administrable interface.

• | `initialLookupGroups`
--- | ---
| Type: | `String[]`
| Default: | `new String[] { "" } /* public group */`
| Description: | The names of the lookup groups that the service should discover and join. An empty array specifies that no groups should be joined. A `null` value specifies that all groups should be joined. Otherwise, the value specifies the names of the groups to join. The array must not contain `null` elements. This entry is obtained and used when the service is first started. Following initial startup, the set of lookup groups is controlled through the service's {@link net.jini.admin.JoinAdmin} administrable interface.

• | `initialLookupLocators`
--- | ---
| Type: | `{@link net.jini.core.discovery.LookupLocator}[]`
| Default: | `new LookupLocator[0]`
| Description: | The locations of specific lookup services that the service should discover and join. An empty array or `null` specifies that no specific lookup services should be joined. The array must not contain `null` elements. This entry is obtained and used when the service is first started. Following initial startup, the set of specific lookup services is controlled through the service's {@link net.jini.admin.JoinAdmin} administrable interface. The `LookupLocator` instances specified in this entry will not be prepared by the proxy preparer specified in the `locatorPreparer` entry, and will only be prepared by the preparer in the `recoveredLocatorPreparer` entry when they are being recovered.

• | `leasePeriodPolicy`
--- | ---
| Type: | {@link org.apache.river.landlord.LeasePeriodPolicy}
| Default: |
    new {@link org.apache.river.landlord.FixedLeasePeriodPolicy}(
        3 * 60 * 60 * 1000L,  // max = 3 hours
        60 * 60 * 1000L)      // default = 1 hour
| Description: | The policy for calculating lease grants and renewals. The value should not be `null`. The default grants leases with a maximum duration of 3 hours and a default duration of 1 hour. This entry is obtained at service start and restart.

• | `listenerPreparer`
--- | ---
| Type: | {@link net.jini.security.ProxyPreparer}
| Default: | `new {@link net.jini.security.BasicProxyPreparer}()`
| Description: | Preparer for {@link net.jini.core.event.RemoteEventListener} proxies that have registered with this service via the {@link net.jini.event.MailboxRegistration#enableDelivery enableDelivery} method. This preparer is used to prepare proxies only when they initially join with this service. The value should not be `null`. The preparer must return a listener which is equal to the original listener as determined by {@link java.lang.Object#equals Object.equals}. This entry is obtained at service start and restart. This preparer needs to perform all operations needed to use a newly received listener, typically including verifying trust in the participant proxy, granting permissions, and setting constraints. The prepared participant will be retained by the service in its persistent store. The service (potentially) calls the {@link net.jini.core.event.RemoteEventListener#notify notify} method on these proxies.

• | `locatorToJoinPreparer`
--- | ---
| Type: | {@link net.jini.security.ProxyPreparer}
| Default: | `new {@link net.jini.security.BasicProxyPreparer}()`
| Description: | Prepares {@link net.jini.core.discovery.LookupLocator} instances passed to {@link net.jini.admin.JoinAdmin} methods. The value should not be `null`. When registering with lookup services, this service may call or use the constraints assigned to the {@link net.jini.core.discovery.LookupLocator#getRegistrar getRegistrar} methods of `LookupLocator` instances returned from this preparer. This entry is obtained at service start and restart. This preparer needs to perform all operations needed to use a newly received lookup locator, typically including verifying trust in the lookup locator and setting constraints. The prepared lookup locator will be retained by the service in its persistent store. The `LookupLocator` instances obtained from the `initialLookupLocators` configuration entry will not be prepared by this preparer.

• | `loginContext`
--- | ---
| Type: | {@link javax.security.auth.login.LoginContext}
| Default: | `null`
| Description: | If not `null`, specifies the JAAS login context to use for performing a JAAS login and supplying the {@link javax.security.auth.Subject} to use when running the service. If `null`, no JAAS login is performed. This entry is obtained at service start and restart.

• | `logToSnapshotThreshold`
--- | ---
| Type: | `int`
| Default: | `50`
| Description: | The threshold used to determine whether or not to take a snapshot of the server's state. The value should not be negative. The service will delay making new snapshots until the number of log updates is greater than this value. This entry is obtained at service start and restart. This entry is only used by persistent implementations.

• | `maxUnexportDelay`
--- | ---
| Type: | `long`
| Default: | `120000` (2 minutes)
| Description: | How long to retry “nice” unexport attempts before forcing the unexport. Part of destroying a Mercury server includes calling {@link net.jini.export.Exporter#unexport Exporter.unexport(boolean force)} on the `Exporter` used to export the server (see `serverExporter`). The initial `unexport` call passes `false` for the value of the `force` parameter. This is done in order to allow the destroy call to return cleanly to the client. If the initial `unexport` call fails, Mercury will retry calling `unexport(false)` for up to `maxUnexportDelay` milliseconds before giving up and calling `unexport(true)`. `maxUnexportDelay` must be a non-negative long value. If `maxUnexportDelay` is zero then the very first call to `unexport` passes `true` for the value of the `force` parameter, no nice unexport attempt is made. Obtained at service start and restart. Note, the delay between attempted `unexport` calls is controlled by the `unexportRetryDelay` configuration entry.

• | `notificationsExecutorService`
--- | ---
| Type: | {@link java.util.concurrent/ExecutorService ExecutorService}
| Default: | `new` {@link java.util.concurrent/ThreadPoolExecutor ThreadPoolExecutor}( 10, 10, /* Ignored */ 15, TimeUnit.SECONDS, new LinkedBlockingQueue(), /* Unbounded Queue */ new NamedThreadFactory("EventTypeGenerator", false) )
| Description: | The pool of threads used to make event delivery attempts. The {@link java.util.concurrent/ExecutorService#shutdown shutdown} method of this object will be called when the service is destroyed. This entry is obtained at service start and restart.

• | `persistenceDirectory`
--- | ---
| Type: | `String`
| Default: | Required for persistent implementations: no default
| Description: | The directory where the service's persistent state is recorded. The value should not be `null`. This entry is obtained at service start and restart. This entry is required for persistent implementations and is otherwise not used.

• | `recoveredListenerPreparer`
--- | ---
| Type: | {@link net.jini.security.ProxyPreparer}
| Default: | `new {@link net.jini.security.BasicProxyPreparer}()`
| Description: | Preparer for recovered {@link net.jini.core.event.RemoteEventListener} proxies that have been previously registered and prepared with this service (via the {@link net.jini.event.MailboxRegistration#enableDelivery enableDelivery} method). This preparer needs to perform only those operations whose results are not retained in the participant itself, but need to be performed in the environment in which the participant is unmarshalled, typically just granting permissions. The service (potentially) calls the {@link net.jini.core.event.RemoteEventListener#notify notify} method on these proxies.

• | `recoveredLocatorToJoinPreparer`
--- | ---
| Type: | {@link net.jini.security.ProxyPreparer}
| Default: | `new {@link net.jini.security.BasicProxyPreparer}()`
| Description: | Prepares {@link net.jini.core.discovery.LookupLocator} instances for use when they are recovered from persistent storage. The value should not be `null`. When registering with lookup services, this service may call or use the constraints assigned to the {@link net.jini.core.discovery.LookupLocator#getRegistrar getRegistrar} methods of `LookupLocator` instances returned from this preparer. This entry is obtained at service start and restart. This entry is only used by persistent implementations. This preparer needs to perform only those operations whose results are not retained in the lookup locator itself, but need to be performed in the environment in which the lookup locator is unmarshalled. Typically no operations are needed. The `LookupLocator` instances obtained from the `initialLookupLocators` configuration entry will not be prepared by this preparer until they are being recovered.

• | `serverExporter`
--- | ---
| Type: | {@link net.jini.export.Exporter}
| Default: |
    // Activatable implementation
    new {@link net.jini.activation.ActivationExporter}(
        activationID,
        new {@link net.jini.jeri.BasicJeriExporter}(
            {@link net.jini.jeri.tcp.TcpServerEndpoint#getInstance TcpServerEndpoint.getInstance}(0),
            new {@link net.jini.jeri.BasicILFactory}(), false, true))
    // Non-activatable implementations
    new {@link net.jini.jeri.BasicJeriExporter}(
        {@link net.jini.jeri.tcp.TcpServerEndpoint#getInstance TcpServerEndpoint.getInstance}(0),
        new {@link net.jini.jeri.BasicILFactory}(),false, true)
| Description: | The object to use for exporting the service. The value should not be `null`. In the activatable case, the call to `getEntry` will supply the activation ID in the `data` argument. This entry is obtained at service start and restart.

• | `unexportRetryDelay`
--- | ---
| Type: | `long`
| Default: | `1000` (1 second)
| Description: | When destroying a Mercury server how long to wait between unexport attempts. `unexportRetryDelay` must be a positive long value. When destroying itself Mercury will sleep for `unexportRetryDelay` milliseconds between {@link net.jini.export.Exporter#unexport Exporter.unexport} calls. Obtained at service start and restart. See `maxUnexportDelay` for additional details.

## Access Control Permission Targets

The following table lists the remote methods on Mercury's proxy objects and the associated target names for enforcing access control using {@link org.apache.river.mercury.MercuryPermission}:

Proxy Method | Target Name
--- | ---
{@link net.jini.event.EventMailbox#register EventMailbox.register} | register
{@link net.jini.event.MailboxRegistration#enableDelivery MailboxRegistration.enableDelivery} | enableDelivery
{@link net.jini.event.MailboxRegistration#disableDelivery MailboxRegistration.disableDelivery} | disableDelivery
{@link net.jini.core.event.RemoteEventListener#notify RemoteEventListener.notify} | notify
{@link net.jini.core.lease.Lease#renew Lease.renew} | renew
{@link net.jini.core.lease.Lease#cancel Lease.cancel} | cancel
{@link net.jini.core.lease.LeaseMap#renewAll LeaseMap.renewAll} | renewAll
{@link net.jini.core.lease.LeaseMap#cancelAll LeaseMap.cancelAll} | cancelAll
{@link net.jini.admin.Administrable#getAdmin Administrable.getAdmin} | getAdmin
{@link net.jini.admin.JoinAdmin#getLookupAttributes JoinAdmin.getLookupAttributes} | getLookupAttributes
{@link net.jini.admin.JoinAdmin#addLookupAttributes JoinAdmin.addLookupAttributes} | addLookupAttributes
{@link net.jini.admin.JoinAdmin#modifyLookupAttributes JoinAdmin.modifyLookupAttributes} | modifyLookupAttributes
{@link net.jini.admin.JoinAdmin#getLookupGroups JoinAdmin.getLookupGroups} | getLookupGroups
{@link net.jini.admin.JoinAdmin#addLookupGroups JoinAdmin.addLookupGroups} | addLookupGroups
{@link net.jini.admin.JoinAdmin#removeLookupGroups JoinAdmin.removeLookupGroups} | removeLookupGroups
{@link net.jini.admin.JoinAdmin#setLookupGroups JoinAdmin.setLookupGroups} | setLookupGroups
{@link net.jini.admin.JoinAdmin#getLookupLocators JoinAdmin.getLookupLocators} | getLookupLocators
{@link net.jini.admin.JoinAdmin#addLookupLocators JoinAdmin.addLookupLocators} | addLookupLocators
{@link net.jini.admin.JoinAdmin#removeLookupLocators JoinAdmin.removeLookupLocators} | removeLookupLocators
{@link net.jini.admin.JoinAdmin#setLookupLocators JoinAdmin.setLookupLocators} | setLookupLocators
{@link org.apache.river.admin.DestroyAdmin#destroy DestroyAdmin.destroy} | destroy
{@link net.jini.security.proxytrust.ProxyTrust#getProxyVerifier ProxyTrust.getProxyVerifier} | getProxyVerifier
{@link org.apache.river.start.ServiceProxyAccessor#getServiceProxy ServiceProxyAccessor.getServiceProxy} | getServiceProxy

## Loggers and Logging Levels

The Mercury service implementation uses separate {@link java.util.logging.Logger}s, prefixed by `org.apache.river.mercury`, for each type of information it logs. The following tables describe the type of information logged as well as the levels of information logged.

`org.apache.river.mercury.admin`
Level | Description
--- | ---
{@link java.util.logging.Level#FINEST FINEST} | for low level service destruction operation tracing

`org.apache.river.mercury.delivery`
Level | Description
--- | ---
{@link org.apache.river.logging.Levels#HANDLED HANDLED} | for exceptions handled during failed event delivery attempts
{@link java.util.logging.Level#FINEST FINEST} | for low level event delivery operation tracing

`org.apache.river.mercury.expiration`
Level | Description
--- | ---
{@link java.util.logging.Level#FINEST FINEST} | for low level lease expiration operation tracing

`org.apache.river.mercury.init`
Level | Description
--- | ---
{@link java.util.logging.Level#SEVERE SEVERE} | for problems that prevent service startup
{@link java.util.logging.Level#CONFIG CONFIG} | for configuration access during service initialization
{@link org.apache.river.logging.Levels#HANDLED HANDLED} | for exceptions handled during service initialization
{@link java.util.logging.Level#FINEST FINEST} | for low level operation tracing during service initialization

`org.apache.river.mercury.lease`
Level | Description
--- | ---
{@link java.util.logging.Level#FINEST FINEST} | for low level leasing operation tracing (creation, renewal, etc.)

`org.apache.river.mercury.operations`
Level | Description
--- | ---
{@link java.util.logging.Level#FINER FINER} | for method level tracing during service operation

`org.apache.river.mercury.persistence`
Level | Description
--- | ---
{@link org.apache.river.logging.Levels#HANDLED HANDLED} | for exceptions handled during service persistence attempts
{@link java.util.logging.Level#FINEST FINEST} | for low level service persistence operation tracing

`org.apache.river.mercury.receive`
Level | Description
--- | ---
{@link java.util.logging.Level#FINEST FINEST} | for low level event reception tracing

`org.apache.river.mercury.recovery`
Level | Description
--- | ---
{@link org.apache.river.logging.Levels#HANDLED HANDLED} | for exceptions handled during service recovery attempts
{@link java.util.logging.Level#FINEST FINEST} | for low level service recovery operation tracing

`org.apache.river.mercury.startup`
Level | Description
--- | ---
{@link java.util.logging.Level#INFO INFO} | for successful service creation message.

See the {@link org.apache.river.logging.LogManager} class for one way to use the `HANDLED` logging level in standard logging configuration files.

## Examples for Running Mercury

This section provides examples of running Mercury in various configurations.

- Assumptions for running the examples
- JRMP configurations
  - Transient
  - Persistent
  - Activatable
- Jini extensible remote invocation (Jini ERI) configurations
  - Transient
  - Persistent
  - Activatable
- Stopping activatable configurations

### Assumptions for Running the Examples

The examples below make the following assumptions:

- The Java(TM) 2 Platform, Standard Edition, (J2SE(TM)) has been installed, and its commands are available in the current path
- The Apache River release has been installed in the install_dir directory
- The example configuration and policy files described below are available in the config_dir directory
- The local host name is your_host
- The local lookup group name is your.group
- The HTTP server for download JAR files is running on your_host and is available on port http_port. This HTTP server is serving files located in the install_dir/lib-dl directory. You can use the {@link org.apache.river.tool.ClassServer} class for this purpose.
- The examples are being run on UNIX platforms
- The examples are being run on a secure network where access control and authentication are not needed. See the hello example for some client and service configurations that enforce security.
- For activatable services, an activation system is running on your_host. You can use the {@link org.apache.river.phoenix} implementation for this purpose.

Throughout the example, items in bold need to be customized for your local environment.

### Starting Transient Mercury using JRMP

To run a transient Mercury, which does not store any information persistently or use the activation system to restart itself, using JRMP for remote communication, run the following command.

>     java -Djava.security.policy=config_dir/jsk-all.policy \
>          -jar install_dir/lib/start.jar \
>          config_dir/start-transient-jrmp-mercury.config

This configuration uses the following files.

#### File config_dir/jsk-all.policy

Use this security policy file for starting and running all Mercury configurations. This file grants all permissions to local code included in the `lib` subdirectory of the Apache River release installation.

>     grant codebase "file:install_dir/lib/*" {
>         permission java.security.AllPermission;
>     };

#### File config_dir/start-transient-jrmp-mercury.config

Use this configuration source file to start transient Mercury using JRMP.

>     import org.apache.river.start.NonActivatableServiceDescriptor;
>     import org.apache.river.start.ServiceDescriptor;

>     org.apache.river.start {
>         private static codebase = "http://your_host:http_port/mercury-dl.jar"
>            + " http://your_host:http_port/jsk-dl.jar";
>         private static policy = "config_dir/jsk-all.policy";
>         private static classpath = "install_dir/lib/mercury.jar";
>         private static config = "config_dir/transient-jrmp-mercury.config";

>         static serviceDescriptors = new ServiceDescriptor[] {
>     	new NonActivatableServiceDescriptor(
>     	    codebase, policy, classpath,
>     	    "org.apache.river.mercury.TransientMercuryImpl",
>     	    new String[] { config })
>         };
>     }

#### File config_dir/transient-jrmp-mercury.config

Use this configuration source file to run transient Mercury using JRMP.

>     import net.jini.jrmp.JrmpExporter;

>     org.apache.river.mercury {
>         initialLookupGroups = new String[] { "your.group" };
>         serverExporter = new JrmpExporter();
>     }

### Starting Persistent Mercury using JRMP

To run a persistent Mercury, which stores information persistently but does not use the activation system to restart itself, using JRMP for remote communication, run the following command.

>     java -Djava.security.policy=config_dir/jsk-all.policy \
>          -jar install_dir/lib/start.jar \
>          config_dir/start-persistent-jrmp-mercury.config

Note: Because JRMP does not provide a convenient way to specify the same object ID each time a given object is exported, this configuration is only useful for debugging -- an existing service proxy cannot be used after the service is restarted.

This configuration uses the following additional files.

#### File config_dir/start-persistent-jrmp-mercury.config

Use this configuration source file to start persistent Mercury using JRMP.

>     import org.apache.river.start.NonActivatableServiceDescriptor;
>     import org.apache.river.start.ServiceDescriptor;

>     org.apache.river.start {
>         private static codebase = "http://your_host:http_port/mercury-dl.jar"
>            + " http://your_host:http_port/jsk-dl.jar";
>         private static policy = "config_dir/jsk-all.policy";
>         private static classpath = "install_dir/lib/mercury.jar";
>         private static config = "config_dir/persistent-jrmp-mercury.config";

>         static serviceDescriptors = new ServiceDescriptor[] {
>     	new NonActivatableServiceDescriptor(
>     	    codebase, policy, classpath,
>     	    "org.apache.river.mercury.NonActivatableMercuryImpl",
>     	    new String[] { config })
>         };
>     }

#### File config_dir/persistent-jrmp-mercury.config

Use this configuration source file to run persistent Mercury using JRMP.

>     import net.jini.jrmp.JrmpExporter;

>     org.apache.river.mercury {
>         initialLookupGroups = new String[] { "your.group" };
>         persistenceDirectory = "config_dir/mercury.log";
>         serverExporter = new JrmpExporter();
>     }

### Starting Activatable Mercury using JRMP

To run an activatable Mercury, which stores information persistently and uses the activation system to restart itself, using JRMP for remote communication, run the following command.

>     java -Djava.security.policy=config_dir/jsk-all.policy \
>          -jar install_dir/lib/start.jar \
>          config_dir/start-activatable-jrmp-mercury.config

You should remove the config_dir/group.log directory before running this command. Note that the activation system will restart the activatable Mercury service as needed until Mercury is shutdown.

Remember to remove the config_dir/mercury.log directory before running this command if you want Mercury to forget registrations and settings made in previous invocations.

This configuration uses the following additional files.

#### File config_dir/start-activatable-jrmp-mercury.config

Use this configuration source file to start activatable Mercury using JRMP.

>     import org.apache.river.start.ServiceDescriptor;
>     import org.apache.river.start.SharedActivatableServiceDescriptor;
>     import org.apache.river.start.SharedActivationGroupDescriptor;

>     org.apache.river.start {
>         private static mercuryCodebase = "http://your_host:http_port/mercury-dl.jar"
>            + " http://your_host:http_port/jsk-dl.jar";
>         private static mercuryPolicy = "config_dir/jsk-all.policy";
>         private static mercuryClasspath = "install_dir/lib/mercury.jar";
>         private static mercuryConfig = "config_dir/activatable-jrmp-mercury.config";

>         private static groupPolicy = "config_dir/jsk-all.policy";
>         private static groupClasspath = "install_dir/lib/sharedvm.jar";
>         private static groupPersistenceDirectory = "config_dir/group.log";

>         static serviceDescriptors = new ServiceDescriptor[] {
>     	new SharedActivationGroupDescriptor(
>     	    groupPolicy, groupClasspath, groupPersistenceDirectory,
>     	    null /* serverCommand */,
>     	    null /* serverOptions */,
>     	    null /* serverProperties */),
>     	new SharedActivatableServiceDescriptor(
>     	    mercuryCodebase, mercuryPolicy, mercuryClasspath,
>     	    "org.apache.river.mercury.ActivatableMercuryImpl",
>     	    groupPersistenceDirectory,
>     	    new String[] { mercuryConfig },
>     	    true /* restart */)
>         };
>     }

#### File config_dir/activatable-jrmp-mercury.config

Use this configuration source file to run activatable Mercury using JRMP.

>     import java.rmi.activation.ActivationID;
>     import net.jini.jrmp.JrmpExporter;

>     org.apache.river.mercury {
>         initialLookupGroups = new String[] { "your.group" };
>         persistenceDirectory = "config_dir/mercury.log";
>         serverExporter = new JrmpExporter((ActivationID) $data, 0);
>     }

### Stopping Activatable Mercury

To destroy the activation group running an activatable Mercury, under a a JRMP or Jini ERI configuration, run the following command.

>     java -Djava.security.policy=config_dir/jsk-all.policy \
>          -jar install_dir/lib/destroy.jar \
>          config_dir/stop-activatable-mercury.config

Running this command will remove the config_dir/group.log directory.

Note that this command does not actually destroy the service itself, but just destroys the activation group the service is running in. You may want to first destroy the service using Mercury's administrable interface, or to remove the config_dir/mercury.log directory after destroying the activation group.

This command uses the following additional file.

#### File config_dir/stop-activatable-mercury.config

Use this configuration source file to destroy the activation group for an activatable Mercury.

>     import org.apache.river.start.ServiceDescriptor;
>     import org.apache.river.start.SharedActivatableServiceDescriptor;

>     org.apache.river.start {
>         private static codebase = "http://your_host:http_port/group-dl.jar";
>         private static policy = "config_dir/jsk-all.policy";
>         private static classpath = "install_dir/lib/group.jar";
>         private static persistenceDirectory = "config_dir/group.log";

>         static serviceDestructors = new ServiceDescriptor[] {
>     	new SharedActivatableServiceDescriptor(
>     	    codebase, policy, classpath,
>     	    "org.apache.river.start.SharedGroupImpl",
>     	    persistenceDirectory,
>     	    null /* config */,
>     	    false /* restart */)
>         };
>     }

### Starting Transient Mercury using Jini ERI

To run a transient Mercury, which does not store any information persistently or use the activation system to restart itself, using Jini ERI for remote communication, run the following command.

>     java -Djava.security.policy=config_dir/jsk-all.policy \
>          -jar install_dir/lib/start.jar \
>          config_dir/start-transient-mercury.config

This configuration uses the following additional files.

#### File config_dir/start-transient-mercury.config

Use this configuration source file to start transient Mercury using Jini ERI.

>     import org.apache.river.start.NonActivatableServiceDescriptor;
>     import org.apache.river.start.ServiceDescriptor;

>     org.apache.river.start {
>         private static codebase = "http://your_host:http_port/mercury-dl.jar"
>            + " http://your_host:http_port/jsk-dl.jar";
>         private static policy = "config_dir/jsk-all.policy";
>         private static classpath = "install_dir/lib/mercury.jar";
>         private static config = "config_dir/transient-mercury.config";

>         static serviceDescriptors = new ServiceDescriptor[] {
>     	new NonActivatableServiceDescriptor(
>     	    codebase, policy, classpath,
>     	    "org.apache.river.mercury.TransientMercuryImpl",
>     	    new String[] { config })
>         };
>     }

#### File config_dir/transient-mercury.config

Use this configuration source file to run transient Mercury using Jini ERI.

>     org.apache.river.mercury {
>         initialLookupGroups = new String[] { "your.group" };
>     }

### Starting Persistent Mercury using Jini ERI

To run a persistent Mercury, which stores information persistently but does not use the activation system to restart itself, using Jini ERI for remote communication, run the following command.

>     java -Djava.security.policy=config_dir/jsk-all.policy \
>          -jar install_dir/lib/start.jar \
>          config_dir/start-persistent-mercury.config

This configuration uses the following additional files.

#### File config_dir/start-persistent-mercury.config

Use this configuration source file to start persistent Mercury using Jini ERI.

>     import org.apache.river.start.NonActivatableServiceDescriptor;
>     import org.apache.river.start.ServiceDescriptor;

>     org.apache.river.start {
>         private static codebase = "http://your_host:http_port/mercury-dl.jar"
>            + " http://your_host:http_port/jsk-dl.jar";
>         private static policy = "config_dir/jsk-all.policy";
>         private static classpath = "install_dir/lib/mercury.jar";
>         private static config = "config_dir/persistent-mercury.config";

>         static serviceDescriptors = new ServiceDescriptor[] {
>     	new NonActivatableServiceDescriptor(
>     	    codebase, policy, classpath,
>     	    "org.apache.river.mercury.NonActivatableMercuryImpl",
>     	    new String[] { config })
>         };
>     }

#### File config_dir/persistent-mercury.config

Use this configuration source file to run persistent Mercury using Jini ERI.

>     import net.jini.id.UuidFactory;
>     import net.jini.jeri.BasicILFactory;
>     import net.jini.jeri.BasicJeriExporter;
>     import net.jini.jeri.tcp.TcpServerEndpoint;

>     org.apache.river.mercury {
>         initialLookupGroups = new String[] { "your.group" };
>         persistenceDirectory = "config_dir/mercury.log";
>         serverExporter = new BasicJeriExporter(
>     	TcpServerEndpoint.getInstance(obj_port),
>     	new BasicILFactory(),
>     	false,
>     	true,
>     	UuidFactory.create("obj_UUID_string"));
>     }

The obj_port is the fixed TCP port to use for listening for requests for this object. The obj_UUID_string is the {@linkplain net.jini.id.Uuid universally unique ID} for the exported object. These IDs have the form `"01234567-89ab-cdef-0123-456789abcdef"`.

Remember to remove the config_dir/mercury.log directory before restarting persistent Mercury if you want it to forget registrations and settings made in previous invocations.

### Starting Activatable Mercury using Jini ERI

To run an activatable Mercury, which stores information persistently and uses the activation system to restart itself, using Jini ERI for remote communication, run the following command.

>     java -Djava.security.policy=config_dir/jsk-all.policy \
>          -jar install_dir/lib/start.jar \
>          config_dir/start-activatable-mercury.config

You should remove the config_dir/group.log directory before running this command. Note that the activation system will restart the activatable Mercury service as needed until Mercury is shutdown.

Remember to remove the config_dir/mercury.log directory before running this command if you want Mercury to forget registrations and settings made in previous invocations.

This configuration uses the following additional files.

#### File config_dir/start-activatable-mercury.config

Use this configuration source file to start activatable Mercury using Jini ERI.

>     import org.apache.river.start.ServiceDescriptor;
>     import org.apache.river.start.SharedActivatableServiceDescriptor;
>     import org.apache.river.start.SharedActivationGroupDescriptor;

>     org.apache.river.start {
>         private static mercuryCodebase = "http://your_host:http_port/mercury-dl.jar"
>            + " http://your_host:http_port/jsk-dl.jar";
>         private static mercuryPolicy = "config_dir/jsk-all.policy";
>         private static mercuryClasspath = "install_dir/lib/mercury.jar";
>         private static mercuryConfig = "config_dir/activatable-mercury.config";

>         private static groupPolicy = "config_dir/jsk-all.policy";
>         private static groupClasspath = "install_dir/lib/sharedvm.jar";
>         private static groupPersistenceDirectory = "config_dir/group.log";

>         static serviceDescriptors = new ServiceDescriptor[] {
>     	new SharedActivationGroupDescriptor(
>     	    groupPolicy, groupClasspath, groupPersistenceDirectory,
>     	    null /* serverCommand */,
>     	    null /* serverOptions */,
>     	    null /* serverProperties */),
>     	new SharedActivatableServiceDescriptor(
>     	    mercuryCodebase, mercuryPolicy, mercuryClasspath,
>     	    "org.apache.river.mercury.ActivatableMercuryImpl",
>     	    groupPersistenceDirectory,
>     	    new String[] { mercuryConfig },
>     	    true /* restart */)
>         };
>     }

#### File config_dir/activatable-mercury.config

Use this configuration source file to run activatable Mercury using Jini ERI.

>     org.apache.river.mercury {
>         initialLookupGroups = new String[] { "your.group" };
>         persistenceDirectory = "config_dir/mercury.log";
>     }

@see net.jini.event.EventMailbox