Writing a singleton startable plugin

A Singleton startable plugin runs on a single server in the cluster.

Write a new class that implements the IStartablePlugin interface. Implement the following methods.

  • A start method to start your service.
  • A stop method to stop your service.
  • A property accessor function to get the State property from your startable plugin.

    This method returns a typecode from the typelist StartablePluginState: the value Stopped or Started. The administration user interface uses this property accessor to show the state to the user. Define a private variable to hold the current state and your property accessor (get) function can look simple.

    // Private variables...
    var _state = StartablePluginState.Stopped;
    
    ...
    
    // Property accessor (get) function...
    override property get State() : StartablePluginState {
      return _state // return our private variable
    }

    Alternatively, combine the variable definition with the shortcut keyword to simplify your code. You can combine the property definition with the variable definition in a single code statement.

    var _state : StartablePluginState as State

The plugin includes a constructor which is called on system startup. However, locate the service code in the plugin’s start method, not its constructor.

The start method must initialize the plugin’s State property by using an internal variable defined in the plugin. The variable’s value must be one of the supported values of the StartablePluginState class, such as Started or Stopped.

The start method can also start any desired listener code or threads, such as a JMS queue listener.

The start method accepts an argument that references a callback handler of type StartablePluginCallbackHandler. This callback is important if the startable plugin modifies any entity data, which most startable plugins do.

Any plugin code that affects entity data must be run within a method called execute. The execute method accepts an argument of a special type of in-line function called a Gosu block, which is described in the Gosu Reference Guide. The Gosu block itself accepts no arguments. The execute method is then passed to the callback handler.

If you do not need a user context, use the simplest version of the callback handler method execute, whose one argument is the Gosu block.

You do not need to create a separate bundle. If you create new entities to the current bundle, they are in the correct default database transaction the application sets up for you. Use the code returned by the Transaction.getCurrent method to get the current bundle if you need a reference to the current writable bundle.

The Java language does not directly support blocks. If you implement your plugin in Java, you cannot use a Gosu block but you can use an anonymous class to do the same thing.

The plugin’s start method also includes a boolean variable that indicates whether the server is starting. If true, the server is starting up. If false, the start request comes from the Startable Services user interface.

The following shows a simple Gosu block that changes entity data. This example assumes your listener defined a variable messageBody with information from your remote system. If you get entities from a database query, remember to add them to the current bundle.

The following example queries all User entities and sets a property on results of the query.

// Variable definition earlier in your class...
var _callback : StartablePluginCallbackHandler;

...

override function start( cbh: StartablePluginCallbackHandler, isStarting: boolean ) {
  _callback = cbh
  _callback.execute( \ -> {

    var q = gw.api.database.Query.make(User) // run a query
    var b = gw.Transaction.Transaction.Current // get the current bundle

    for (e in q.select()) {
      // Add entity instance to writable bundle, then save and only modify that result
      var writable_object = bundle.add(e) 

      // Modify properties as desired on the result of bundle.add(e)
      writable_object.Department = "Example of setting a property on a writable entity instance."
    }
  })
  // You do not need to commit the bundle here. The execute method commits after your block runs.
}

Note that to make an entity instance writable, save and use the return result of the bundle add method.

Just like your start method must set your internal variable that sets its state to started, your stop method must set your internal state variable to StartablePluginState.Stopped. Additionally, stop whatever background processes or listeners you started in your start method. For example, if your start method creates a new JMS queue listener, your stop method destroys the listener. Similar to the start method’s isStartingUp parameter, the stop method includes a boolean variable that indicates whether the server is shutting down now. If true, the server is shutting down. If false, the stop request comes from the Startable Services user interface.