Communicating via internal facets

An internal facet is an interface between two netlets in the same application. If we create a facet (i.e. anything which implements the IRemote marker interface) then this allows us to wrap it as an internal facet plugin:


public interface IInternalFacetProvider
{
    /**
     * Fetch a facet.
     *
     * @param facet   Facet that needs to be returned
     * @param arg     Facet-specific argument.
     * @return    Object which can be cast into the facet type
     *            and used.
     */
    public IRemote getInternalFacet(String facet, Serializable arg)
        throws BeatrixFacetException;

    /** Utility class helping lookup */
    public static class Get
    {
        /** Get the only instance of this plugin in the given manager.
         * Only the first such plugin is returned. If there isn't one then
         * an ArrayIndexOutOfBoundsException is thrown.
         */
        public static IInternalFacetProvider one(IPluginManager pm)
        {
            return ((IInternalFacetProvider)pm.lookup(IInternalFacetProvider.class)[0]);
        } 
    }
}

For example we might like a diary available to all our netlets, but only implemented on some netlets. If we have a facet com.mycompany.IDiary we can write it as a plugin:


public class DiaryPlugin implements IPlugin, IInternalFacetProvider
{
    // ...some work omitted

    public IRemote getInternalFacet(String facet, Serializable diary_name)
    {
        return (IDiary)_diary_collection.getDiary((String)diary_name);
    }

    public boolean init(IPluginManager m, Object arg)
    {
        // ...load up _diary_collection
    }

    public void shutdown()
    {
        // ...write diaries to disk
    }
}

We choose netlet N1 to carry this implementation, so elsewhere we add the plugin to its plugin manager. This is in the code for N1:


    _plugin_manager.add(IDiary.class.getName(), DiaryPlugin.class, null, false);

And now any netlet which has a handle to N1 can get this facet. In netlet N2 we can write this:


    INetletHandle n1 = //...handle to netlet N1
    IDiary d = (IDiary)n1.getInternalFacet(IDiary.class.getName(), "Bob Jones");

Now N2 can use the IDiary interface as implemented on N1. For details on netlet handles see the IPeerSupport interface (Section [*]).

What happens in N2's getInternalFacet() call is this:

  1. Our call to getInternalFacet() on the netlet handle calls that method on netlet N1--the Manager, Worker or AccessPoint class.
  2. This scans its plugin manager for any IFacetProvider plugin that was added with the facet name, com.mycompany.IDiary (obtained using the Class.getName() method). It finds the DiaryPlugin class we added. This plugin will be initialised if it wasn't already.
  3. It calls that facet provider's getInternalFacet() method with the arguments given: com.mycompany.IDiary and Bob Jones. So it will return the ``Bob Jones'' diary from _diary_collection.
Some points to note:

Nik Silver 2002-03-09