Migration from BPC 4.* to BPC 5.0

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

Migration of indexes for OpenSearch 3.x

As with every OpenSearch update, we strongly recommend creating a backup of the OpenSearch indexes before the update.

Back up the directory INSTALLATIONSVERZEICHNIS/opensearch_data.

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

If OpenSearch 3.x is started with old indexes, it may happen that some indexes are updated to version 3.x, while old Elasticsearch indexes remain. In this case, OpenSearch does not start in version 2.x or version 3.x.

We therefore recommend that you always create a backup of the opensearch_data directory and run the migration tool, even if there are no indexes that were created with Elasticsearch.

The migration of old Elasticsearch indexes is carried out as follows:

  1. Start OpenSearch with version 2.x

  2. Download the migration tool opensearch-migrator.jar

  3. Change to the download directory

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

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

  6. If the tool issues a message during execution that system indices or closed indices from an old version are present, these should also be migrated (see warnings/console output of the tool). To do this, the migration tool must be executed again with the arguments --migrateSystemIndices or --deleteOldClosedIndices. 7the Elasticsearch indices should be migrated without errors

  7. OpenSearch 3.x should now start without errors

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

Update of jvm.options for outsourced OpenSearch configuration

If the OpenSearch configuration has been outsourced to a separate directory and is not located in the OpenSearch directory in the BPC installation path (INSTALLATIONSVERZEICHNIS/opensearch/config), it is necessary to update the file jvm.options. (See also Outsourcing the OpenSearch configuration)

This is configured by default for newer installations via the bundle supplied. The configuration is swapped out to INSTALLATIONSVERZEICHNIS/opensearch-config.

An old jvm.options file from an OpenSearch 2.x installation leads to 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 INSTALLATIONSVERZEICHNIS/opensearch-config/jvm.options with the new file INSTALLATIONSVERZEICHNIS/opensearch-3.2.x/config/jvm.options.

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

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 changed to a standardized JSON format.
This necessitates changes in the backend systems such as INUBIT and IGUASU.

Query string Parameters and 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 changed from Form Data to the new, standardized JSON structure.

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

The new configuration only requires the setting Function_ActionsEndpointProcessor. This setting can be used 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: Call structure in comparison
Here you can see the direct comparison between the old form structure and the new JSON structure.

ALT with two selected indices (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:Comment

NEU (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"
    }
  ]
}

Prozess Starter

Auch das Starten von Prozessen folgt nun der neuen JSON-Struktur.

Konfiguration
Ähnlich wie bei den Prozess-Aktionen entfallen die Einstellungen Function_InubitBackendConnection, Function_InubitBaseURL und Function_ProcessStarterEndpoint. Diese Einstellungen werden automatisch zur Einstellung Function_VpsEndpointProcessor migriert.

Stattdessen wird nur noch die Einstellung Function_VpsEndpointProcessor benötigt, um das Ziel (Flow-Prozessor oder Backend Connection) zu definieren.

Metadaten
Zusätzliche Metadaten können direkt in der Prozess-Starter-Konfiguration im Monitor für jeden Prozess individuell über ein metadata-Objekt hinzugefügt werden.

Beispiel: Aufrufstruktur im Vergleich
ALT "mit Kontext" (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>

NEU "mit Kontext" (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"
    }
  ]
}

ALT "mit 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>

NEU "mit 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 "positionen" ist die ID (key) des Grids in der Prozess-Starter Konfiguration

ALT "mit 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>

NEU "mit 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 Das "metadata"-Objekt wird gesetzt, wenn mode auf "initialRemote" gesetzt wird oder reloadRemoteData true ist.
2 "reloadOnChange" wird nur gesetzt, wenn reloadRemoteData = true.

Prozessstatuswechsel

Die Änderung des Prozessstatus wurde ebenfalls auf die vereinheitlichte JSON-Struktur umgestellt.

Konfiguration
Die Konfiguration über Function_InubitBackendConnection, Function_InubitBaseURL und Function_ChangeStateEndpoint ist nicht mehr notwendig. Diese Einstellungen werden automatisch zur Einstellung Function_ChangeStateEndpointProcessor migriert.

Die Definition des Ziels erfolgt nun ausschließlich über die Einstellung Function_ChangeStateEndpointProcessor.

Metadaten
Sollen beim Statuswechsel Metadaten übergeben werden, kann ein metadata-Objekt direkt in der ChangeStateConfig für jede Spalte hinzugefügt werden.

Beispiel: Aufrufstruktur im Vergleich
ALT (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" ist nicht mehr Teil der Default ChangeStateConfig. Wenn childStatus gesetzt ist, wird es automatisch in das metadata-Objekt migriert.

Changes in the Forms module

Some changes and standardizations have been made within the Forms module. This mainly affects the form configuration itself, but also the exchange of messages from a Forms application.

Form configuration

So that a Form configuration can be displayed, some changes are required. The Configuration onChangeBufferTime has been removed, as validateOnChange has been revised and now only triggers after processing has been completed. dataUrl has been replaced with stateUrl and enables data to be loaded into state.

The Schema for validating form configurations is much more restrictive. As a result, forms are often not displayed if they do not correspond to the specified schema.

Multilingualism has been revised and can be used in considerably more places. However, the tag MULTI_LANGUAGE must now be used. The MULTI_LANGUAGE tag is required in all places where a translation is expected.

Table 1. Multilingualism
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 uses a different syntax than before. It is now necessary to use ${} for binding.

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

Message exchange

The following are affected by these changes Iframe Messages, Server Messages and also onChange within the form configuration.

The structure for calling an Action has been standardized. Changes are therefore required in places where the Forms module is interacted with.

Table 3. Action Request
Before After

Iframe Messages.

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

Bei Iframe Nachrichten ist action statt requestName und payload statt request zu verwenden.

{
  "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"
  }
}

Bei Antworten auf einen erfolgreichen Submit ist payload statt data zu verwenden. Zudem wird der Tag result nicht mehr verwendet. Um eine Rückmeldung an den Nutzer zu geben, kann nun die Aktion dialog verwendet werden.

{
  "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"
    }
  }
}

The messages from the Forms module were only sent in the context of Iframe Messages. A success tag was added to indicate whether the action could be performed. 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 standardization.

Table 5. Renaming 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 adapted in the structure for standardization.

Table 6. Structure adjustment actions
Before After
{
  "result": "success",
  "action": "setFormConfig",
  "data": {
    "formConfig": {
      "metaData": {
        "id": 0,
        "version": 0
      },
      "components": [
        {
          "type": "html",
          "value": "setFormConfig"
        }
      ],
      "configuration": {}
    }
  }
}

Der zuvor erforderliche Tag formConfig wurde entfernt.

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

Iframe message.

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

Server Nachricht.

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

Sowohl für Iframe als auch Server Nachrichten wurden zuvor die neuen Daten direkt in den data Bereich im state geschrieben. Daten werden jetzt direkt in den state geschrieben. Für das gleiche Ziel ist daher ein extra data erforderlich. Für Server Nachrichten entfällt zudem der zusätzliche tag state.

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

Validation

The Validation has been revised in several places. The 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 of the server-side Validation has been changed. validationErrors is now a separate action that can be triggered and is no longer evaluated as a separate attribute. The instancePath starts at 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"
    }
  ]
}

The Validation errors are stored differently in 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 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).E.g. in a password manager) if you have not already done so.

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

curl --cert {OPENSEARCH-ZERTIFIKAT} {OPENSEARCH-URL}/bpc-configuration/_doc/_core_noinstance_apiKeys/\?pretty

Under Direct access to OpenSearch you can find more details on how to access OpenSearch with curl.


Keywords: