Migration from BPC 4.* to BPC 5.0

This page describes the migration of an existing BPC 4 installation to BPC 5.

Migration of Indices for OpenSearch 3.x

As with any OpenSearch update, we strongly recommend creating a backup of the OpenSearch indices before updating.

To do this, back up the directory <BPC-INSTALL-DIR>/opensearch_data.

The following steps are required if the installation being migrated uses an OpenSearch system that contains indexes originally created with an older version of Elasticsearch. We provide a migration tool that can be used to migrate all old indexes.

If OpenSearch 3.x is started with legacy indexes, some indexes may be updated to version 3.x while legacy Elasticsearch indexes remain. In this case, OpenSearch will not start in either version 2.x or version 3.x.

Therefore, we strongly recommend creating a backup of the ` opensearch_data` directory and running the migration tool, even if there are no indexes created with Elasticsearch.

The migration of the old Elasticsearch indexes is performed as follows:

  1. Start OpenSearch version 2.x

  2. Download the migration tool opensearch-migrator.jar

  3. Navigate to the download directory

  4. Ensure that Java 21 (from the BPC installation) is located at PATH and that JAVA_HOME is set correctly

  5. Start the migration tool, depending on how OpenSearch is accessed:

  6. If the tool displays a message during execution indicating that system indices or closed indices from an older version are present, these should also be migrated (see the tool’s warnings/console output). To do this, the migration tool must be run again with the arguments --migrateSystemIndices or --deleteOldClosedIndices.

  7. The Elasticsearch indices should be migrated without errors

  8. OpenSearch 3.x should now start without errors

Depending on the size of the indices, this migration (reindexing of indices) can take anywhere from a few minutes to several hours.

Updating jvm.options for an external OpenSearch configuration

If the OpenSearch configuration is located in a separate directory and not in the OpenSearch directory within the BPC installation path (<BPC-INSTALL-DIR>/opensearch/config), you must update the file jvm.options. (See also Moving the OpenSearch Configuration)

For newer installations using the included bundle, this is configured by default. There, the configuration is moved to <BPC-INSTALL-DIR>/opensearch-config.

An old jvm.options file from an OpenSearch 2.x installation causes the following error:

fatal error in thread [main], exiting
java.lang.NoClassDefFoundError: org/opensearch/javaagent/bootstrap/AgentPolicy$AnyCanExit

In this case, please replace the file <BPC-INSTALL-DIR>/opensearch-config/jvm.options with the new file <BPC-INSTALL-DIR>/opensearch-3.2.x/config/jvm.options.

Manual changes made to the file jvm.options must be reapplied.

Change to the call structure for process actions, process starters, and process status changes

The content type x-www-form-urlencoded and the XML-based format have been converted to a uniform JSON format.
This necessitates changes in backend systems such as INUBIT and IGUASU.

Query string parameters as well as the legacy parameters gridExtId, tablePrefix, and mandant are no longer supported and have been removed.

A request object now always consists of the following elements:

  • "config": A configuration object.

  • "bpcUrl": A unique URL to identify the target in the format bpc://<flow/backendconnection>/<instanceId>/<EndpointOrProcessor>.

  • "records" (optional): An array of records, if a context is passed.

  • "metadata" (optional): An object for additional context or configuration information, in which, for example, legacy Parameters can be passed if necessary.

A detailed description of all endpoints can be found in our OpenAPI specification.

Process Actions

The execution of process actions has been migrated from Form Data to the new, unified JSON structure.

Configuration
The previous configuration via the settings Function_InubitBackendConnection (inubit_proxyId), Function_InubitBaseURL (inubit_baseUrl), and Function_ProcessActionsEndpoint is deprecated. These settings are automatically migrated to the setting Function_ActionsEndpointProcessor.

The new configuration now only requires the setting Function_ActionsEndpointProcessor. This setting allows you to select either a processor from the Flow module or a backend connection (HTTP proxy) with a user-defined endpoint.

Metadata
To send additional metadata with process actions, this can now be configured centrally in the monitor settings under “Process Action Metadata.”

Example: Comparison of call structures
Here you can see a direct comparison between the old form structure and the new JSON structure.

OLD with two selected indexes (Form Data)
URL: /cxf/bpc-monitor/monitor/httpProxy/inubit-placeholder/ibis/servlet/IBISHTTPUploadServlet/PM_LogMonitor_Action?gridId=singlegrid&gridExtId=PM-core-singlegrid-grid&multiRecords=true&buttonId=action_test&action_test=Action%20Requires%20Comments

Content-Type: application/x-www-form-urlencoded

index0_action_test:[{"id": "simple-action","name": "A Simple Action","iconCls": "x-fal fa-alarm-clock","sortValue": 1},{"id": "action-requires-comments","name": "Action Requires Confirmation","iconCls": "x-fal fa-biking-mountain","sortValue": 1, "requireConfirmation": true}]
index0_collabdata:Collaboration Service not available or collabReferenceKey not set
index0_id:1
index0_text:requireConfirmation true
index0__id:1
index0_action_test_zwo:action zwo
index0_bpccleanedid:_1
index0_tablePrefix:single_
index1_action_test:[{"id": "simple-action","name": "A Simple Action","iconCls": "x-fal fa-alarm-clock","sortValue": 1},{"id": "action-requires-comments","name": "Action Requires Comments","iconCls": "x-fal fa-biking-mountain","sortValue": 1,"requireComment": true, "requireConfirmation": true}]
index1_collabdata:Collaboration Service not available or collabReferenceKey not set
index1_id:2
index1_text:requireConfirmation true requireComment true
index1__id:2
index1_action_test_zwo:action zwo
index1_bpccleanedid:_2
index1_tablePrefix:single_
actionConfig_id:action-requires-comments
actionConfig_name:Action Requires Comments
actionConfig_iconCls:x-fal fa-biking-mountain
actionConfig_sortValue:1
actionConfig_requireComment:true
actionConfig_requireConfirmation:true
actionConfig_label:Action Requires Comments
actionConfig_column:action_test
actionConfig_type:processAction
actionConfig_comment:Kommentar

NEW (JSON)

{
  "config": {
    "id": "action-requires-comments",
    "name": "Action Requires Comments",
    "iconCls": "x-fal fa-biking-mountain",
    "sortValue": 1,
    "requireComment": true,
    "requireConfirmation": true,
    "label": "Action Requires Comments",
    "column": "action_test",
    "type": "processAction",
    "instanceId": "process-actions-test-monitor-notifications",
    "comment": "Kommentar"
  },
  "metadata": {
    "foo": "bar"
  },
  "bpcUrl": "bpc://flow/flow_iguasu/endpointOrProcessor",
  "records": [
    {
      "action_test": "[{\"id\": \"simple-action\",\"name\": \"A Simple Action\",\"iconCls\": \"x-fal fa-alarm-clock\",\"sortValue\": 1},{\"id\": \"action-requires-comments\",\"name\": \"Action Requires Confirmation\",\"iconCls\": \"x-fal fa-biking-mountain\",\"sortValue\": 1, \"requireConfirmation\": true}]",
      "collabdata": "Collaboration Service not available or collabReferenceKey not set",
      "id": "1",
      "text": "requireConfirmation true",
      "_id": "1",
      "action_test_zwo": "action zwo",
      "bpccleanedid": "_1"
    },
    {
      "action_test": "[{\"id\": \"simple-action\",\"name\": \"A Simple Action\",\"iconCls\": \"x-fal fa-alarm-clock\",\"sortValue\": 1},{\"id\": \"action-requires-comments\",\"name\": \"Action Requires Comments\",\"iconCls\": \"x-fal fa-biking-mountain\",\"sortValue\": 1,\"requireComment\": true, \"requireConfirmation\": true}]",
      "collabdata": "Collaboration Service not available or collabReferenceKey not set",
      "id": "2",
      "text": "requireConfirmation true requireComment true",
      "_id": "2",
      "action_test_zwo": "action zwo",
      "bpccleanedid": "_2"
    }
  ]
}

Process Starter

Starting processes now also follows the new JSON structure.

Configuration
Similar to process actions, the settings Function_InubitBackendConnection, Function_InubitBaseURL, and Function_ProcessStarterEndpoint are no longer required. These settings are automatically migrated to the setting Function_VpsEndpointProcessor.

Instead, only the setting Function_VpsEndpointProcessor is now required to define the target (flow processor or backend Connection).

Metadata
Additional metadata can be added directly in the process starter configuration in the monitor for each process individually using an metadata object.

Example: Comparison of call structures
OLD "with context" (XML)

<root>
	<portletArchiveName></portletArchiveName>
	<operation>startProcess</operation>
	<mandant>default</mandant>
	<gridID>singlegrid</gridID>
	<key>datenuebertragen</key>
	<bpcModule>monitor</bpcModule>
	<bpcModuleInstanceId>process-starter-start-with-context</bpcModuleInstanceId>
	<data type="array">
		<item type="tuple">
			<statusField>ERROR</statusField>
			<textField>This is third test object</textField>
			<idField>3</idField>
			<dateField>2020-02-01</dateField>
			<records type="array">
				<item type="tuple">
					<status>ERROR</status>
					<collabdata>Collaboration Service not available or collabReferenceKey not set</collabdata>
					<text>This is third test object</text>
					<_id>3</_id>
					<processid>3</processid>
					<timestamp>2020-02-01T12:00:00.000+0200</timestamp>
					<bpccleanedid>_3</bpccleanedid>
				</item>
			</records>
		</item>
	</data>
</root>

NEW "with context" (JSON)

{
  "config": {
    "id": "datenuebertragen",
    "label": "startWithContextProcess",
    "parameters": {
      "statusField": "ERROR",
      "textField": "This is third test object",
      "idField": "3",
      "dateField": "2020-02-01"
    },
    "type": "processStarter",
    "instanceId": "process-starter-start-with-context"
  },
  "bpcUrl": "bpc://flow/flow_iguasu/endpointOrProcessor",
  "records": [
    {
      "status": "ERROR",
      "collabdata": "Collaboration Service not available or collabReferenceKey not set",
      "text": "This is third test object",
      "_id": "3",
      "processid": "3",
      "timestamp": "2020-02-01T12:00:00.000+0200",
      "bpccleanedid": "_3"
    }
  ]
}

OLD "with grid" (XML)

<root>
	<portletArchiveName></portletArchiveName>
	<operation>startProcess</operation>
	<mandant>default</mandant>
	<gridID>singlegrid</gridID>
	<key>sendOrders</key>
	<bpcModule>monitor</bpcModule>
	<bpcModuleInstanceId>process-starter-with-role</bpcModuleInstanceId>
	<data type="array">
		<item type="tuple">
			<receiver>Nummer 1</receiver>
			<artikelnummer>Nummer 2</artikelnummer>
			<positionen>
				<record>
					<id>extModel408-1</id>
					<artikelnummertabelle>Nummer 1</artikelnummertabelle>
					<quantity>1</quantity>
				</record>
				<record>
					<id>extModel408-2</id>
					<artikelnummertabelle>Nummer 2</artikelnummertabelle>
					<quantity>2</quantity>
				</record>
			</positionen>
		</item>
	</data>
</root>

NEW "with grid" (JSON)

{
  "config": {
    "id": "sendOrders",
    "label": "Bestellung aufgeben (für BPC-4638)",
    "parameters": {
      "receiver": "Nummer 1",
      "artikelnummer": "Nummer 2",
      "positionen": [ (1)
        {
          "id": "extModel409-1",
          "artikelnummertabelle": "Nummer 1",
          "quantity": 1
        },
        {
          "id": "extModel409-2",
          "artikelnummertabelle": "Nummer 2",
          "quantity": 2
        }
      ]
    },
    "type": "processStarter",
    "instanceId": "process-starter-with-role"
  },
  "bpcUrl": "bpc://flow/flow_iguasu/endpointOrProcessor"
}
1 "positions" is the ID (key) of the grid in the Process Starter configuration

ALT "with mode = initialRemote & reloadRemoteData" (XML)
URL: /cxf/bpc-httpproxy/httpProxy/inubit-placeholder/ibis/servlet/IBISHTTPUploadServlet/BPC_PS_Listener?reloadOnChange=true

<root>
	<portletArchiveName></portletArchiveName>
	<mandant>default</mandant>
	<gridID>singlegrid</gridID>
	<custom>true</custom>
	<bpcModule>monitor</bpcModule>
	<bpcModuleInstanceId>process-starter-forms</bpcModuleInstanceId>
	<process>sendOrders</process>
	<key>artikelnummer</key>
	<operation>choiceList</operation>
	<formData>
		<receiver>Nummer 1</receiver>
		<artikelnummer>null</artikelnummer>
		<positionen></positionen>
	</formData>
</root>

NEW "with mode = initialRemote & reloadRemoteData" (JSON)

{
  "config": {
    "id": "sendOrders",
    "label": "Bestellung aufgeben (für BPC-4638)",
    "parameters": {
      "receiver": "Nummer 1",
      "artikelnummer": "",
      "positionen": {}
    },
    "type": "processStarter",
    "instanceId": "process-starter-forms"
  },
  "metadata": { (1)
    "process": "sendOrders",
    "key": "artikelnummer",
    "operation": "choiceList",
    "reloadOnChange": true  (2)
  },
  "bpcUrl": "bpc://flow/flow_iguasu/endpointOrProcessor"
}
1 The "metadata" object is set when mode is set to "initialRemote" or reloadRemoteData is true.
2 "reloadOnChange" is only set if reloadRemoteData = true.

Process status change

The process status change has also been converted to the standardized JSON structure.

Configuration
Configuration via Function_InubitBackendConnection, Function_InubitBaseURL, and Function_ChangeStateEndpoint is no longer necessary. These settings are automatically migrated to the Function_ChangeStateEndpointProcessor setting.

The destination is now defined exclusively via the Function_ChangeStateEndpointProcessor setting.

Metadata
If metadata is to be passed during a status change, a metadata object can be added directly to the ChangeStateConfig for each column.

Example: Comparison of call structures
OLD (Form Data)

Content-Type: application/x-www-form-urlencoded

tablePrefix:single_
mandant:default
timelineUpdate:TIMESTAMP
childStatus:Info
command:StatusChange
columnsstring:status
changeStatusBox_status:on
newStatusCombo_status:inprocess
commentfield:Starte Verarbeitung
processes:extModel8836-1

NEW (JSON)

{
  "config": {
    "timelineUpdate": "TIMESTAMP",
    "type": "statusChange",
    "column": "status",
    "newStatus": "inprocess",
    "comment": "Starte Verarbeitung",
    "processes": "extModel8836-1",
    "instanceId": "change-status-test-monitor"
  },
  "bpcUrl": "bpc://flow/flow_iguasu/endpointOrProcessor",
  "metadata": {
    "childStatus": "Info" (1)
  }
}
1 "childStatus": "Info" is no longer part of the default ChangeStateConfig. If childStatus is set, it is automatically migrated to the metadata object.

Changes in the Forms Module

Several changes and standardizations have been made within the Forms module. These changes primarily affect the form configuration itself, but also message exchange from within a Forms application.

Form Configuration

Several changes are required to enable the display of a form configuration. The configuration onChangeBufferTime has been removed because validateOnChange has been revised and now triggers only after editing is complete. dataUrl has been replaced with stateUrl and allows data to be loaded into the state.

The schema for validating form configurations is significantly more restrictive. As a result, forms are more likely to not be displayed if they do not conform to the specified schema.

Multilingual support has been revised and can now be used in significantly more places. However, the MULTI_LANGUAGE tag must now be used. The MULTI_LANGUAGE tag is required wherever a translation is expected.

Table 1. Multilingual Support
Before After
{
  "type": "textfield",
  "label": {
    "de": "deutsches label",
    "en": "englisch label"
  }
}
{
  "type": "textfield",
  "label": {
    "MULTI_LANGUAGE" : {
      "de": "deutsches label",
      "en": "englisch label"
    }
  }
}
{
  "state": {
    "data": {
      "options": [{
        "value": "one",
        "label": {
          "de": "Eins",
          "en": "One"
        }
      },
      {
        "value": "two",
        "label": {
          "de": "Zwei",
          "en": "Two"
        }
      }]
    }
  }
}
{
  "state": {
    "data": {
      "options": [{
        "value": "one",
        "label": {
          "MULTI_LANGUAGE": {
            "de": "Eins",
            "en": "One"
          }
        }
      },
      {
        "value": "two",
        "label": {
          "MULTI_LANGUAGE": {
            "de": "Zwei",
            "en": "Two"
          }
        }
      }]
    }
  }
}

Data binding now uses a different syntax than before. For binding, it is now necessary to use ${}.

Table 2. Data Binding
Before After
{
  "type": "textfield",
  "value": "/data/text"
}
{
  "type": "textfield",
  "value": "${/data/text}"
}

Message Exchange

These changes affect iframe messages, server messages, and the onChange event within the form configuration.

The structure for calling an action has been standardized. Consequently, changes are required in places where the Forms module is used.

Table 3. Action Request
Before After

Iframe Messages.

{
  "sourceId": "SOURCE_ID",
  "requestName": "setData",
  "request": {
    "welcomeMsg" : "<h1>Willkommen</h1>"
  }
}

For Iframe messages, use action instead of requestName and payload instead of request.

{
  "sourceId": "SOURCE_ID",
  "action"  : "setFormState",
  "payload": {
    "data": {
      "welcomeMsg": "<h1>Willkommen</h1>"
    }
  }
}

Response to a successful submit.

{
  "result" : "success",
  "action" : "downloadFile",
  "data"   : {
    "fileName" : "testfile.txt",
    "data"     : "Hello World"
  }
}

For responses to a successful submit, use payload instead of data. In addition, the result tag is no longer used. To provide feedback to the user, the action dialog can now be used.

{
  "action"  : "downloadFile",
  "payload" : {
    "fileName" : "testfile.txt",
    "data"     : "Hello World"
  }
}

onChange configuration.

{
  "type": "textfield",
  "onChange": {
    "action": "getFormState",
    "data": {
      "stateUrl": "http://localhost:3000/load"
    }
  }
}
{
  "type": "textfield",
  "onChange": {
    "action": "getFormState",
    "payload": {
      "url": "http://localhost:3000/load"
    }
  }
}

Messages from the Forms module were only modified in the context of iframe messages. A success tag was added here to indicate whether the action could be executed. requestName was replaced with action.

Table 4. Action Response
Before After

Iframe messages.

{
  "requestName" : "setFormConfig",
  "destinationId" : "*",
  "response" : {}
}
{
  "success" : true,
  "action" : "setFormConfig",
  "destinationId" : "*",
  "response" : {}
}

In the iframe context, various actions have been renamed for consistency.

Table 5. Renamed Actions
Before After

getFormConfig

This function has been removed. getFormConfig now has a different meaning and is used to load a form configuration.

printForm

print

resetForm

reset

setData

setFormState

submitData

submit

validateData

validate

Some functions have been restructured for consistency.

Table 6. Structural Adjustments to Actions
Before After
{
  "result": "success",
  "action": "setFormConfig",
  "data": {
    "formConfig": {
      "metaData": {
        "id": 0,
        "version": 0
      },
      "components": [
        {
          "type": "html",
          "value": "setFormConfig"
        }
      ],
      "configuration": {}
    }
  }
}

The previously required tag formConfig has been removed.

{
  "action": "setFormConfig",
  "payload": {
    "metaData": {
      "id": 0,
      "version": 0
    },
    "components": [
      {
        "type": "html",
        "value": "setFormConfig"
      }
    ],
    "configuration": {}
  }
}

Iframe message.

{
  "requestName": "setData",
  "request": {
    "welcomeMsg" : "<h1>Willkommen</h1>"
  }
}

Server message.

{
  "action" : "setFormState",
  "data"   : {
    "state" : {
      "welcomeMsg" : "<h1>Willkommen</h1>"
    }
  }
}

Previously, for both Iframe and server messages, the new data was written directly to the data section in state. Data is now written directly to state. Therefore, an additional data is required for the same purpose. For server messages, the additional tag state is no longer required.

{
  "action"  : "setFormState",
  "payload": {
    "data": {
      "welcomeMsg": "<h1>Willkommen</h1>"
    }
  }
}

Validation

The validation has been revised in several places. Data schema validation now starts at the state level.

Table 7. Data schema validation
Before After
{
  "dataSchema": {
    "type": "object",
    "properties": {
      "textValue": {
        "minLength": 20,
        "type": "string"
      }
    }
  }
}
{
  "dataSchema": {
    "type": "object",
    "properties": {
      "data": {
        "type": "object",
        "properties": {
          "textValue": {
            "minLength": 20,
            "type": "string"
          }
        }
      }
    }
  }
}

The message format for server-side validation has been changed. validationErrors It is now a separate action that can be triggered and is no longer treated as a separate attribute. The instancePath starts at the state level and uses the new data-binding notation.

Table 8. Server-side validation
Before After
{
  "validationErrors": [
    {
      "instancePath": "/textValue",
      "message": "validation error"
    }
  ]
}
{
  "action": "validationErrors",
  "payload": [
    {
      "instancePath": "${/data/text}",
      "message": "validation error"
    }
  ]
}

Validation errors are stored differently in the state.

Table 9. Server-side validation
Before After
{
  "state": {
    "valid": true,
    "validationOk" :  {
      "server": true,
      "client": true
    },
    "validationErrors": {
      "server": [],
      "client": []
    }
  }
}
{
  "state": {
    "validationOk" :  {
      "all": true,
      "dataSchema": true,
      "field": true,
      "server": true
    },
    "validationErrors": {
      "all": [],
      "dataSchema": [],
      "field": [],
      "server": []
    }
  }
}

Masking of API keys in the frontend

In BPC 5.0, API keys are masked in the frontend and can therefore no longer be read. We therefore recommend that you store existing API keys in a secure location (e.g., in a password manager) if you have not already done so.

API keys can still be read directly from OpenSearch, for example using curl:

curl --cert {OPENSEARCH-CERTIFICATE} {OPENSEARCH-URL}/BPC-configuration/_doc/_core_noinstance_apiKeys/\?pretty

Under “Direct Access to OpenSearch,” you’ll find more details on how to access OpenSearch using curl.


Keywords: