This page shows how to create various types of connected system plug-in configurations and how to use them to meet your use case.
Fields are created by calling the setProperties(PropertyDescriptor...)
method on the SimpleConfiguration
object that has been passed to the getConfiguration
method. In these examples you may see field properties (such as isExpressionable
) not explicitly set when they are required. That is because these fields have defaults that result in valid configurations.
To create an input field for plain text, use the textProperty()
method.
1
2
3
return simpleConfiguration.setProperties(
textProperty("username").label("Username").build()
);
To create an input field that will store sensitive data, use the encryptedTextProperty()
method. Values gathered through an encrypted text field are encrypted before being stored, cleared on export, must be provided on import via the properties file, and cannot be retrieved by the client after save.
Note: Encrypted text fields are only allowed in connected systems.
1
2
3
4
return simpleConfiguration.setProperties(
textProperty("username").label("Username").build(),
encryptedTextProperty("password").label("Password").build()
);
To create a dropdown field, create a text field and provide a list of choices that can be selected from the dropdown. The name
method represents how the value is displayed to the user and the value
method is how the value is stored in the SimpleConfiguration. We have the dropdownProperty
method to help accomplish this.
1
2
3
4
5
6
7
return integrationConfiguration.setProperties(
dropdownProperty("state", Arrays.asList(
choice().name("Maryland").value("MD").build(),
choice().name("Virginia").value("VA").build())
.label("State")
.build()
);
Additional information can be added to the field as an instruction, a tooltip (description) or placeholder text. This information helps a user understand how to interact with the field.
1
2
3
4
textProperty("username").label("Username")
.instructionText("This will be your work email")
.placeholder("fake.name@appian.com")
.build()
To create a boolean field, use the booleanProperty()
method. Boolean properties can render as a radio button or checkbox based on the provided displayMode()
.
1
2
3
4
5
6
return integrationConfiguration.setProperties(
booleanProperty("verbose-output").label("Verbose Output")
.displayMode(BooleanDisplayMode.RADIO_BUTTON) //Default display mode is checkbox
.description("Should the request return additional metadata?")
.build()
);
To mark a field as required use the isRequired()
method on the property descriptor builder. The developer will be able to see which fields are required when configuring an integration or connected system.
1
2
3
4
5
textProperty("username").label("Username")
.instructionText("This will be your work email")
.placeholder("fake.name@appian.com")
.isRequired(true)
.build()
Tip: All template methods can be still executed with null values for required fields. Always have appropriate null handling for all fields, even required ones.
If a field's values are likely to change between environments use the isImportCustomizeable(true)
method on the property builder.
1
2
3
4
5
6
7
8
9
10
11
12
return simpleConfiguration.setProperties(
textProperty("username").label("Username")
.instructionText("This will be your work email")
.placeholder("fake.name@appian.com")
.isRequired(true)
.isImportCustomizable(true)
.build(),
encryptedTextProperty("password").label("Password")
.isRequired(true)
.description("Make sure to keep this value a secret!")
.build()
);
Import customizable fields can be set through the import customization file on import. Only connected systems can have importCustomizable fields.
If you want to have dynamic fields then you must create a field where the refresh policy is set to ALWAYS
. This triggers a call to getConfiguration
when the value of that field is changed. This example shows how to create a dynamic field, retrieve the user-entered value and use that value to determine behavior. Only integrations can have dynamic behavior.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
String state = integrationConfiguration.getValue("state");
if(state == null) {
return integrationConfiguration.setProperties(
textProperty("state").label("State")
.choices(
Choice.builder().name("Maryland").value("MD").build(),
Choice.builder().name("Virginia").value("VA").build())
.refresh(RefreshPolicy.ALWAYS)
.build()
);
}
String stateFlower = null;
if("VA".equals(state)) {
stateFlower = "American dogwood";
} else if ("MD".equals(state)) {
stateFlower = "Black-Eyed Susan";
}
return integrationConfiguration.setProperties(
textProperty("state").label("State")
.choices(
Choice.builder().name("Maryland").value("MD").build(),
Choice.builder().name("Virginia").value("VA").build())
.refresh(RefreshPolicy.ALWAYS)
.build(),
textProperty("state-flower").label("State Flower")
.instructionText(String.format("The official flower of %s", state))
.isReadOnly(true)
.build()
).setValue("state-flower", stateFlower);
To send a document, create a document input field using the documentProperty()
method.
1
2
3
4
5
return integrationConfiguration.setProperties(
documentProperty("resume").label("Resume")
.instructionText("Upload your resume here.")
.build()
);
This will allow the developer to provide a document from Appian to your plug-in. The Document
class then gives you access to an InputStream
of the contents along with other metadata.
To allow developers to specify non-static values (SAIL expressions and rule inputs) in input fields, use the isExpressionable(true)
method on the property builder.
1
2
3
4
5
6
return integrationConfiguration.setProperties(
integerProperty("sandwiches").label("Number of Sandwiches Remaining")
.instructionText("This value will be used to predict when there will be no remaining sandwiches")
.isExpressionable(true)
.build()
);
EXPRESSION
, then the field must also be marked as expressionable.To display a field as an expression box, use the displayHint(DisplayHint.EXPRESSION)
on the field's builder. The field be marked as expressionable and Connected systems cannot have fields with DisplayHint.EXPRESSION
.
1
2
3
4
5
6
7
return integrationConfiguration.setProperties(
integerProperty("sandwiches").label("Number of Sandwiches Remaining")
.instructionText("This value will be used to predict when there will be no remaining sandwiches")
.displayHint(DisplayHint.EXPRESSION)
.isExpressionable(true)
.build()
);
Complex types are referred to as "local types" in the SDK. Local types are custom dynamic data structures that you can define to fit your specific needs. To create a local type input, use the localTypeProperty()
method. To create the local type definition, use the localType()
method. List types must have an itemType
provided, and be expressionable with a DisplayHint
type of expression. List types cannot have a placeholder.
1
2
3
4
5
6
7
8
9
10
11
12
LocalTypeDescriptor addressType = localType("address").properties(
textProperty("street").label("Street Name").build(),
integerProperty("zip").label("Zip Code").build(),
textProperty("state").label("State")
.choices(
Choice.builder().name("Maryland").value("MD").build(),
Choice.builder().name("Virginia").value("VA").build())
.build()
).build();
return integrationConfiguration.setProperties(
localTypeProperty(addressType).label("Address").isExpressionable(true).build()
);
To create a list input, use the listTypeProperty()
method. To set the item type, call the itemType()
method, and provide a SystemType
or local type.
1
2
3
4
5
return integrationConfiguration.setProperties(
listTypeProperty("testscores").label("Test Scores")
.itemType(SystemType.DOUBLE)
.build()
);
In order to create a list input of complex type, you will first need to register the complex type using the localTypeProperty()
method. Otherwise, you will not be able to reference the complex type in the definition of your list type input.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
LocalTypeDescriptor addressType = localType("address").properties(
textProperty("street").label("Street Name").build(),
integerProperty("zip").label("Zip Code").build(),
textProperty("state").label("State")
.choices(
Choice.builder().name("Maryland").value("MD").build(),
Choice.builder().name("Virginia").value("VA").build())
.build()
).build();
localTypeProperty(addressType, "neededToRegister");
return integrationConfiguration.setProperties(
listTypeProperty("addresslist").label("Address List")
.itemType(TypeReference.from(addressType))
.isExpressionable(true)
.build()
);
Values entered by the user are stored in the SimpleConfiguration
object.
To retrieve values use:
getValue(String)
- Gets a value at the top level (not in a local type property).getValue(PropertyPath)
- Gets any value. getValue(new PropertyPath("key"))
is equivalent to getValue("key")
getValue()
could be null, so don't store values in primitivesgetConfiguration()
method, values are not available for the following fields:
Suppose you have a SimpleConfiguration
defined as follows and all of the _KEY
variables are defined as unique strings:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
LocalTypeDescriptor localTypeDescriptor = localType("localType")
.property(
textProperty(INNER + TEXT_PROP_KEY).build()
).build();
return simpleConfiguration.setProperties(
textProperty(TEXT_PROP_KEY).build(),
doubleProperty(DOUBLE_PROP_KEY).build(),
integerProperty(INTEGER_PROP_KEY).build(),
documentProperty(DOCUMENT_PROP_KEY).build(),
listTypeProperty(LIST_PROP_KEY).itemType(SystemType.INTEGER).build(),
localTypeProperty(localTypeDescriptor, LOCAL_TYPE_PROP_KEY).isExpressionable(true).build(),
booleanProperty(BOOL_PROP_KEY).build(),
encryptedTextProperty(ENC_PROP_KEY).build()
);
Retrieving text value with key TEXT_PROP_KEY
String value = simpleConfiguration.getValue(TEXT_PROP_KEY);
Retrieving double value with key DOUBLE_PROP_KEY
Double value = simpleConfiguration.getValue(DOUBLE_PROP_KEY);
Retrieving integer value with key INTEGER_PROP_KEY
Integer value = simpleConfiguration.getValue(INTEGER_PROP_KEY);
Retrieving document value with key DOCUMENT_PROP_KEY during execution
com.appian.connectedsystems.templateframework.sdk.configuration.Document value = simpleConfiguration.getValue(DOCUMENT_PROP_KEY);
Retrieving integer list value with key LIST_PROP_KEY during execution
List<Integer> value = simpleConfiguration.getValue(LIST_PROP_KEY);
Retrieving local type value with key LOCAL_TYPE_PROP_KEY during execution
Map<String, Object> value = simpleConfiguration.getValue(LOCAL_TYPE_PROP_KEY);
Retrieving boolean value with key BOOL_PROP_KEY
Boolean value = simpleConfiguration.getValue(BOOL_PROP_KEY);
Retrieving EncryptedText value with key ENC_PROP_KEY
String value = simpleConfiguration.getValue(ENC_PROP_KEY);
Suppose you have the following simpleConfiguration
object:
1
2
3
4
5
6
7
8
9
10
11
12
13
String TEXT_PROP_KEY = "textPropertyKey";
String LOCAL_TYPE_KEY = "localTypePropertyKey";
LocalTypeDescriptor localTypeDescriptor = localType("localType")
.property(
textProperty(TEXT_PROP_KEY).build()
).build();
simpleConfiguration.setProperties(
localTypeProperty(localTypeDescriptor)
.key(LOCAL_TYPE_KEY)
.build()
);
To access the value in the text field:
String text = simpleConfiguration.getValue(new PropertyPath(LOCAL_TYPE_KEY, TEXT_PROP_KEY));
To access values from the connected system in an integration's getConfiguration
method:
1
2
3
4
5
6
7
8
9
@Override
protected SimpleConfiguration getConfiguration(
SimpleConfiguration integrationConfiguration,
SimpleConfiguration connectedSystemConfiguration,
PropertyPath propertyPath,
ExecutionContext executionContext) {
String apiKey = connectedSystemConfiguration.getValue("API_KEY_PROPERTY_KEY");
.....
}
To access values from the connected system in an integration's execute
method:
1
2
3
4
5
6
7
8
@Override
protected IntegrationResponse execute(
SimpleConfiguration integrationConfiguration,
SimpleConfiguration connectedSystemConfiguration,
ExecutionContext executionContext) {
String apiKey = connectedSystemConfiguration.getValue("API_KEY_PROPERTY_KEY");
....
}
It can be useful to set values on read-only fields to display information to the developer. To set a value on a property use:
simpleConfiguration.setValue("propertyKey", object)
simpleConfiguration.setValue(new PropertyPath("localKey", "nestedKey", object)
Values for expressible and document fields cannot be set, only cleared.
Expression.emptyExpression()
to clear it.Document.emptyDocument()
to clear it.Create and Use a Configuration