TrackStudio Enterprise 3.5
Implementing Adapters

The following topic describes adapter development.

An adapter is a class which implements the com.trackstudio.app.adapter.Adapter interface. Each subsystem in TrackStudio has its own interface, inherited from gran.app.adapter.Adapter. For instance, to implement an export adapter, you must implement the class, which implements the com.trackstudio.app.adapter.ExportAdapter interface. Adapters are stateless components, i.e. they do not have an internal state and do not remember the history of the previous calls. 

The list of the loadable adapters can be found in trackstudio.adapter.properties, for example:

adapter.email com.trackstudio.app.adapter.email.BaseFilterNotifyAdapter

If you need to execute a pipeline of some adapters (implementing the same interface) to perform some operation, you must put them in one line using ';' as a separator, for example:

adapter.store com.trackstudio.app.adapter.store.BaseStoreAdapter;
              com.trackstudio.app.adapter.store.MailImportMessageStoreAdapter;
              com.trackstudio.app.adapter.store.MailImportTaskStoreAdapter;
              com.trackstudio.app.adapter.store.CleanStoreAdapter;
              com.trackstudio.app.adapter.store.PostProcessingStoreAdapter

If there are two identical adapters in the list, only the first of them will be executed. If there is an adapter not implementing the required interface in the list, it is not loaded. 

TrackStudio assumes each type of adapter as consists of three components: the adapter interface, the proper adapter, and AdapterManager establishing the pipeline. 

Let's look the implementation and interaction of the system components in the work of adapters:

  1. Interface. The adapter interface must extend Adapter. The following requirements are demanded of the method signature:
  • The name of the interface must be SomethingAdapter
  • Every method must either throw GranException or not throw an exception.
  • The names of methods must end with Impl
  • If a method returns a value, this method must have a parameter result of a returning type, which must come last in the list of parameters. For example,
boolean authorizeImpl(String userId,
                      String password,
                      boolean result)
              throws GranException;
  • Persistent objects (with rare exception) are passed either by their string identifier or in the collections java.util.Collection, java.util.LinkedList, etc. In the case of an ID passing of the object, to continue working you must open a Hibernate session and load the object. When using the object list you do not have to open a session (remember that in this case each object in the collection must be Hibernate-initialized). If executing an adapter results in changes in the persistent object, you must always open and close the session. It is also recommended that you use transactions in this case.

Interface example:

package com.trackstudio.app.adapter;

import com.trackstudio.exception.GranException;

public interface AuthAdapter extends Adapter {
    boolean authorizeImpl(String userId, String password, boolean result)
              throws GranException;
    void changePasswordImpl(String userId, String password)
              throws GranException;
}
  1. An adapter has the following structure:
package com.trackstudio.app.adapter.auth;

public class SimpleAuthAdapter implements AuthAdapter {

    public boolean init() {
        return true;
    }

    public String getDescription() {
        return "Basic Database Authentication Adapter";
    }

    public boolean authorizeImpl(String userId, String password, boolean result)
         throws GranException {
        ...
    }

    public void changePasswordImpl(String userId, String password)
         throws GranException {
        ...
    }
}

Within an adapter, methods can be called only through AdapterManager. Direct calling *Impl-methods is not recommended as it may cause problems when enhancing the system.

  1. XXXAdapterManager controls the lists of adapters supporting the defined interface and is responsible for the correct passing of the parameters.

The system enhancement is carried out through classes implementing the existing interfaces (for example, com.trackstudio.app.adapter.AuthAdapter). At the same time, you do not have to modify the initial system code, the adapter interface, or AdapterManager. 

To call the adapters, a singleton class AdapterManager is used. This class stores the list of all adapters available on the system and allows registration of new adapters in the system. To call a method (e.g. for exporting), you must execute the following:

AdapterManager.getInstance().getExportAdapterManager()
                            .export(taskid, userid);