Execute an Integration

This page shows how to set up execution for a connected system plug-in. There are examples of showing different types of execution results and debugging information to the designer.

Indicating a Successful Execution

Return IntegrationResponse.forSucess() in the template's execute() method.

Map<String,Object> resultMap = new HashMap<>();
resultMap.put("mySuccessfulResponseCode", 123);
return IntegrationResponse.forSucess(resultMap).build();

Indicating a Failed Execution

Return IntegrationResponse.forError() in execute() method.

1
2
3
4
5
6
7
8
9
IntegrationError integrationError = IntegrationError.builder()
    .title("My error title")
    .message("My error message")
    .detail("My error detail")
    .build();
    
return IntegrationResponse
    .forError(integrationError)
    .build();

Note: These strings in the IntegrationError should not be internationalized because they are used by designers to perform error handling. Changing these strings can break existing integrations.

Adding Debugging Information about the Request

When an integration fails or doesn't work as expected, the designer will need additional information about the request to debug the issue. For that reason, you should always add diagnostics to your IntegrationResponse.

Add information about the request using to the diagnostic map. Obfuscate any sensitive values because these values will be displayed to the designer in the request tab.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
String region = connectedSystemConfiguration.getValue(REGION_KEY);
String apiKey = connectedSystemConfiguration.getValue(API_KEY);
String city = integrationConfiguration.getValue(CITY_KEY);

Map<String,Object> requestDiagnostic = new HashMap<>();
requestDiagnostic.put("API Key", apiKey == null ? null, "********");
requestDiagnostic.put("Region", region);
requestDiagnostic.put("City", city);

IntegrationDesignerDiagnostic diagnostic = IntegrationDesignerDiagnostic.builder()
    .addRequestDiagnostic(requestDiagnostic)
    .build();

return IntegrationResponse.forSuccess(new HashMap<>())
    .withDiagnostic(diagnostic)
    .build();

Screen_Shot_2019-01-10_at_7.13.11_PM.png

Adding Debugging Information about the Response

When an integration fails or doesn't work as expected, the designer will need additional information about the response to debug the issue. For that reason, you should always add diagnostics to your IntegrationResponse.

Add information about the response using to the diagnostic map.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Step 1: Get information from the response
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpRequestBase myHttpRequest = new HttpGet("https://example.com");
HttpResponse httpResponse = httpClient.execute(myHttpRequest);

int statusCode = httpResponse.getStatusLine().getStatusCode();
String response = EntityUtils.toString(httpResponse.getEntity());

// Step 2: Add information to Integration Response
Map<String,Object> responseDiagnostic = new HashMap<>();
responseDiagnostic.put("Status Code", statusCode);
responseDiagnostic.put("Raw Response", response);

IntegrationDesignerDiagnostic diagnostic = IntegrationDesignerDiagnostic.builder()
        .addResponseDiagnostic(responseDiagnostic)
        .build();

return IntegrationResponse.forSuccess(new HashMap<>())
    .withDiagnostic(diagnostic)
    .build();

Screen_Shot_2019-01-10_at_4.59.07_PM.png

Adding Timing Information

If performance becomes an issue for a designer, it's important for them to understand the performance breakdown. Is the issue pre- or post-processing, or is the issue in the network connection or external system?

To add timing information, use the addExecutionTimeDiagnostic() on the diagnostic builder. We recommend you only record the time it takes for the external system to respond.

1
2
3
4
5
6
7
8
9
10
11
12
final long start = System.currentTimeMillis();
makeExternalCall(...)
final long end = System.currentTimeMillis();
final long executionTime = end - start;

IntegrationDesignerDiagnostic diagnostic = IntegrationDesignerDiagnostic.builder()
    .addExecutionTimeDiagnostic(executionTime)
    .build();

return IntegrationResponse.forSuccess(new HashMap<>())
    .withDiagnostic(diagnostic)
    .build();

Screen_Shot_2019-01-10_at_4.13.29_PM.png

Configuring HttpClient when a Proxy is Enabled

If a proxy is enabled by an Appian administrator, you must use the provided configuration data when making HTTP requests to non excluded hosts. Here is an example of using the proxy data to configure the Apache HttpClient.

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
32
33
34
//Step 1: Configure RequestConfig and add to HttpRequest
ProxyConfigurationData proxyConfigurationData = executionContext.getProxyConfigurationData();
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
if (proxyConfigurationData.isEnabled() && !proxyConfigurationData.isExcludedHost(httpPost.getURI().getHost())) {
  String proxyHost = proxyConfigurationData.getHost();
  int proxyPort = proxyConfigurationData.getPort();
  HttpHost proxy = new HttpHost(proxyHost, proxyPort);
  requestConfigBuilder.setProxy(proxy);
}
RequestConfig requestConfig = requestConfigBuilder.build();
httpPost.setConfig(requestConfig);

//Step 2: Configure Credential Provider
// If your 3rd party system requires username and password credentials, add them to the credential provider
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
    new UsernamePasswordCredentials("Your User Name",
        "Your Password"));

HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credentialsProvider);

// Add credentials to client if needed
if (proxyConfigurationData.isEnabled() && proxyConfigurationData.isAuthRequired()) {
  AuthScope authScope = new AuthScope(proxyConfigurationData.getHost(),
      proxyConfigurationData.getPort());
  Credentials credentials = new UsernamePasswordCredentials(proxyConfigurationData.getUsername(),
      proxyConfigurationData.getPassword());
  credentialsProvider.setCredentials(authScope, credentials);
}

//Step 3: Create a http client and execute with the configurations from above steps
HttpClient httpClient = HttpClientBuilder.create().build();
httpResponse = httpClient.execute(httpPost, context);

Sending Documents

When a configuration contains a document property, and the designer provides a value for the property, the configuration will contain a Document object during execution. Use the document object to acquire the an input stream of the document's data.

1
2
3
Document document = integrationConfiguration.getValue("documentKey");
String documentName = document.getFileName();
InputStream inputStream = document.getInputStream();
FEEDBACK