Service Activators

Service activators can be used to do http calls to the backend via pure configuration.

  • Data from the state can be sent to the backend via a mapping configuration
  • Response values from the backend can be written to the state via a mapping configuration
  • Service activators can be executed conditionally
  • Can be used to display server side validations on a page
  • Can be combined with the ngx-xtra dynamic form component to fill possible selections in a dropdown with a server side call.

Service Activators can also be triggered via PFE Actions.

Documentation of the configuration

The configuration of service activators is also supported by the config editor:

service activators in editor

1. Example for a Service Activator Configuration

{
  "pageId": "summary",
  "onPageLeaveServiceActivators": [
    {
      "path": "mo-bff/contract/process",
      "responseDataMapping": [
        {
          "responseDataExpression": "$.contractNumber",
          "stateKeyExpression": "$.contractNumber"
        }
      ]
    }
  ]
}

2. Error Handling with Service Activators

By default, a failure in a service activator call results in a redirect onto the global error page of the app. A failure is defined as any HTTP error response.

In general, the error handling can be configured in these locations:

  • Directly with the service activator in question
  • Globally. This is the default if no specific configuration is added to a service activator

Error Handling for a Specific Service Activator

The service activator configuration supports the definition of certain errorCases and how they should be handled.

This is done in the errorHandling attribute within the service activator configuration. The configuration itself defines an array of errorCases.

Every ErrorCase handling can define conditions that determine if it should become active or not. The first valid errorCase out of all configured ones is then executed.

The execution of an error case follows these steps:

  1. Run the errorResponseDataMapping configured in the errorCase. This allows it to save data from the payload of the response into the state. It works the same as the responseDataMapping for successful service activators.
  2. Execute the actions that are configured in the errorCase. This makes it possible to handle more specific behavior that is not covered by the standard configuration. The result of the action, directly translates to the behavior of the error handling. If the action returns true, the behavior is the same as with the ignoreError flag. If it returns false, the behavior is the same as with the disableErrorPageNavigation flag. An action can also trigger a custom navigation in this case. Alternatively, it is possible to ignore the action result with the ignoreActionsResult flag.
  3. After this, it is determined if the error should be ignored (ignoreError flag). In this case, no further error handling is done and the service activator behaves the same as a successful one.
  4. If the error was not ignored, it is checked if the error page navigation is disabled (disableErrorPageNavigation flag). For example: If the disableErrorPageNavigation is set for the error case of a service activator, that was triggered in the onPageLeave*, the navigation would be aborted and the user would stay on the current page.
  5. If these flags are not set, the errorPageNavigation of the service activator is used to determine the error page to go to. This navigation works similar to a standard navigation, but is able to access the payload of the error response.
  6. If there is no errorPageNavigation configuration, a fallback to the global error page is done.

A simple example configuration for a service activator with one error case could look like this:

{
  "onPageLeaveServiceActivators": [
    {
      "path": "errorServiceActivator",
      "errorHandling": {
        "errorCases": [
          {
            "conditions": [
              {
                "type": "PFE_EXPRESSION",
                "value1Expression": "$.response.status",
                "operator": "==",
                "value2Expression": "404"
              }
            ],
            "disableErrorPageNavigation": true
          }
        ]
      }
    }
  ]
}

In this example, the service activator runs into a 404 response. It is triggered when the page is left (onPageLeaveServiceActivators) As the disableErrorPageNavigation flag is set, the user will stay on the page and the navigation will be aborted in case of the 404 response.

Conditions of an errorCase

The configuration of the errorCase conditions are the same as the standard navigation conditions. They do however have a few extra gimmicks.

The state is only available under $.state in these conditions. The error response is available under $.response, which means that the response body for error responses is available under $.response.error.

The response headers are available under $.responseHeaders The data model for this can be found here: ErrorCaseConditionsState. They are converted into this structure: [index: string]: string[] The background for this is, that response headers can have duplicates. So the same header could have multiple values.

An example could look like this:

Response headers:

status: 400,
statusText:'error'
error: "Bad Request",
type: "REJECTION",
type: "this is a duplicate value of the type header"
message: "Http failure response for /path: 400 error",

These response headers are then converted to the following data model and provided to the conditions:

{
  "type": ["REJECTION", "this is a duplicate value of the type header"],
  "anotherHeader": ["something"]
}

In this example, we only want the error case to become active, if the type header is set, with the value REJECTION. If this value is not available, the error case should not become active.

This can be done with the following condition/expression:

{
  "value1Expression": "$.responseHeaders.type[?(@==\"REJECTION\")]"
}

This expression checks the values of the type header, if the value REJECTION is present.

To clarify, the following condition would lead to the same result. The extracted valued from the expression is REJECTION. This value is seen as truthy in the conditions.

{
  "value1Expression": "$.responseHeaders.type[?(@==\"REJECTION\")]",
  "operator": "==",
  "value2Expression": "REJECTION"
}

A full example of a service activator call with a more complex error handling of errors could look like this:

{
  "onPageLeaveServiceActivators": [
    {
      "path": "endpoint",
      "errorCases": [
        {
          "conditions": [
            {
              "value1Expression": "$.response.status",
              "operator": "==",
              "value2Expression": "400"
            },
            {
              "value1Expression": "$.responseHeaders.type[?(@==\"REJECTION\")]",
              "operator": "==",
              "value2Expression": "REJECTION"
            }
          ],
          "errorPageNavigation": [
            {
              "nextPageId": "errorPage"
            }
          ]
        },
        {
          "conditions": [
            {
              "value1Expression": "$.response.status",
              "operator": "==",
              "value2Expression": "400"
            }
          ],
          "disableErrorPageNavigation": true
        }
      ]
    }
  ]
}

This example configuration has the effect, that the user will only be navigated to the errorPage if the 400 response also contains the type header with the value REJECTION.

In all other cases, the navigation is stopped and the user stays on the page.

Actions

Actions that run within an error case can also influence the result of the error handling. If one of the actions returns a negative result (false), the error is thrown up. This has the same effect as the disableErrorPageNavigation flag.

errorPageNavigation

An example for a custom errorPageNavigation could look like this:

{
  "onPageLeaveServiceActivators": [
    {
      "path": "endpoint",
      "errorCases": [
        {
          "conditions": [
            {
              "value1Expression": "$.response.status",
              "operator": "==",
              "value2Expression": "500"
            }
          ],
          "errorPageNavigation": [
            {
              "nextPageId": "myCustomErrorPage",
              "conditions": [
                {
                  "value1Expression": "$.response.error.thisServer",
                  "operator": "==",
                  "value2Expression": "isCrashed"
                }
              ]
            },
            {
              "nextPageId": "fallbackErrorPage"
            }
          ]
        }
      ]
    }
  ]
}

The navigation to the myCustomErrorPage only happens if the response body contains the text isCrashed in the field thisServer for the response with the status code 500. If that is not the case, the default fallbackErrorPage is used.

Global Error Page Configuration

The errorPageNavigation configuration can be used to define conditions that determine the error page that should be displayed.

Example for such a configuration:

{
  "navConfiguration": {
    "errorPageNavigation": [
      {
        "nextPageId": "teapotError",
        "conditions": [
          {
            "value1Expression": "$.response.status",
            "operator": "===",
            "value2Expression": "418"
          }
        ]
      },
      {
        "nextPageId": "defaultErrorPage",
      }
    ]
  }
}

The conditions to determine if a navigation to an error page should happen are similar to the NavOptionConfig conditions. But in difference to those, the PFE state is only available under $.state in the error page navigation conditions.

Additionally the response data is available:

  • The error response is available under $.response
  • The http status is available under $.response.status
  • The response body for error responses is available under $.response.error
  • The response headers under $.responseHeaders

The errorResponseDataMapping in the errorCases configuration of a specific service activator can be used to write the error response data to the state before the error page navigation is triggered.

Example for a Service Activator for a Validation

The user will only be able to navigate, once the service returned a non-error response

{
  "path": "some-service/validate",
  "serviceActivatorMethod": "POST",
  "preventNavigationOnError": true,
  "requestDataMapping": [
    {
      "requestDataExpression": "$.fieldToValidate",
      "stateKeyExpression": "$.userdata.fieldToValidate"
    },
    {
      "requestDataExpression": "$.anotherFieldToValidate",
      "stateKeyExpression": "$.userdata.anotherFieldToValidate"
    }
  ],
  "responseDataMapping": [
    {
      "responseDataExpression": "$",
      "stateKeyExpression": "$.someService.validationStatus"
    }
  ],
  "serviceActivatorErrorHandlingExcludeStatusCodes": [404, 400],
  "serviceActivatorResponseStatusHandlers": [
    {
      "statusCode": 400,
      "stateKeyExpression": "$.validationErrorData",
      "stateValue": "common.validation.formatError"
    },
    {
      "statusCode": 404,
      "stateKeyExpression": "$.validationErrorData",
      "stateValue": "common.validation.notFoundError"
    }
  ]
}

3. Trigger Service Activators Through Code

While it is recommended to rely on the trigger points of the navigation flow, it is also possible to trigger service activators directly in the code. The PfeBusinessService provides the triggerSingleServiceActivator() for this.

It can be used like this:

this.pfeBusinessService
  .triggerSingleServiceActivator('serviceActivatorID')
  .then((response) => {
    // The full HTTP response of the service activator is available here
  })
  .catch((error) => {
    // The full HTTP error response of the service activator is available here
  });

By default, the PFE error handling is active for every service activator. That means an automatic navigation to the error page is triggered.

It might be desirable to stay on the current page, for example if the error is supposed to be handled manually in the code of the catch block. This can be done, by disabling the navigation to the error page for the service activator in question. For example:

{
  "errorServiceActivator": {
    "path": "http://example.com/this-is-a-404",
    "serviceActivatorMethod": "GET",
    "errorHandling": {
      "errorCases": [
        {
          "disableErrorPageNavigation": true
        }
      ]
    }
  }
}

results matching ""

    No results matching ""