Since CDS 5.9.2 this is the quickest way of creating and deploying the bookshop sample:
cds init bookshop
cd bookshop
cds add samples
cds add hana
cds add xsuaa
cds add mta
npm install
mbt build
cf deploy mta_archives/bookshop_1.0.0.mtar
SAP
Since CDS 5.9.2 this is the quickest way of creating and deploying the bookshop sample:
cds init bookshop
cd bookshop
cds add samples
cds add hana
cds add xsuaa
cds add mta
npm install
mbt build
cf deploy mta_archives/bookshop_1.0.0.mtar
Somehow I always forget the syntax for this….
TYPES: BEGIN OF ty_test.
INCLUDE TYPE z_table.
TYPES: my_new_field TYPE string,
END OF ty_test.
https://sap.github.io/cloud-sdk/docs/js/features/connectivity/destination
const { getDestination } = require("@sap-cloud-sdk/connectivity")
const myDestination= await getDestination("myDestination")
if (myDestination === null) throw Error(`Destination "myDestination" not found`)
for (let key in myDestination) {
console.log(key, myDestination[key])
}
If the default port 4004 is already open and you want to see what is bound to it, select View -> Find Command -> Ports Preview
Solution to kill another “watch.js” process using/blocking the port: https://answers.sap.com/questions/13016130/sap-business-application-studio-stop-running-serve.html
To archive the same in a single command use:
lwctl -c basic-tools kill -9 $(lwctl -c basic-tools ps aux | grep watch.js | awk '{print $2}')
As alternative, change the default port by adding a new port in package.json to the start script, for example: “start”: “cds run –port 4003” and use npm run start instead of cds watch.
Update 20.02.2023: Just had the problem again due to a VPN disconnect. But this time I had an application running using cds run
. Therefore, I had to change the command from watch.js
to cds.js
:
lwctl -c basic-tools kill -9 $(lwctl -c basic-tools ps aux | grep cds.js | awk '{print $2}')
Update 10.05.2023: A better approach seems to be killing the node process. This should work in both situation.
lwctl -c basic-tools kill -9 $(lwctl -c basic-tools ps aux | grep node | awk '{print $2}')
Update 29.02.2024: With the BAS migration to Code – OSS the previous commands were not working anymore, but this new command seems to work:
kill -9 $(ps aux | grep cds.js | awk '{print $2}')
const sfsfSrv = await cds.connect.to('sfsf')
// Option 1: Query Notation
const response = await sfsfSrv.run(SELECT`teamMembersSize`.from`User`.where`userId = ${req.user.id}`)
console.log("option 1: " + response[0].teamMembersSize)
// Option 2: HTTP method-style
const response2 = await sfsfSrv.get(`/User('${req.user.id}')/teamMembersSize/$value`)
console.log("option 2: " + response2)
An easy way to test your approuter is using the user-api-service. For that add the following route to your xs-app.json
{
"source": "^/user-api(.*)",
"target": "$1",
"service": "sap-approuter-userapi"
}
And after deployment, open the application router URL and add /user-api/currentUser
to it. You should see your Email and other User details. This is testing that the application router is actually getting the security token from the UAA instance.
These three entries in a .env file
cds.requires.ECEmploymentInformation.[development].credentials.authentication=BasicAuthentication
cds.requires.ECEmploymentInformation.[development].credentials.username=myUsername
cds.requires.ECEmploymentInformation.[development].credentials.password=myPassword
are equal to line 12, 13, and 14 in this package.json snippet:
{
"cds": {
"ECEmploymentInformation": {
"kind": "odata-v2",
"model": "srv/external/ECEmploymentInformation",
"credentials": {
"[production]": {
"destination": "sfsf"
},
"[development]": {
"url": "https://apisalesdemo2.successfactors.eu/odata/v2",
"authentication": "BasicAuthentication",
"username": "myUsername",
"password": "myPassword",
}
}
}
}
}
https://sapui5.hana.ondemand.com/#/api/sap.ui.core.EventBus%23overview
In the receiving controller you need to subscribe your eventId and function you want to call from the second controller:
// Attaches an event handler to the event with the given identifier on the given event channel
this.getOwnerComponent().getEventBus().subscribe("Default", "myEventId", () => {
this._myFunctionIWantToCall();
});
The sending controller has to publish the event to trigger the function call:
// Fires an event using the specified settings and notifies all attached event handlers.
this.getOwnerComponent().getEventBus().publish("Default", "myEventId", {});
Get:
const oModel = this.getView().getModel()
const sPath = this.getView().getBindingContext().sPath
const sID = oModel.getProperty(sPath+"/ID")
Set:
const newID = "12345"
oModel.setProperty(sPath+"/ID", newID)
When using the set property function, you can now submit your changes this way:
// First check if there are any changes
if (!oModel.hasPendingChanges()) {
MessageToast.show("Nothing to do!")
return
}
// Now submit your changes
oModel.submitChanges({
success: () => MessageToast.show("Success!"),
error: (err) => alert(err)
})
This way is much more comfortable, than using oModel.update()
.