生成基础框架
首先使用官方的示例模板,并创建自定义Activity
git clone https://github.com/project-flogo/core cp -R core/examples/activity/* /myNewActivity
Metadata
第二步就是更新activity的meta信息,信息都在descriptor.json文件中,其中包含组件名称、版本、输出输出等信息。
-
name: The name of the activity (this should match the name of the folder the activity is in, like
HelloWorld
) -
version: The version of the activity (it is recommended to use semantic versioning for your activities)
-
type: This describes the type of contribution this is (this should be
flogo:activity
in this case) -
title: The application title to display in the web ui
-
ref: The Go package reference that will be used by the web ui to fetch the contribution upon installation
-
description: A brief description of your activity (this is displayed in the Flogo Web UI)
-
author: This is you!
-
settings: An array of name/type pairs that describe the activity settings. Note that activity settings are pre-compiled settings and can be used to increased performance. Settings are not fetched for every invocation
-
input: An array of name/type pairs that describe the input to the activity
-
output: An array of name/type pairs that describe the output to the activity
{ "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" } ]
比如示例中,需要一个anInput的输入,且类型是string,组件会返回一个string类型的anOutput输出。
功能逻辑
后面开始编写功能逻辑,主要是更新*.go这几个文件。
-
activity.go: which contains the actual activity implementation in go
-
activity_test.go: which contains unit tests for the activity
-
metadata.go: which contains the basic input/output/settings metadata. This is used by the engine
首先更新metadata.go文件中的输出输出配置信息等。
package sample 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 (r *Input) FromMap(values map[string]interface{}) error { strVal, _ := coerce.ToString(values["anInput"]) r.AnInput = strVal return nil } func (r *Input) ToMap() map[string]interface{} { return map[string]interface{}{ "anInput": r.AnInput, } } type Output struct { AnOutput string `md:"anOutput"` } func (o *Output) FromMap(values map[string]interface{}) error { strVal, _ := coerce.ToString(values["anOutput"]) o.AnOutput = strVal return nil } func (o *Output) ToMap() map[string]interface{} { return map[string]interface{}{ "anOutput": o.AnOutput, } }
这里的输出输出都需要实现FromMap与ToMap函数,FromMap表示输入map到输入结构体的转化。ToMap是结构体到map的转化。
后面开始构造主主力函数。
package sample import ( "github.com/project-flogo/core/activity" "github.com/project-flogo/core/data/metadata" ) func init() { _ = activity.Register(&Activity{}) //activity.Register(&Activity{}, New) to create instances using factory method 'New' } 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 }
核心功能都在Eval函数中。
单元测试
核心功能测试完毕后,使用单元测试测试下功能模块。
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) }
使用新组件
上传到git服务器,使用
flogo install github.com/yourusername/yourrepository
进行安装。