{{sidenavigation.sidenavigationExpandLabel}}
{{getMsg('Help_YouAreHere')}}: {{page.title}} {{page.title}}
{{$root.getMsg("downLoadHelpAsPdf")}} {{helpModel.downloadHelpPdfDataStatus}}

Extending Task Planner

All components of a task can be implemented yourself. The components are triggers, jobs, result actions and series.

In this guide any trigger, job, result handler, or series is called a 'component' because many explanations and relations are the same for all components.

To add new components, a plugin is required which has the taskplanner plugin as a dependency. See Plugins Guide for general help on how to create an own plugin.

For each component, you must implement a factory class which provides all required information and a real implementation of the component.

Life cycle

When defining a new task, either by using the Task Planner web application or the public API, then that task will consist of component definitions. The definitions only contain configured settings or other meta information, but no functionality or program logic.

Example: The TriggerDefinition for the Time Trigger contains the execution time and the repeat interval.

For each kind of component, such as the time trigger and email result action, a factory class exists and is registered in ServerPluginManager. The factory is responsible to create, validate, and provide information about the component.

Example: The TimeTriggerFactory for the Time Trigger specifies which options can be set in the web application, what information is displayed, and will create a TimeTrigger implementation.

The factory produces the real implementation of the component, like a real job which does something when executed.

Example: The TimeTrigger contains the program logic which will start tasks of the Task Planner according to the settings configured in the definition.


In short form: Definition → Factory → Implementation


The moment when a real implementation is constructed with the factory depends on the component: Jobs, result actions, and series are created when the task is executed and a trigger is created when the task is activated.

When adding a new kind of component, you must implement a new factory and a new component implementation, but no new definition because the definitions are all the same for one component type.

Example: All triggers are defined with a TriggerDefinition, but each kind of trigger has its own TriggerFactory and Trigger implementation class.

Component Keys

A kind of component is identified with a unique key, e.g. 'trigger.time' for the time trigger. The key is called EXTENSION_NAME. The factory which is responsible to create the implementation must know the key for that component. Predefined Factory classes expose a public constant EXTENSION_NAME which can be helpful when using the public API.

The definition of a component also contains that key so the corresponding factory can be located. Additionally it can (optionally) contain some properties which typically affect the implementation behavior, e.g. the repeat interval of the time trigger.

Component Factory

The main objective of the factory is to construct an implementation for the definition which has been set up by using the Task Planner web application or the public API. For example the TriggerFactory.createInstanceFrom() creates a Trigger object from a TriggerDefinition.

Other methods of the factory provide information about possible fields and settings of the component. If you do not want to use the Task Planner web application, then some methods of the factory can be left empty.

Method summary:

  • validate(definition, taskID) - here the settings can be validated. This can be left empty if no validation is required or desired.
  • getSummary(definition) - provides a human readable summary of the configured component which is used in the web application. You can return null if you do not use the web application.
  • createInstanceFrom( definition ) - here the actual component is constructed. This is the core method that must be implemented.
  • getInformation(taskID) - this provides information about the properties of the component and some display values for the web application. The fields defined here are also responsible to replace the placeholders with a value from the series if one is configured. If not using the web application, then you can most likely simply return null here, however keep in mind that the replacement of placeholders in a series will not work then.

There are some more methods which can be overridden but they are usually not required. See the documentation of the factory classes and its methods for more details.

Factory and Implementation classes

Which classes can be extended and what methods do they expose?

The factory base class is also the extension point for registering it in ServerPluginManager.

Example: spm.register( TriggerFactory.class, new TimeTriggerFactory() );

Trigger

To add a new kind of trigger you must extend com.inet.taskplanner.server.api.trigger.TriggerFactory and implement your trigger with the com.inet.taskplanner.server.api.trigger.Trigger interface.

Job

To add a new kind of job you must extend com.inet.taskplanner.server.api.job.JobFactory and implement your job with the com.inet.taskplanner.server.api.job.Job interface.

Additional factory methods

  • getResultFlavors(definition) - returns which ResultFlavor(s) this job will generate with the given settings. An empty list can also be returned if your job does not produce results.
  • validateCondition(definition) - here the condition settings can be validated if you use conditions.

Result actions

To add a new kind of result action you must extend com.inet.taskplanner.server.api.action.ResultActionFactory and implement your result action with the com.inet.taskplanner.server.api.action.ResultAction class.

Additional factory methods

  • getSupportedFlavors(definition) - returns which ResultFlavor(s) this result action is able to process with the given settings. If your action does not require any results then ResultFlavor.NONE should be returned.

Series

To add a new kind of series you must extend com.inet.taskplanner.server.api.series.SeriesFactory and implement your series with the com.inet.taskplanner.server.api.series.Series interface.

How to start

The recommended way how to add a new component:

  1. Create a plugin which has taskplanner as a dependency
  2. Create a factory class which extends the factory class for your component type (see above).
  3. Create a String constant for the KEY / EXTENSION_NAME and use that in your factory constructor.
  4. If your component has settings, then add public constants for the property keys of your settings. Optionally implement the validate method so it checks your settings for correctness.
  5. If your component will be used in the web application, then the methods getSummary() and getInformation() should be implemented, otherwise can be left to return null.
  6. If you want to use a series with your component, your component is a Job or ResultAction, and you are going to want to support placeholders in some settings of your component, then you must also implement the getInformation() method. For the placeholders, it is important that each property where you want placeholders to work must have a corresponding field representation (same property name) in the ResultActionInfo or JobInfo.
  7. Create the implementation class, see above. Let the createInstanceFrom() method create your implementation component and let it transfer the settings from your definition to your implementation class.
  8. Register your factory in ServerPluginManager

Example

Factory class

public class DTXActionFactory extends ResultActionFactory<ResultAction> {
 
    public static final String       EXTENSION_NAME = "DTX Action";
    public static final ResultFlavor DTX            = ResultFlavor.create( "DTX" ); //some custom flavor, you need some custom job which creates results of this type
    public static final String       PROPERTY_SYSTEM = "dtx system";
 
    public DTXActionFactory() {
        super( EXTENSION_NAME );
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public List<ResultFlavor> getSupportedFlavors( ResultActionDefinition definition ) {
        List<ResultFlavor> list = new ArrayList<>();
        list.add( DTX );
        return list;
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public ResultActionInfo getInformation( GUID taskID ) {
        //can return null if you do NOT use the web application AND you do not want to use placeholders in this result action
        //        return null;
        List<Field> fields = new ArrayList<>();
        //this is required if you want to use series and placeholders in PROPERTY_SYSTEM must be replaced
        fields.add( new TextField( PROPERTY_SYSTEM, "DTX System Host" ) );
 
        URL iconUrl = getClass().getResource( "path/to/your/icon/in/src/of/your/plugin" );
        return new ResultActionInfo( EXTENSION_NAME, "Send to DTX System", "Description of the Action", iconUrl, null, fields );
 
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    protected void validate( ResultActionDefinition definition, GUID taskID ) throws ValidationException {
        // can always be left empty
 
        String system = definition.getProperty( PROPERTY_SYSTEM );
        if( system == null ) {
            throw new ValidationException( "DTX System must be specified!!" );
        }
 
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    protected ResultAction createInstanceFrom( ResultActionDefinition definition ) {
        return new DTXResultAction( definition.getProperty( PROPERTY_SYSTEM ) );
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public SummaryInfo getSummary( ResultActionDefinition definition ) {
        //can return null if you do NOT use web gui
        List<SummaryEntry> entries = new ArrayList<>();
        entries.add( new SummaryEntry( "Transmit to DXT System", definition.getProperty( PROPERTY_SYSTEM ) ) );
        return new SummaryInfo( entries );
    }
 
}

Result action class

public class DTXResultAction extends ResultAction {
 
    private String dtxSystem;
 
    public DTXResultAction( String dtxSystem ) {
        this.dtxSystem = dtxSystem;
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    protected void handle( List<JobResultContainer> results ) throws TaskExecutionException {
        //we only process DTX results
        results.forEach( ( resultContainer ) -> {
            List<Result> dtxResults = resultContainer.getResults( DTXActionFactory.DTX );
            //... do send somewhere to dtxSystem ...
        } );
 
    }
 
}

In your Plugin class

@Override
public void registerExtension( ServerPluginManager spm ) {
    spm.register( ResultActionFactory.class, new DTXActionFactory() );
    //...
}
i-net CoWork
This application uses cookies to allow login. By continuing to use this application, you agree to the use of cookies.


Help - Extending Task Planner