Writing A jConduit
From JSyncManagerWiki
Contents |
Introduction
So you want to synchronize your PalmOS handheld with your favourite application or database, but such a facility doesn't exist, or you want to roll your own to control what goes onto your handheld and when.
So you want to synchronize your PalmOS handheld with your favourite application or database, but such a facility doesn't exist, or you want to roll your own to control what goes onto your handheld and when. You have some Java experience, but are new to the world of writing conduits.
This is the sort of thing the jSyncManager was designed to handle, and writing synchronization plug-ins (known as jConduits) can be quick and easy. This article will briefly describe what you need to begin.
(Note that this article will describe the steps to take to create a basic jConduit for synchronizing with an application or database at the record level, or via VFS. If you want to synchronize by writing PRC, PDB, or PQA files to the handheld, there is a special abstract jConduit class you can use to simplify this sort of synchronization called AbstractInstaller).
First off, you'll need the following to develop your jConduit:
- A Java Software Development Kit, version 1.4 or better recommended,
- The jSyncManager API (for this article, we're assuming the v3.2 API).
(You may also want the jSyncManager Core Application Set and the necessary transport APIs if you want to test your jConduit -- this article will only deal with what you need to write and compile your jConduit).
Once you have the parts you need, you'll want to ensure the jSyncManager API JAR file is somewhere where your JDK is going to be able to find it at compile time. Your jre/lib/ext directory is a good place, but if you don't have access to such a directory, anywhere in your CLASSPATH is fine. Various IDEs may also support importing the JAR for automatic compile-time interrogation.
Creating your jConduit Class
The first thing you'll want to do is to create a class in which to define your new jConduit. There are some rules the jSyncManager expects you to follow in creating a package name space for your jConduit to make it load-able:
- Your jConduit must be in a package inside the org.jSyncManager.Conduit package,
- The package name you choose must exactly match the name you choose for your jConduit class.
Thus, if you wish to call your jConduit MyConduit, you'd need to put it into the package org.jSyncManager.Conduit.MyConduit. Note that any supplementary classes you develop can be in whatever package you like -- only the jConduit entry point must be in the org.jSyncManager.Conduit package.
(The original rationale for this was that it was hoped that one day Java would have the ability to query the available packages/classes within a given package, allowing the jSyncManager to dynamically discover all available jConduits on a given system. This facility doesn't look like it's ever going to exist, so this requirement may change in a future release).
All jConduits are derived from a common ancestor class called AbstractConduit (found in the org.jSyncManager.API.Conduit package). As such, your jConduit class must sub-class AbstractConduit:
package org.jSyncManager.Conduit.MyConduit;
import org.jSyncManager.API.Conduit.AbstractConduit;
public class MyConduit extends AbstractConduit {
...
Implementing your Constructor
The jSyncManager jConduit API only recognizes one constructor signature, and that's the no parameter constructor. You may define other constructors, but they won't be called when your jConduit is installed. Only the no parameter constructor will be called.
Implementing the Basic Methods
If you check the JavaDoc (or the source code) for the AbstractConduit class, there are a number of available methods which you can override and extend. However, you are only required to implement three methods:
- getResourceBundleName()
- constructConfigPanel()
- startSync(ConduitHandler, DLPUserInfo)
Implementing the first method is easy. To encourage easily translatable jConduits, the jConduit subsystem has some built-in resource handling. Data such as the name of your jConduit, its description, and information on who wrote it can be contained within a resource bundle you specify. This method simply returns its fully-qualified name. Note that you can use any type of resource bundle supported by Java, including ResourceBundle, ListResourceBundle, or a PropertyResourceBundle. Due to the ease of maintenance, we generally use PropertyResourceBundles in the jSyncManager.
(Note that you can bypass the use of a resource bundle if you insist by re-implementing the getConduitName() and getConduitDescription() methods, but this is highly discouraged).
You can have whatever resource keys you want within your resource bundle, however the following resources must be present:
# Property file metadata Language=<name of the language these resources are in, in that language (ie: "English")> Translator=<name of the person who did the translation> Translator E-Mail=<e-mail address of the person who did the translation>
# jConduit Properties conduit.name=<name of the jConduit (ie: "MyConduit")> conduit.description=<description of your jConduit>
Note that if you wish to access resources within your bundle, you can call the getConduitResourceBundle() method inside your jConduit. The AbstractConduit class takes care of the loading and caching of your resource bundle the first time it is needed, so there is no need to load it yourself.
The next method to be implemented is the constructConfigPanel() method. This method returns a javax.swing.JPanel instance containing whatever GUI controls of widgets you want to present the user with when they choose to configure your jConduit. If you don't need any configuration (such as a path to a data file or directory, user login information, etc.), it's perfectly safe to just return null here.
The last method you need to implement is the startSync(ConduitHandler, DLPUserInfo) method. This method is the entry point to the actual meat of where your synchronization logic is going to reside, and provides you with the tool you need to open handheld database, read and write records, resources, VFS files, and entire database, so routine maintenance, query various handheld information and other synchronization tasks -- the ConduitHandler class. Describing the ConduitHandler class is outside the scope of this article, but it has extensive JavaDoc documentation to help you write your jConduit. Your jConduit is also passed a reference to the handheld users information, so you can do whatever special per-user validation or synchronization handling you may want to do (for example, you may want to use the handheld user name to get the rows of a database table specifically for that user in a local or networked DBMS).
A few things to note about the startSync method. First is that it throws the NotConnectedException. Your startSync implementation generally shouldn't catch this exception internally, as it is raised when the connection to the handheld has been lost -- and event that must be registered by the jConduit synchronization engine which calls your jConduit. If you must catch this exception to determine if the connection has been lost mid-sync, please be sure to re-throw it so the synchronization engine knows the connection has been lost, eg:
catch (NotConnectedException nce) {
System.err.println("Oops -- the connection was lost!");
throw nce;
} // end-catch
That's it -- once you've implemented these three methods, you have yourself a basic jConduit that can be loaded and run by the jSyncManager.
Other jConduit Methods
The AbstractConduit class also contains a number of other non-final methods which you can extend to enhance your jConduit in different ways. For example, you can specify tasks to be performed each time your jConduit is initialized. You can also specify the priority of your jConduit (which is very useful in cases where you're writing a suite of jConduits, and want them to run in a specific order). There is also a method to let you know when the user has dismissed the dialog containing your jConduits configuration panel, letting you know whether they selected "Ok" or "Cancel". For information on these methods, consult the JavaDoc for the AbstractConduit class.
A Note on jConduit Preference Storage
One of the nice tasks that the jConduit API can relieve you of is the storage of persistent jConduit state information. This can be user settings or other information you'd like to track concerning the synchronization process.
When the jSyncManager is exited normally, each jConduit instance is serialized to disk inside the users java.home directory (in a directory called .jsyncmanager). Each instance variable you define (and don't flag as transient) will be saved to disk at exit time. Each jConduit is deserialized at load time, will all previous state information intact.
This system has a few results you should be aware of:
- Your jConduits constructor is only called when your jConduit is initially installed. As it's serialized and deserialized thereafter, the constructor won't be called again. If you need to do any load-time jConduit initialization, do it in the initialize() method.
- You can make variables for which it doesn't make any sense to serialize all of the data so that they don't get stored at serialization time by specifying the Java transient modifier. If you need to use this because you're referencing a type which isn't serializable, you can initialize the variable in the initialize() method as above.
Further Reading

