Hi,
We would like to add workflow/wizard functionality into our existing SmartGWT based application. I have searched forum and found those threads requesting workflow examples, but not a single line of working example code:
So, I would like to share what I have learned so far.
I have created a simple flow starting with fetching process state data from client-only DataSource.
Next node is a script task which logs data.
Then, there is a user task which displays a form in the window and allows user to enter data.
Modified data is processed by a gateway, which compares to specified criteria.
Then it goes to error flow and back to user form or, if data matches criteria (field1='value1')), to node saving data and finishing process.
Here is index.html js example code:
and MainEntryPoint.java gwt example code:
Data file for client-only ds test.data.xml:
I have been working with SmartClient 12.1d dated 2019.12.01.
Comments welcome.
MichalG
We would like to add workflow/wizard functionality into our existing SmartGWT based application. I have searched forum and found those threads requesting workflow examples, but not a single line of working example code:
- https://forums.smartclient.com/forum...amples-missing
- https://forums.smartclient.com/forum...rkflow-example
- https://forums.smartclient.com/forum...-by-sponsoring
- https://forums.smartclient.com/forum...orkflow-widget
- https://forums.smartclient.com/forum...rkflow-example
- https://forums.smartclient.com/forum...rkflow-feature
- https://forums.smartclient.com/forum...bpm-or-similar
So, I would like to share what I have learned so far.
I have created a simple flow starting with fetching process state data from client-only DataSource.
Next node is a script task which logs data.
Then, there is a user task which displays a form in the window and allows user to enter data.
Modified data is processed by a gateway, which compares to specified criteria.
Then it goes to error flow and back to user form or, if data matches criteria (field1='value1')), to node saving data and finishing process.
Here is index.html js example code:
Code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Client</title>
</head>
<body>
<script type="text/javascript">
var isomorphicDir = "isomorphic/";
</script>
<script src="isomorphic/system/modules-debug/ISC_Core.js"> </script>
<script src="isomorphic/system/modules-debug/ISC_Foundation.js"> </script>
<script src="isomorphic/system/modules-debug/ISC_Containers.js"> </script>
<script src="isomorphic/system/modules-debug/ISC_Grids.js"> </script>
<script src="isomorphic/system/modules-debug/ISC_Forms.js"> </script>
<script src="isomorphic/system/modules-debug/ISC_RichTextEditor.js"></script>
<script src="isomorphic/system/modules-debug/ISC_Calendar.js"> </script>
<script src="isomorphic/system/modules-debug/ISC_DataBinding.js"> </script>
<script src="isomorphic/system/modules-debug/ISC_Workflow.js"> </script>
<script src="isomorphic/skins/Graphite/load_skin.js"></script>
<script type="text/javascript">
var ds = isc.DataSource.create({
ID: "Test",
dataURL: "test.data.xml",
dataFormat: "xml",
dataProtocol: "postXML",
fields: [
{name: "id", type: "text", primaryKey: true},
{name: "field1", type: "text"},
{name: "field2", type: "text"},
],
clientOnly: true
});
var process = isc.Process.create({
//state: {field1: "valueA", field2: "valueB"},
elements : [
isc.ServiceTask.create({
ID: "data",
dataSource: ds,
outputFieldList: ["id", "field1", "field2"],
operationType: "fetch",
criteria: {field1: "valueA"},
nextElement: "script"
}),
isc.ScriptTask.create({
ID: "script",
inputFieldList: ["id", "field1", "field2"],
execute: function(input, inputRecord) {
isc.logEcho(inputRecord, "ScriptTask");
},
nextElement: "form"
}),
isc.UserTask.create({
ID: "form",
inputFieldList: ["id", "field1", "field2"],
outputFieldList: ["id", "field1", "field2"],
targetView: isc.Window.create({
ID: "wnd",
width: 300,
height: 120,
items: [isc.DynamicForm.create({
ID: "df",
fields:[
{name:"id", type:"text", hidden: true},
{name:"field1", type:"text"},
{name:"field2", type:"text"},
{title:"Submit", type:"submit"}
],
})]
}),
targetForm: "df",
nextElement: "gate"
}),
// isc.XORGateway.create({ ID: "gate", inputFieldList: "field1", criteria: advancedCriteria, failureElement: "errorFlow", nextElement: "goodFlow" }),
isc.DecisionGateway.create({
ID: "gate",
inputFieldList: ["id", "field1","field2"],
criteriaMap: {goodFlow: {field1: "value1"}, errorFlow: {field1: "value2"}},
defaultElement: "errorFlow"
}),
isc.ScriptTask.create({
ID:"goodFlow",
inputFieldList: ["id", "field1", "field2"],
execute: function(input, inputRecord) {
isc.warn("goodFlow - save");
isc.Window.getById("wnd").hide();
},
nextElement: "save"
}),
isc.ServiceTask.create({
ID: "save",
inputFieldList: ["id", "field1", "field2"],
dataSource: ds,
operationType: "update",
}),
isc.ScriptTask.create({
ID:"errorFlow",
inputFieldList: ["id", "field1", "field2"],
execute: function(input, inputRecord) {
isc.warn("errorFlow - try again");
},
nextElement: "script"
})
]
});
process.start();
</script>
</body>
</html>
and MainEntryPoint.java gwt example code:
Code:
package pl.com.tech4.client;
import com.google.gwt.core.client.EntryPoint;
import com.smartgwt.client.data.Criteria;
import com.smartgwt.client.data.DataSource;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.data.fields.DataSourceTextField;
import com.smartgwt.client.types.DSDataFormat;
import com.smartgwt.client.types.DSOperationType;
import com.smartgwt.client.types.DSProtocol;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.util.workflow.DecisionGateway;
import com.smartgwt.client.util.workflow.ProcessElement;
import com.smartgwt.client.util.workflow.ScriptTask;
import com.smartgwt.client.util.workflow.ServiceTask;
import com.smartgwt.client.util.workflow.UserTask;
import com.smartgwt.client.util.workflow.XORGateway;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.SubmitItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import java.util.HashMap;
public class MainEntryPoint implements EntryPoint {
@Override
public void onModuleLoad() {
layout();
}
private void layout() {
DataSource ds = new DataSource();
ds.setID("Test");
ds.setDataURL("test.data.xml");
ds.setDataFormat(DSDataFormat.XML);
ds.setDataProtocol(DSProtocol.POSTXML);
DataSourceTextField id = new DataSourceTextField("id");
id.setPrimaryKey(true);
DataSourceTextField field1 = new DataSourceTextField("field1");
DataSourceTextField field2 = new DataSourceTextField("field2");
ds.setFields(id, field1, field2);
ds.setClientOnly(true);
com.smartgwt.client.util.workflow.Process process = new com.smartgwt.client.util.workflow.Process() {
@Override
public void finished(Record state) {
SC.logWarn("Process finished.");
}
};
process.setID("process");
ServiceTask dataTask = new ServiceTask();
dataTask.setID("data");
dataTask.setDataSource(ds);
dataTask.setOutputFieldList("id", "field1", "field2");
dataTask.setOperationType(DSOperationType.FETCH);
dataTask.setCriteria(new Criteria("field1", "valueA"));
dataTask.setNextElement("script");
ScriptTask scriptTask = new ScriptTask() {
@Override
public Object execute(Object input, Record inputRecord) {
SC.logEcho(inputRecord.getJsObj(),"scriptTask");
return input;
}
};
scriptTask.setID("script");
scriptTask.setNextElement("form");
scriptTask.setInputFieldList("id", "field1", "field2");
UserTask formTask = new UserTask();
formTask.setID("form");
formTask.setNextElement("gate");
formTask.setInputFieldList("id", "field1", "field2");
formTask.setOutputFieldList("id", "field1", "field2");
final Window wnd = new Window();
wnd.setWidth(300);
wnd.setHeight(120);
DynamicForm df = new DynamicForm();
df.setID("df");
TextItem idItem = new TextItem("id");
idItem.setHidden(true);
TextItem field1Item = new TextItem("field1");
TextItem field2Item = new TextItem("field2");
SubmitItem submit = new SubmitItem("submit");
df.setFields(idItem, field1Item, field2Item, submit);
wnd.addItem(df);
formTask.setTargetView(wnd);
formTask.setTargetForm(df);
// XORGateway gateway = new XORGateway();
// gateway.setCriteria(criteria);
// gateway.setNextElement("goodFlow");
// gateway.setFailureElement("errorFlow");
DecisionGateway gateway = new DecisionGateway();
gateway.setID("gate");
HashMap criteriaMap = new HashMap();
criteriaMap.put("goodFlow", new Criteria("field1", "value1"));
criteriaMap.put("errorFlow", new Criteria("field1", "value2"));
gateway.setCriteriaMap(criteriaMap);
gateway.setDefaultElement("errorFlow");
ScriptTask goodFlowTask = new ScriptTask() {
@Override
public Object execute(Object input, Record inputRecord) {
SC.warn("goodFlow - save");
wnd.hide();
return input;
}
};
goodFlowTask.setID("goodFlow");
goodFlowTask.setInputFieldList("id", "field1", "field2");
goodFlowTask.setNextElement("save");
ServiceTask saveTask = new ServiceTask();
saveTask.setID("save");
saveTask.setDataSource(ds);
saveTask.setInputFieldList("id", "field1", "field2");
saveTask.setOperationType(DSOperationType.UPDATE);
ScriptTask errorFlowTask = new ScriptTask() {
@Override
public Object execute(Object input, Record inputRecord) {
SC.warn("errorFlow - try again");
return input;
}
};
errorFlowTask.setID("errorFlow");
errorFlowTask.setInputFieldList("id", "field1", "field2");
errorFlowTask.setNextElement("script");
ProcessElement[] elements = new ProcessElement[7];
elements[0] = dataTask;
elements[1] = scriptTask;
elements[2] = formTask;
elements[3] = gateway;
elements[4] = goodFlowTask;
elements[5] = saveTask;
elements[6] = errorFlowTask;
// process.setElements(elements);//does not work
process.getOrCreateJsObj();
process.setAttribute("elements", elements, true);
//Record state = new Record();
//state.setAttribute("field1Item", "value2");
//process.setState(state);
process.start();
}
}
Code:
<response>
<startRow>0</startRow>
<endRow>1</endRow>
<totalRows>2</totalRows>
<data>
<Test>
<id>1</id>
<field1>valueA</field1>
<field2>valueB</field2>
</Test>
<Test>
<id>2</id>
<field1>valueC</field1>
<field2>valueD</field2>
</Test>
</data>
<status>STATUS_SUCCESS</status>
</response>
Comments welcome.
MichalG
Comment