Skip to main content

Connecting to External Systems From the Business Application Studio

What is the Business Application Studio?

The SAP Business Application Studio (BAS) is a development environment offered as a service on SAP BTP. You can subscribe to the BAS and from there quickly start developing without installing node, git, Visual Studio Code, nor other tools. The solution looks and feels like Visual Studio Code, which is no surprise since it is based on Eclipse Theia, the open source version of Visual Studio Code.

However, SAP added a few useful features to the BAS. You can connect the BAS to your SAP BTP account, which allows you to reach all systems that you have configured on SAP BTP from your local machine. This includes systems that are connected through the Cloud Connector (CC) and are normally not reachable through the internet. Being able to test changes locally reduces the overhead of deploying remotely and thus increases convenience for developers.

Connecting to on-premise systemsConnecting to on-premise systems

Case 1: Connection to an On-Premise System

Technical Background

Companies do not expose their SAP S/4HANA On-Premise systems to the internet. They are only reachable via a Cloud Connector attached to an SAP BTP account. In principle, you cannot reach these systems outside the SAP BTP account.

However, due to the subscription between the BAS and the SAP BTP account, there is a connection from the local application to the SAP S/4HANA system. On a high level the connection works the following way:

  • The BAS includes an HTTP_PROXY running at http://localhost:8887
  • This proxy forwards all http requests to the SAP BTP account
  • SAP BTP searches the existing destinations for one matching the name
  • If a destination is present, an initial request is sent to this destination
  • The proxy is a reverse proxy also piping back the response to the BAS

Prerequisite 1: The Business Application Studio (BAS)

You have an SAP BTP account and a subscription to the BAS. Via the subscription, the BAS can access all destination in the subscribed account.

Prerequisite 2: Cloud Connector and Destination Setup

You have set up a working Cloud Connector and configured a destination pointing to an on-premise system. Per default, destinations are not usable by a subscribed BAS. You need to set two properties WebIDEEnabled and HTML5.DynamicDestination to enable that feature for a specific destination. Go to the destination configuration on SAP BTP and add the properties:

PropertyValue
WebIDEEnabledtrue
HTML5.DynamicDestinationtrue

Checking the Connection

Before you start the implementation, ensure that the connection is correctly configured. The connectivity proxy running in BAS expects a pattern of the kind http://<destinationName>.dest. When such a pattern is found the destination name is extracted and checked against the destinations in the related Cloud Foundry account. If a match is found and the WebIDEEnabled and HTML5.DynamicDestination properties are enabled for the destination the request is forwarded via this destination. All authorization information from the real destination is used. You can test this flow by using a simple curl command without any code.

curl <destinationName>.dest/path/to/service

So if your destination is called S4H_Test.dest and you want to query the catalog service the command would be:

curl -v -i "S4H_Test.dest/sap/opu/odata/iwfnd/catalogservice;v=2/ServiceCollection?%24top=1"

If the request responds with status code 200 for the service you want to use, you can start the implementation. The connectivity proxy has a built-in cache that needs to be emptied after you adjusted destinations. This is done by calling:

curl localhost:8887/reload

For more details on testing and troubleshooting have a look at this guide.

Implementation

If the connection is tested and working you can start the implementation. The SAP Cloud SDK helps you to consider the HTTP_PROXY automatically and makes it easy to use the same code base locally and in production on SAP BTP. The SAP Cloud SDK has a destination lookup priority considering environment variables first.

The trick is to define a destinations environment variable when you run locally, which works like a switch under the hood when you execute:

executeHttpRequest({ destinationName: 'myDestinationName', jwt: '<JWT>' });

The code is the same for local execution and production. The two situations are:

Case 1: When run locally, the SAP Cloud SDK reads the destination from the environment variables. The jwt is irrelevant. The destination contains only the name and URL of the real SAP BTP destination. Since the destination has no proxy type specified, the SAP Cloud SDK takes the HTTP_PROXY into account, as is the default. From there the flow described above takes place.

Case 2: When run on SAP BTP there is no environment variable present. The jwt is used to fetch the full destination from the service. The proxy type is OnPremise and the connectivity service provides all proxy information.

note

The executeHttpRequest() function is used by all request builders provided of the SAP Cloud SDK as well as by CAP applications connecting to an SAP S/4HANA system.

You use launch configurations to run and debug applications locally. Either extend your existing .vscode/launch.json or create a new one.

{
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug my application",
"program": "${workspaceFolder}/dist/main.js",
"envFile": "${workspaceFolder}/.env",
"preLaunchTask": "npm build",
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
]
}
]
}

This example uses a Nest.js application. The code will look similar for express or CAP applications. The program property defines the script file executed when you run the configuration. In this project, the main.js script will start up the Nest server. The preLaunchTask property build before each run which compiles the TypeScript files to JavaScript. The outFiles property defines where the compiled files will be located.

To provide the destination, set the destinations environment variable. This interrupts the destination lookup and the destination will consider the HTTP_PROXY environment variable. If a .env file is present, it is loaded when starting the application. Create or adjust the file to include the following:

destinations="[{
"name": "<destinationName>",
"url": "http://<destinationName>.dest",
"proxyConfiguration":{
"host": "127.0.0.1",
"port": 8887,
"protocol":"http"
}
}]"

Fill in the name and url of the destination you configured on SAP BTP. You can use the same pattern <name>.dest that you have used for testing the connection. The proxy host and port are from the http_proxy environment variables BAS creates for you. All requests done with the SAP Cloud SDK will now reach the SAP S/4HANA system via the BAS connectivity proxy. You can start your application via the launch button.

note

The SAP Cloud SDK also offers a mockTestDestination() method which reads destination information from a system.json and credentials.json file. In the end, this only sets the destinations environment variables as stored in the .env file, but could become advantageous if you have many systems. You can also set the credentials.json to your git ignore list so that they are not checked-in by accident and share the systems with your colleagues.

For the simple case you would add mockTestDestination(<destinationName>) to your local startup script and have a systems.json in your project root:

{
"systems": [
{
"alias": "your destination name",
"uri": "your destination url "
}
]
}

Supported Authentication Types for On-Premise Systems

The supported authentication types are either BasicAuthorization or PrincipalPropagation. In case you use principal propagation, the BAS will fill the SAP-Connectivity-Authentication header as discussed in the on-premise connectivity guide. The user logged into the BAS will be propagated. In case your BAS user is not a valid user of the on-premise system you can use a destination using basic authorization.

Case 2: Connection to Cloud Systems

Cloud systems are reachable via the internet and you do not need any cloud connector to reach them. The same is true for the destination service of the SAP Business Technology Platform. Hence, you can use the same approach locally and in production.

Prerequisite: Service Setup

On Cloud Foundry, the access to services is granted via the VCAP_SERVICE variables. Make sure to configure your application so that it can access the destination service. If not, follow the steps in the Cloud Foundry tutorial.

Implementation

You can mirror the VCAP_SERVICE variables from your Cloud Foundry account to your local BAS. Start the BAS and connect your BAS workspace to the SAP BTP account. This is done via the little connection icon () on the left of the BAS. Then select the application from which you want to mirror the variables and select the folder containing the .env file to store it. Use the envFile property in the launch.json to load the file on your local application startup.

Now your application will fetch the service credentials and call the destination service as in production. Note that there are certain limitations to this approach. Within the BAS you will not have a JWT issued for your user. This means that flows like OAuth2SAMLBearerAssertion and OAuth2UserTokenExchange can only work if you provide such a JWT. This is possible in principle, but difficult within the local development environment.

Create dedicated development destinations which use the following authentications flows:

  • OAuth2ClientCredentials
  • BasicAuthentication
  • ClientCertificateAuthentication (you will have to disable the proxy until the http-proxy-agent provides a fix)

Note that for the connection to the cloud system, the destinations do not need the two properties WebIDEEnabled and HTML5.DynamicDestination, because the BAS connectivity proxy is not needed.

Supported Authentication Types for Cloud Systems

For calls to cloud systems, i.e. systems that are reachable over the internet, the local BAS proxy is not needed. However, the web proxy is used for all requests. In general, this does not cause problems except for destinations with authentication type ClientCertificateAuthentication because proxies break the certificate chain. As a workaround you can add the target system to the no_proxy environment variable in your application code. Replace DESTINATION_URL with the URL of your destination and add the following line before you execute your request:

process.env.no_proxy += ',DESTINATION_URL';