User-defined start classes

You can define start classes that are loaded automatically when the server is started. The purpose of this feature is to allow you to write Java code that executes at the time the MobiLink server starts the JVM—before the first synchronization. This means you can create connections or cache data before a user synchronization request.

You do this with the DMLStartClasses option of the mlsrv11 -sl java option. For example, the following is part of a mlsrv11 command line. It causes mycl1 and mycl2 to be loaded as start classes.

-sl java(-DMLStartClasses=com.test.mycl1,com.test.mycl2)

Classes are loaded in the order in which they are listed. If the same class is listed more than once, more than one instance is created.

All start classes must be public and must have a public constructor that either accepts no arguments or accepts one argument of type ianywhere.ml.script.ServerContext.

The names of loaded start classes are output to the MobiLink log with the message "Loaded JAVA start class: classname".

For more information about Java virtual machine options, see -sl java option.

To see the start classes that are constructed at server start time, see getStartClassInstances method.

Example

The following is a start class template. It starts a daemon thread that processes events and creates a database connection. (Not all start classes need to create a thread but if a thread is spawned it should be a daemon thread.)

import ianywhere.ml.script.*;
import java.sql.*;

public class StartTemplate extends
    Thread implements ShutdownListener {
    ServerContext   _sc;
    Connection      _conn;
    boolean         _exit_loop;

    public StartTemplate(ServerContext sc) throws SQLException {

        // Perform setup first so that an exception 
        // causes MobiLink startup to fail.
        _sc = sc;

        // Create a connection for use later.
        _conn = _sc.makeConnection();

        _exit_loop = false;
        setDaemon(true);
        start();
    }

    public void run() {
        _sc.addShutdownListener(this);

        // run() cannot throw exceptions.
        try {
            handlerLoop();
            _conn.close();
            _conn = null;
        }
        catch(Exception e) {
    
            // Print some error output to the MobiLink log.
            e.printStackTrace();
 
            // This thread shuts down and so does not 
            // need to be notified of shutdown.
            _sc.removeShutdownListener(this);
    
            // Ask server to shutdown so that this fatal
            // error is fixed.
            _sc.shutdown();
        }
        // Shortly after return this thread no longer exists.
        return;
    }
 
    // stop our event handler loop
    public void shutdownPerformed(ServerContext sc) {
        try {
            // Wait max 10 seconds for thread to die.
            join(10*1000);
        }
        catch(Exception e) {
            // Print some error output to the MobiLink log.
            e.printStackTrace();
        }
    }

    private void handlerLoop() throws InterruptedException {
        while (!_exit_loop) {
            // Handle events in this loop. Sleep not
            // needed, block on event queue.
            sleep(1 * 1000);
        }
    }
}