cf CLI
). Installation instructions can be found in the CloudFoundry documentation.example-app
. In this directory, create a package.json
file with the following content:{
"name": "example-app",
"version": "1.0.0",
"description": "Example application using the SAP S/4HANA Cloud SDK for JavaScript.",
"scripts": {
"start": "ts-node src/server.ts"
},
"dependencies": {
"express": "^4.16.3"
},
"devDependencies": {
"ts-node": "^7.0.1",
"typescript": "^3.0.3"
}
}
package.json
acts as a project descriptor used by npm
, the Node.js package manager.example-app
directory in your terminal and call npm install
. This will install the necessary dependencies for our application.tsconfig.json
with the following content:{
"typeAcquisition": {
"enable": true
}
}
src
inside your example-app
and add two files: First, server.ts
, that will contain the logic for starting the webserver.import app from './application';
const port = 8080;
app.listen(port, () => {
console.log('Express server listening on port ' + port);
});
application.ts
, that contains the logic and routes of our application.import * as bodyParser from 'body-parser';
import * as express from 'express';
import { Request, Response } from 'express';
class App {
public app: express.Application;
constructor() {
this.app = express();
this.config();
this.routes();
}
private config(): void {
this.app.use(bodyParser.json());
this.app.use(bodyParser.urlencoded({ extended: false }));
}
private routes(): void {
const router = express.Router();
router.get('/', (req: Request, res: Response) => {
res.status(200).send('Hello, World!');
});
this.app.use('/', router);
}
}
export default new App().app;
routes
function:router.get('/', (req: Request, res: Response) => {
res.status(200).send('Hello, World!');
});
router.get
) on the root path of the application ('/'
, the first parameter) by calling the function provided as the second parameter. In this function, we simply send a response with status code 200 and 'Hello, World!'
as body.npm start
. This will in turn execute the command we have defined for start
in the scripts
section of our package.json
."scripts": {
"start": "ts-node src/server.ts"
}
npm start
, you should see the following output in your terminal: Express server listening on port 8080
. Now you can visit http://localhost:8080
in your browser, and you will be greeted with Hello, World!
in response!.tgz
archive and unpacked it, which gave us a directory called s4sdk
. Now we need to copy this directory into the example-app
directory. Then, we can add the SDK as a dependency to our application by adding two entries to the dependencies
section of our package.json
so that this section looks as follows (don't forget to add a comma behind the second line):"dependencies": {
"express": "^4.16.3",
"s4sdk-core": "file:s4sdk/s4sdk-core",
"s4sdk-vdm": "file:s4sdk/s4sdk-vdm"
}
file:
prefix instructs npm to install the dependencies from your machine instead of fetching them from the npm registry.npm install
again to install the SDK to your project. In a development environment such as Visual Studio Code, this will also make available the types of the SAP S/4HANA Cloud SDK for code completion.routes
function in application.ts
.import { BusinessPartner } from 's4sdk-vdm/business-partner-service';
router.get('/businesspartners', (req: Request, res: Response) => {
BusinessPartner.requestBuilder()
.getAll()
.top(100)
.execute()
.then((businessPartners: BusinessPartner[]) => {
res.status(200).send(businessPartners);
});
});
import { BusinessPartner } from 's4sdk-vdm/business-partner-service';
/businesspartners
. Then, we use the SDK's Virtual Data Model (VDM) to retrieve business partners from our SAP S/4HANA Cloud system. The VDM, originally introduced in the SAP S/4HANA Cloud SDK for Java, allows you to query OData services exposed by your SAP S/4HANA Cloud system in a type-safe, fluent and explorative way. More details can be found in this blog post introducing the VDM in the SDK for Java.BusinessPartner.requestBuilder()
. This in turn will offer you a function for each operation that you can perform on the respective entity. In the case of business partners, the possible operations are getAll()
, getByKey()
, create()
and update()
. We choose getAll()
, since we want to retrieve a list of business partners. Now we can choose from the variety of options to further refine our query, such as select()
and filter()
. However, for now we keep it simple by only calling top(100)
to restrict the query to the first 100 results. Finally, we call execute()
. The SDK takes care of the low level infrastructure code of the request.then()
and providing it with a function that handles the query result. As you can see from the signature of the callback function, promises returned by the VDM are automatically typed with the respective entity, in this case we get an array of business partners (BusinessPartner[]
). Now we can simply send a response with status code 200 and the business partners retrieved from the SAP S/4HANA system as response body.set destinations=[{"name":"ErpQueryEndpoint", "url": "https://mys4hana.com", "username": "myuser", "password":"mypw"}]
npm start
and navigate to http://localhost:8080/businesspartners
, you should see a list of business partners retrieved from your SAP S/4HANA Cloud system.manifest.yml
file. Add this file to the root directory of your application.---
applications:
- name: example-app
memory: 256M
random-route: true
buildpacks:
- nodejs_buildpack
command: npm start
env:
destinations: >
[
{
"name": "ErpQueryEndpoint",
"url": "https://mys4hana.com",
"username": "<USERNAME>",
"password": "<PASSWORD>"
}
]
env
section. Here, we provide the destination settings for the SAP S/4HANA system we want to connect to. Simply substitute the value for each entry with the respective values for your SAP S/4HANA system.package.json
."engines": {
"node": "10.14.1"
}
package.json
leads to CloudFoundry defaulting to an older version of node. However, the VDM relies on some features only present in newer version of Node.js. Additionally, as in any project, it is good practice to specifiy the version of the runtime environment to protect yourself from errors introduced in unwanted version changes down the line.package.json
should look as follows:{
"name": "example-app",
"version": "1.0.0",
"description": "Example application using the SAP S/4HANA Cloud SDK for JavaScript.",
"scripts": {
"start": "ts-node src/server.ts"
},
"dependencies": {
"express": "^4.16.3",
"s4sdk-core": "file:s4sdk/s4sdk-core",
"s4sdk-vdm": "file:s4sdk/s4sdk-vdm"
},
"devDependencies": {
"ts-node": "^7.0.1",
"typescript": "^3.0.3"
},
"engines": {
"node": "10.14.1"
}
}
cf push
on your command line in the root directory of the application. This uses the Cloud Foundry command line interface (CLI), whose installation is described in this blog post. The cf CLI
will automatically pick up the manifest.yml
. At the end of the deployment, cf CLI
will print the URL under which you can access your application. If you now visit the /businesspartners
route of your application at this URL, you should see a list of business partners that have been retrieved from your SAP S/4HANA system! This requires that the URL of the system you connect to is accessible from Cloud Foundry.s4sdk
and javascript
.import { BusinessPartner, Customer } from 's4sdk-vdm/business-partner-service';
import { and, or } from 's4sdk-core';
BusinessPartner.requestBuilder()
.getAll()
.select(
BusinessPartner.FIRST_NAME,
BusinessPartner.LAST_NAME,
BusinessPartner.TO_CUSTOMER.select(Customer.CUSTOMER_FULL_NAME)
)
.filter(
or(
BusinessPartner.BUSINESS_PARTNER_CATEGORY.equals('1'),
and(
BusinessPartner.FIRST_NAME.equals('Foo'),
BusinessPartner.TO_CUSTOMER.filter(Customer.CUSTOMER_NAME.notEquals('bar'))
)
)
)
.execute();
BusinessPartner.
in your editor. The autocompletion of modern editors, such as Visual Studio Code, will then provide a list of suggestions, which you can navigate to find the fields you need, without having to refer to the service's metadata. Furthermore, we ensure that each query you build is type-safe. This means that if you try to e.g. select a field that does not exist on the respective entity, your editor will report a type mismatch, effectively preventing your from writing incorrect queries.Customer
, a related entity, to your selection, from which we only use the full name.and()
and or()
functions. Each field also provides a function for each filter operation that can be used on the respective field. Additionally, we again make sure that the values you provide in the filter clause match the type of the respective field. If, for example, you'd try to filter a string-typed field by a number (e.g. BusinessPartner.FIRST_NAME.equals(5)
), a type mismatch will be reported.execute()
in our queries. If no parameter is provided, execute()
will by default try to load a destination named "ErpQueryEndpoint" from your application's environment variables (the one we configured in the manifest.yml
, remember?). You can of course provide more destinations. If you want to use a specific destination for your OData queries, you do so by passing the destination's name to the execute call, like this:execute('MyCustomDestination')
execute({
url: "https://mys4hana.com/",
username: "MyUser",
password: "MyPassword"
})
Authorization
header directly.BusinessPartner.requestBuilder()
...
.withCustomHeaders({
Authorization: "Bearer <EncodedJWT>"
})
.execute()
Authorization
header using this mechanism, the VDM will ignore the username and password otherwise provided by any destination configuration.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
24 | |
11 | |
11 | |
8 | |
7 | |
7 | |
7 | |
6 | |
5 | |
5 |