7 minute read BPS Version: 2024.1.1.48

Overview

While I would guess that the majority of the WEBCON BPS customers are fine with the option to import applications via Designer Studio, there have been enough to request an automated process. With WEBCON BPS 2024 a public REST API was provided.

There’s already a knowledge base article describing it. In addition to the API a command line utility was created by WEBCON. This is located in the Tools folder which was the Migration tools folder in previous versions. This tool can be used to import a package.

What I’m missing from the article is an example on how to use the REST API directly. While it is documented which calls should be made in which order, I’m missing an example. This is reason for this blog post.

Importing a package

Setting up the API application

I won’t provided detailed information, on how to do it. You can refer to the knowledge base article for this. The main difference to other API application is, that this one makes use of the new scope Admin.Import.

Configuration file

When the script gets executed it will read a webconConfig.json file from the .auth folder. If it does not exist, it will create one, open it so that you can provide the required parameters. Alternatively, you can create the file with the following content.

{
  "ClientId": "xyz",
  "ClientSecret": "xyz",
  "Hostname": "https://xyz",
  "ApiVersion": "v6.0"
}
Location of the `webconConfig.json`
Location of the webconConfig.json

Remark: The .gitignore defines that all files in the .auth folder should be ignored except the .empty file. This way the client credentials won’t be committed.

Configuring the import script

The script ImportPackage.ps1 is used for the actual import. Here you can define:

  • The database id, into which the package should be imported
  • The path to the package
  • A custom configuration, if necessary.

In my case I saved the exported package in the Artifacts folder.

Configuration of the import script.
Configuration of the import script.

Remark: I have used the script only from VS Code. Here the PowerShell session is started in the source folder. Therefore, the script changes the location to the PowerShell folder, if it is not the current directory. You may need to change this depending on your use case.

PowerShell explanation

Overview

You can ignore the files in the Classes and Swagger file. The base functionality is located in the UtilityFunction.psm1

UtilityFunctions.psm1 contains the logic.
UtilityFunctions.psm1 contains the logic.

The file itself is ordered into four function areas:

  1. Handling the configuration
  2. Everything related to execution of th REST requests. This includes authentication, executing Get, Post and Patch requests.
  3. The main function Import-WEBCONPackage
  4. An internal helper function to start the import session and upload the file.
Major logic areas in the UtilityFunctions.psm1
Major logic areas in the UtilityFunctions.psm1

Import-WEBCONPackage

This is intended to be used from the external script. It will start the import and return the results of the logs endpoint when the import is finished. If no configuration file is provided the default configuration is used. The status of the import is polled every second, if this exceeds 60 seconds, the script aborts and no longer polls the status.

  • The configuration file can be defined by setting the importConfigurationFilePath parameter.
  • The timeout can be set by setting maxWaitTimeout.
function Import-WEBCONPackage {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [int]
        $dbId,
        [Parameter(Mandatory = $true)]
        [ValidateScript({ Test-Path($_) })]
        [string]$importFilePath
        ,
        [Parameter(Mandatory = $false)]
        [string]$importConfigurationFilePath = ".\Artifcats\defaultConfiguration.json"
        ,
        [Parameter(Mandatory = $false)]
        [int]$maxWaitTimeout = 60
    )

Start-WEBCONPackageImport

This is used from the main function and shouldn’t be used from another function. At least not if everything is working. ;)

This function starts the import sessions and uploads the file. If the file size exceeds 300 kb, the upload is split into multiple requests. You can change this value by setting the variable maxChunkSize. I was too lazy to add parameters to each function so that it could be set by the calling function.

Custom configuration file

Creating a custom configuration file

While the knowledge base article provides information on how to define a custom configuration file. I wasn’t sure whether I understood it correctly. So, I tried to create one using PowerShell and the classes created from the swagger.json.

The result of my experiment is the CreateImportParameters.ps1 with a few tests how to configure different properties. The final object is then converted to JSON an saved as ImportParameters.json

I wanted to create a dummy file with all parameters, but that didn’t work out as expected. I got an System.ArgumentException An item with the same key has already been added.. Maybe because I used [System.Guid]::Empty a lot of times, but it seemed that [System.Guid]::NewGuid() didn’t work either. I’m not sure about it, I didn’t test this thoroughly.

I didn’t use a completely configured file, as you can see with all the commented lines in the script. Based on the swagger.json and the generated classes, the JSON output should work. That’s the benefit of working with classes instead of creating the file in a text editor. ;)

The object is converted to the corresponding JSON
The object is converted to the corresponding JSON

Remark: Before you execute the script, make sure the current location is the PowerShell folder, by executing the lines below from the script. Afterwards you can execute the script whole script including the using module .\MergedClasses.psm1 line. This is necessary so that the classes can be used.

$currentDirectory = Get-Item -Path .
if ($currentDirectory.Name -ne "PowerShell") {
    Set-Location .\"PowerShell"
}

*Selected* takes precedence over *All*

Somewhere in the middle of the knowledge base article there are a few sentences about precedence. This is something you should be aware of.

The value should be set to true/false accordingly. However, it is important to note that the indication of specific elements (“Selected” / “OnlySelected”) takes precedence over all elements to be imported (“All”). For instance, if the “ImportAllPresentationObjects” parameter is set to “true,” it will be ignored if the “ImportOnlySelectedPresentationObjects” parameter is entered in the same configuration file with the corresponding GUID of the presentation object.

In short, if you configure something like

  "overwriteAllGlobalBusinessRules": true,
  "overwriteSelectedGlobalBusinessRules": [
    "0cbe377b-46de-472a-b1a0-9a906b6f52f9"
  ],
 "importBpsGroups": true,
  "importOnlySelectedBpsGroups": [
    "nonexistinggroup@bps.local"
  ],

The system will treat it as

  "overwriteAllGlobalBusinessRules": false,
  "overwriteSelectedGlobalBusinessRules": [
    "0cbe377b-46de-472a-b1a0-9a906b6f52f9"
  ],
 "importBpsGroups": false,
  "importOnlySelectedBpsGroups": [
    "nonexistinggroup@bps.local"
  ],

If you define any Selected the corresponding All property will be ignored. The keyword All is not always used as the example with the BPS Groups shows.

Setting selected values to empty

If you want to define the configuration, that the selected property should be used you have to define it like in the examples above. If you want that the property is ignored, you need to set it to $null. Passing an empty string will cause issues. The same applies to empty arrays.

If you want to make use of the CreateImportParameters.ps1 script be aware of the following:

  1. Setting a string to $null
     # Assigning null will not set the value to null but to an empty string, which then causes issue down the line.
     #$config.overwriteAllProcessesDeploymentModeMailRecipient = $null
     # If we need to set a string to null, we need to use this:
     $config.overwriteAllProcessesDeploymentModeMailRecipient = [NullString]::Value
    
  2. The arrays are initialized by default therefore they need to be set null explicitly
     $config.overwriteSelectedGlobalBusinessRules.Add("0cbe377b-46de-472a-b1a0-9a906b6f52f9")
     #$config.overwriteSelectedGlobalBusinessRules = $null
    

Remark: I’m not 100% sure about the empty arrays because the default script generated by export dialog also uses empty arrays sometimes. For the time being I will just set all to null and not only a few.

Remarks

PowerShell 7

I used VS Code with PowerShell 7 to develop the scripts. This version is typically not installed by default.

Status values

The status values are defined as a simple integer in version 2024.1.1.48. I would have expected that it’s an enum but it may have been forgotten in this version. In PowerShell I’m using this enum to map the integer value to a more human friendly value. In case you are not aware of how enums work: Error is mapped to 0, Completed to 1 etc.

enum ImportStatus 
{
    Error
    Completed
    CompletedWithError
    NotExist
    Created
    InProgress
}

Location of the import session id

If you have lost your import session id, then you can take a look at the HistoryImports table of the content database into which the package should be imported.

The `HistoryImports` table stores the import session id.
The HistoryImports table stores the import session id.

Logs

I’m not sure when we are able to download logs. Maybe only if the status is Completed or CompletedWithError, but not if it’s Error. If you are able to get the logs you are in for a little surprise. In the version 2024.1.1.48 there’s a little mistake and the response is a string where the XML log of the import is assigned to a JSON property without wrapping the value in double quotes. Basically, this is neither a JSON nor a XML value. It may be easier to remove the JSON part so that the XML can be parsed itself.

2024.1.1.48 has a little error in the logs response. The XML is not wrapped in double quotes
2024.1.1.48 has a little error in the logs response. The XML is not wrapped in double quotes

Status ‘Error’

If the PowerShell exits with status Error something went wrong, and the import could not even be completed with errors. You may be able to find more information in the AdminServiceLogs of the configuration database.

The AdminServiceLogs will have more information if the status returns with `Error`.
The AdminServiceLogs will have more information if the status returns with Error.

GitHub Repository

You can find the PowerShell scripts here.

Comments