This blog post will be about sharing what I learned around developping
Funambol Connector. It is not intended to be complete or a replacement of
any Funambol tutorial. However, I'll try to give some tips here to better
understand.


Basic documentation


First things firsts, before anything else, you should have a serious look
at the
Funambol module development tutorial
. This will guide you in the
creation of a dummy connector. However, this paper is not complete enough
for new developers. Thus I'll try to explain some difficult points here.


Take care of which API reference you are reading. The j2se and DS-server
APIs are different with similar concepts and names...


Understanding modules


First of all, the tutorial is about modules and not connectors... what's
the difference ? In fact a module is a general additionnal component to
Funambol which contains one or more connectors.


As you might have understood from the tutorial, the module is composed of several parts:



  • The Java sources of you module, of course.

  • SQL scripts used for installing and uninstalling the module and
    connector in the Funambol DS server.

  • An optional install/install.xml ant script to run at the installation
    time

  • Dependencies libraries.


There are two things to develop to create a complete connector:



  • The Synchronisation source type class, which will access the data.

  • The configuration panel that will be shown in the Funambol admin tool
    for easy configuration of the new synchronization source type.


Why are SQL scripts needed and what are they for ? Funambol is connected to a database describing the connectors and their informations. Thus the informations about your new connector have to be stored in order for it to be used. These informations include the class name of the source type and the one of the panel. There are three possible SQL scripts:



  • create_schema.sql, to use if the module needs a custom data
    schema

  • drop_schema.sql, called when uninstalling the module to remove the
    data

  • init_schema.sql, called when installing the module to fill the
    data


SyncSource interface


The synchronization source type of your connector has to implement the
ds-serveur SyncSource interface. These next lines will try to detail what
the different methods are for.


Synchronization starting and ending



public void beginSync(SyncContext ctx) throws SyncSourceException;
public void endSync() throws SyncSourceException;
public void commitSync() throws SyncSourceException;

These methods are called to initialize and stop the synchronization. Thes
can be used, for example, to start and stop a connection to the source. The
commit method will commit the changes made during the synchronization to the source.


Element getters



public abstract SyncItemKey[] getAllSyncItemKeys()
throws SyncSourceException;

This method will have to return all the items to synchronize in the
source. This method is used in the synchronization mode. The result is an
array of all the unique keys describing each element.



public abstract SyncItemKey[] getDeletedSyncItemKeys(Timestamp sinceTs, Timestamp untilTs)
throws SyncSourceException;
public abstract SyncItemKey[] getNewSyncItemKeys(Timestamp sinceTs, Timestamp untilTs)
throws SyncSourceException;
public SyncItemKey[] getUpdatedSyncItemKeys(Timestamp since, Timestamp until)
throws SyncSourceException;

These three methods will return the deleted, new and updated items
between the since and until timestamps. These methods are used in the fast
synchronization mode. The result is an array of all the unique keys
describing each element.



public abstract SyncItem getSyncItemFromId(SyncItemKey syncItemKey)
throws SyncSourceException;

This method returns and item from its key. This is a difference between
the client and server SyncSource interfaces: from the server side, using
only keys and getting the item at the very last time helps to avoid big
memory uses.


Elements setters



public abstract void removeSyncItem(SyncItemKey syncItemKey, Timestamp time, boolean softDelete)
throws SyncSourceException;
public abstract SyncItem updateSyncItem(SyncItem syncInstance)
throws SyncSourceException;
public abstract SyncItem addSyncItem(SyncItem syncInstance)
throws SyncSourceException;

These methods will remove, add and update items in the source. The
returned sync item correspond to the inserted or updated item. The update
and add methods should solve the conflicts between the items that is already
present on the server and the one that is about to be added or
updated.


Extra methods



public abstract SyncItemKey[] getSyncItemKeysFromTwin(SyncItem syncItem)
throws SyncSourceException;

This method returns the twin items keys, i.e. the keys of the items that
are considered as identical. This notion of identical items is defined in
this method.



public abstract void setOperationStatus(String operationName, int status, SyncItemKey[] keys);

This method is called by the DS-server to notify the status of an
operation. The operation name can be either one of "Add",
"Replace" or "Delete".


Configuration panel implementation


To create a new source configuration panel, you will need to extend the
SourceManagementPanel class. The only thing to know here is to set
the following properties into your synchronization source when clicking on
the validation button. The validation method should contain the following
skeleton:



if (getSyncSource() instanceof JCRSyncSource) {
JCRSyncSource source = (JCRSyncSource)getSyncSource();
source.setSourceURI(uriText.getText().trim());
source.setName(nameText.getText().trim());
source.setType(typeText.getText().trim());
// TODO set your source specific values
ContentType[] contentTypes = new ContentType[] {
new ContentType("text/plain", "1.0")
};
source.setInfo(new SyncSourceInfo(contentTypes, 0));
}

You just have to replace the TODO comment by lines setting the specific
values to your source. Of course, you need to replace the JCRSyncSource
class by your SyncSource class.


(Post originally written by Cedric Bosdonnat on the old Nuxeo blogs.)