Creating Extensions
Flogo exposes a number of different extension points. You can easily extend the capabilities available, by building your own activities. In this tutorial, you explore the Activity contribution point and learn how to build a custom Activity in GO.
Step 1: Generate a basic framework
In this tutorial, you learn to build an Activity with two input parameters (salutation and name). The Activity built returns the concatenation of the two parameters and displays it on the console.
To create an Activity, you can clone the content from the project-flogo GitHub repository.
To start with, from the Flogo Core, you must pull the following example Activity.
git clone https://github.com/project-flogo/core
mkdir -p myNewActivity
cp -R core/examples/Activity/* /myNewActivity
Step 2: Update the Metadata
After you have pulled an example from the Flogo core, the first step is to update the descriptor.json file with the required information. The file contains the metadata for the new Flogo Activity. The metadata in the file contains the following elements.
| Element | Description |
|---|---|
| name |
The name of the Activity This must match with the name of the folder in which the Activity has been added. |
| version |
The version of the Activity. The semantic versioning for the activities must be used. |
| type |
The type of contribution. For example: |
| title | The application title to be displayed in the Flogo Web UI. |
| ref | The reference to the GO package that is used by the web UI to fetch the contribution details during the installation. |
| description |
A brief description of the Activity. This is displayed in the Flogo Web UI. |
| author | The creator of the Activity. |
| settings |
An array of name-type pairs that describe the Activity settings. Note:
|
| input |
An array of name-type pairs that describe the input to the Activity. The |
| output |
An array of name-type pairs that describe the output of the Activity. The |
The updated descriptor.json file must look as follows:
{
"name": "sample-Activity",
"type": "flogo:Activity",
"version": "0.0.1",
"title": "Sample Activity",
"description": "Sample Activity",
"homepage":"https://github.com/project-flogo/tree/master/examples/Activity",
"settings": [
{
"name": "aSetting",
"type": "string",
"required": true
}
],
"input": [
{
"name": "anInput",
"type": "string",
"required": true
}
],
"output": [
{
"name": "anOutput",
"type": "string"
}
]
Step 3: Build the Logic
Now, you must update the .GO files available in the current directory. The . GO files in the directory are as follows:
| File types | Description |
|---|---|
| Activity.go | contains the logic behind Activity implementation in GO |
| Activity_test.go | contains unit tests for the Activity |
| metadata.go | contains the basic input, output, and settings metadata used by the engine |
The first step is to update the metadata.go file. Define the input, output, and settings in the file. These details are used by the engine to build the Activity. Also it is used for leveraging contributions using the Flogo GO library. This enables GO developers to leverage strongly typed objects for IDE auto-completion.
The sample package of the metadata file must look like as follows:
import "github.com/project-flogo/core/data/coerce"
type Settings struct {
ASetting string `md:"aSetting,required"`
}
type Input struct {
AnInput string `md:"anInput,required"`
}
func (i *Input) FromMap(values map[string]interface{}) error {
strVal, err := coerce.ToString(values["anInput"])
if err != nil {
return err
}
i.AnInput = strVal
return nil
}
func (i *Input) ToMap() map[string]interface{} {
return map[string]interface{}{
"anInput": i.AnInput,
}
}
type Output struct {
AnOutput string `md:"anOutput"`
}
func (o *Output) FromMap(values map[string]interface{}) error {
strVal, err := coerce.ToString(values["anOutput"])
if err != nil {
return err
}
o.AnOutput = strVal
return nil
}
func (o *Output) ToMap() map[string]interface{} {
return map[string]interface{}{
"anOutput": o.AnOutput,
}
}The next step is to look at the Business logic and update the Activity.go file.
The sample package of the Activity file must look like as follows:
package sample
import (
"github.com/project-flogo/core/Activity"
"github.com/project-flogo/core/data/metadata"
)
func init() {
//Activity.Register(&Activity{}, New) to create instances using
factory method 'New'
_ = Activity.Register(&Activity{})
}
var ActivityMd = Activity.ToMetadata(&Settings{}, &Input{}, &Output{})
//New optional factory method, should be used if one Activity instance per configuration is desired
func New(ctx Activity.InitContext) (Activity.Activity, error) {
s := &Settings{}
err := metadata.MapToStruct(ctx.Settings(), s, true)
if err != nil {
return nil, err
}
ctx.Logger().Debugf("Setting: %s", s.ASetting)
act := &Activity{} //add aSetting to instance
return act, nil
}
// Activity is an sample Activity that can be used as a base to create a custom Activity
type Activity struct {
}
// Metadata returns the Activity's metadata
func (a *Activity) Metadata() *Activity.Metadata {
return ActivityMd
}
// Eval implements api.Activity.Eval - Logs the Message
func (a *Activity) Eval(ctx Activity.Context) (done bool, err error) {
input := &Input{}
err = ctx.GetInputObject(input)
if err != nil {
return true, err
}
ctx.Logger().Debugf("Input: %s", input.AnInput)
output := &Output{AnOutput: input.AnInput}
err = ctx.SetOutputObject(output)
if err != nil {
return true, err
}
return true, nil
}Now, to test and build the Activity, you must get below GO packages.
go mod init
go mod tidy
Step 4: Perform Unit Testing
After you have completed the building logic of the Activity, you must now perform a unit test. Unit testing gives you an automated way to test the Activity to make sure that it works. This also lets other developers run the same tests to validate the output.
The sample package of the Activity_test file must look like as follows:
package sample
import (
"testing"
"github.com/project-flogo/core/Activity"
"github.com/project-flogo/core/support/test"
"github.com/stretchr/testify/assert"
)
func TestRegister(t *testing.T) {
ref := Activity.GetRef(&Activity{})
act := Activity.Get(ref)
assert.NotNil(t, act)
}
func TestEval(t *testing.T) {
act := &Activity{}
tc := test.NewActivityContext(act.Metadata())
input := &Input{AnInput: "test"}
err := tc.SetInputObject(input)
assert.Nil(t, err)
done, err := act.Eval(tc)
assert.True(t, done)
assert.Nil(t, err)
output := &Output{}
err = tc.GetOutputObject(output)
assert.Nil(t, err)
assert.Equal(t, "test", output.AnOutput)
}To run all the test cases for your Activity run below command.
go test
On a successful run the result must look like as follows:
PASS
ok github.com/tibco/newConnector/myNewActivity 0.002s
Step 5: Upload the Activity in the Flogo App
Now, you can use the Activity in a Flogo app.
To install the Activity in Flogo, in the web UI, under Environment and Tools, go to the Extensions tab, and click Upload.