Open codeyogi911 opened 1 week ago
Hi @codeyogi911,
cds.spawn
should help you with your use case as described here.
cds.spawn ({ tenant:'t0', every: 1000 /* ms */ }, async (tx) => {
const mails = await SELECT.from('Outbox')
await MailServer.send(mails)
await DELETE.from('Outbox').where (`ID in ${mails.map(m => m.ID)}`)
})
@alperdedeoglu I am aware about how to use cds.spawn
, what I want to find out is how to run with a jwt
in the background?
@codeyogi911 What kind of SAP Backend are we talking about? Can you explain the exact use case you have? If that is S/4HANA Private Cloud or on-premise, you need to get the token for destination service on behalf of your tenant. You can do this each time when your job gets executed. I am having hard times understanding what is the actual problem you are having.
I have an SAP Onprem system connected to our multi-tenant app. We are running in the background a Auto Sales Order
job. When connecting to the backend API it fails because there is no jwt
. Is there a way to configure and use technical user
for each tenant?
What i did currently is get the jwt
using password_grant
(which is not correct) and created a cds.user
using this token and @sap/xssec
. I am then using this user in the cds.spawn
.
I feel like its a work around and there should be a way to configure and use background users.
Where exactly do you get your JWT from? Do you mean the XSUAA? By Backend API do you mean CAP API or S/4 API?
Right now as a workaround i get the jwt
from the bound XSUAA using a password_grant
. Backend API means S4 API using Destinations and Cloud Connector.
Right now as a workaround i get the
jwt
from the bound XSUAA using apassword_grant
. Backend API means S4 API using Destinations and Cloud Connector.
And are you using Cloud SDK or something to connect to the backend? Or have you defined a destination? How do you call the on-premise backend? Which library do you use?
I have my function to create sales order defined like:
async function createSalesOrder(orderData) {
LOGGER.info("Creating sales order: ", cds.context.user)
const salesSrv = await cds.connect.to("API_SALES_ORDER_SRV", {
destinationOptions: {
jwt: cds.context.user.tokenInfo.getTokenValue(),
}
})
const result = await salesSrv.create("A_SalesOrder").entries(orderData)
LOGGER.info("Sales order created", result.SalesOrder)
return result
}
earlier i had it defined like:
async function createSalesOrder(orderData) {
let salesSrv
if (cds.context.isPrivilegedSpawn) {
const subDomain = await getTenantSubdomain(cds.context.tenant)
LOGGER.info("Subdomain for tenant", subDomain)
LOGGER.info("Creating sales order for tenant using basic authentication", cds.context.tenant)
salesSrv = await cds.connect.to("API_SALES_ORDER_SRV", {
credentials: {
destination: "onpremise-basic",
path: "/sap/opu/odata/sap/API_SALES_ORDER_SRV",
},
destinationOptions: {
selectionStrategy: "alwaysSubscriber",
iss: `https://${subDomain}.authentication.eu10.hana.ondemand.com/oauth/token`,
useCache: true,
},
})
} else {
salesSrv = await cds.connect.to("API_SALES_ORDER_SRV")
}
const result = await salesSrv.create("A_SalesOrder").entries(orderData)
LOGGER.info("Sales order created", result.SalesOrder)
return result
}
so this stopped working after the upgrading to CDS8, it somehow now gives me 401 when using onpremise-basic
and even if i try in the foreground then also it gives me 401, even though it should use the onpremise
in foreground.
Somehow the destination is not getting cached even after setting
"API_SALES_ORDER_SRV": {
"kind": "odata-v2",
"model": "srv/external/API_SALES_ORDER_SRV",
"csrf": true,
"csrfInBatch": true,
"[production]": {
"credentials": {
"destination": "onpremise",
"path": "/sap/opu/odata/sap/API_SALES_ORDER_SRV"
},
"destinationOptions": {
"selectionStrategy": "alwaysSubscriber",
"useCache": false
}
}
},
Ok got it, can you just give the jwt
with retrieving a token via client_credentials
and let me know how it goes?
I have a use case where the background job needs to access the backend system via
destinations
in a multi tenant app. How can i achieve this? Basically i want to run a background job with atechnical user