Jobs and background execution are required for various use cases. This tutorial covers two specific use cases:
-
Job scheduling by the partner: Imagine you host a poetry slam manager solution for several customers. You need to execute some logic for all subscribed consumers of your solution. For example, you want to schedule jobs that regularly run for poetry slam events of each consumer. For each customer using the application, a reminder notification (launchpad notification and email) is sent to their visitors about upcoming poetry slam events.
-
Background execution triggered by the customer: Imagine you're a poetry slam manager using a poetry slam management solution to handle events. You want to send notifications for a specific poetry slam asynchronously, using background execution. The status of this background execution appears on the poetry slam's object page.
For both use cases, the SAP Job Scheduling service is used to schedule jobs either regularly or as a one-time task. For more information, refer to What Is SAP Job Scheduling Service? on SAP Help Portal. This service also offers a dashboard for job management. In a multi-tenant landscape, only the application provider can access this dashboard. Through a web-based user interface, jobs for provider instances can be created and updated. Jobs for consumers can be viewed and edited but can't be created using the dashboard.
Note: For smaller use cases where asynchronous event handling is primarily needed, consider using the Event-Queue framework. Built on top of CAP Node.js, it's designed for efficient and streamlined asynchronous event processing. However, this approach is not covered here.
In addition to the entitlements listed for the multitenancy version, this list shows the entitlements required in the subaccounts to enable the SAP Job Scheduling service.
| Subaccount | Entitlement Name | Service Plan | Type | Quantity |
|---|---|---|---|---|
| Provider | ||||
| Job Scheduling Service | standard | Service | 1 |
The Partner Reference Application uses the SAP Job Scheduling service as a resource. This service needs to access the Poetry Slam Manager application to call actions for sending notifications. The Poetry Slam Manager provides a new service, JobSchedulerService, with the actions (generateConsumerJobs and sendReminder). It grants access to the SAP Job Scheduling service to call it directly from a job execution.
For the "Job Scheduling by the partner" use case, you as a partner manually create a job in the SAP Job Scheduling dashboard once and it's scheduled to run regularly. During each run, it executes the generateConsumerJobs action on the application instance operating within the provider subaccount. This action creates a job for each consumer and schedules it for immediate execution. The generated consumer jobs have a date parameter that specifies sending notifications for all poetry slams occurring up to that date. The job then calls the sendReminder action with the date as a parameter in the consumer subscription. It selects the relevant poetry slams and sends notifications to the registered visitors and artists.
For the "Background execution triggered by the customer" use case, the user interface of the poetry slam object page is enhanced with a button linked to the instance-based (bound) sendReminderForPoetrySlam action. This action is defined in the PoetrySlamService. It generates a job for this consumer tenant and schedules it for immediate execution. The generated job includes a poetry slam ID parameter, which specifies the poetry slam for which notifications shall be sent. The job executes the sendReminder action with the poetry slam ID as a parameter in the consumer subscription, selecting the relevant poetry slam and sending the notifications to the registered visitors and artists.
To explore this feature with the Poetry Slam Manager, you have two options:
-
Clone the repository of the Partner Reference Application. Check out the main-multi-tenant branch and enhance the application step by step.
-
Alternatively, check out the main-multi-tenant-features branch where the feature is already included.
The following describes how to enhance the main-multi-tenant branch (option 1).
-
As you're sending notifications you configured based on the Send notifications chapter, follow all enablement steps described there first.
-
Add a new OData service to the application called jobSchedulerService.
-
Copy the job scheduler service definition to a new folder
jobschedulerin thesrvfolder. The service offers actions to send reminders and to generate consumer jobs. Besides this, the required authorizations are defined. -
Copy the job scheduler service implementation to the
jobschedulerfolder. The file includes the registration of the actions that are triggered directly by the job scheduler.Note: When the SAP Job Scheduling service invokes an application endpoint, it provides request headers like the Job ID, the Job Schedule ID, the Job Run ID and the SAP Job Scheduling service Host URI. They can be utilized to use the SAP Job Scheduling service REST APIs and Node.js Client Library. For more information, see Asynchronous Mode on SAP Help Portal.
-
Copy the job scheduler action implementation to the
libfolder in thesrvfolder. The file includes the implementation of the actions to send reminders and to generate consumer jobs. -
Copy the job scheduler class to the
libfolder. This class handles the access to the job scheduler service by using the Node.js module @sap/jobs-client. -
Copy the service credentials class serviceCredentials.js to the
libfolder. This class provides functionalities to obtain credentials and tokens used for the authentication to the bound services, such as the SAP Job Scheduling service. Additionally, it includes helper functions to retrieve the provider tenant and determine the application service URL. -
Copy the tenant manager class tenantManager.js to the
libfolder. This class offers functionality to get tenant information from the Saas Provisioning service. -
Add the new service to the srv/services.cds file.
using from './jobscheduler/jobSchedulerService';
-
Include the success and error message texts for actions in the srv/i18n/messages.properties file.
ACTION_JOB_GENERATION_STARTED = The job was successfully scheduled. ACTION_JOB_GENERATION_FAILED = The job scheduling failed. ACTION_JOB_EXECUTION_STARTED = Job execution triggered. ACTION_JOB_EXECUTION_FAILED = Job could not be triggered. ACTION_JOB_REMINDER_SEND_FAIL = The reminder could not be sent. ACTION_JOB_REMINDER_NO_ID_OR_DATE = A valid Poetry Slam ID or date is missing.Note: In the reference example, the srv/i18n/messages_de.properties file with the German texts is also available. You can adopt them accordingly.
-
For local testing, define a new user in the .cdsrc.json file. This user has access only to the SAP Job Scheduling service.
"TechnicalJobSchedulerUser": { "password": "welcome", "id": "jobservice", "roles": ["JobScheduler", "authenticated-user"] }
-
-
Enhance the production section in the package.json of your project by enabling the CDS SaaS Provisioning service.
"[production]": { "multitenancy": true, "cds.xt.SaasProvisioningService": true }
-
Add the following scope and role template to the xs-security.json file. It enables the SAP Job Scheduling service to access the Poetry Slam Manager application:
{ "scopes": [ ... { "name": "$XSAPPNAME.JobScheduler", "description": "SAP Job Scheduling Scope", "grant-as-authority-to-apps": [ "$XSSERVICENAME(poetry-slams-jobscheduler)" ] } ] ... } -
Add the required npm modules as dependencies to the package.json of your project:
-
Open a terminal. Ensure that your project root folder is selected.
-
Run the following command to add the
@sap/jobs-clientnpm package. This node module integrates the SAP Job Scheduling service.npm add @sap/jobs-client -
Add the
@sap-cloud-sdk/http-clientwith the following command. This node module offers a generic http-client.npm add @sap/jobs-client -
Install the required npm modules for the application.
npm install
-
-
Enhance the poetry slam manager domain model.
-
Enhance the
PoetrySlamsentity of the db/poetrySlamManagerModel.cds domain model with a new field that describes the job status.entity PoetrySlams : cuid, managed { ... jobStatusText : String(255) default 'Job not triggered yet'; }
-
Annotate the
PoetrySlamsentity of the db/poetrySlamManagerModel.cds domain model with the jobStatus.annotate PoetrySlams with @fiori.draft.enabled { ... jobStatusText @title: '{i18n>jobStatusText}' @readonly; }
-
Add the UI text for the field into the /db/i18n/i18n_de.properties file.
jobStatusText = Event Reminder StatusNote: In the reference example, the /db/i18n/i18n_de.properties file with the German texts is also available. You can adopt them accordingly.
-
-
Enhance the poetry slam service.
-
Add a new field named
isJobStatusShownto the entity PoetrySlams in the poetry slam service definition. The field controls the visibility of the job scheduling status section on the user interface.virtual null as isJobStatusShown : Boolean @odata.Type: 'Edm.Boolean',
-
Add a new action named
sendReminderForPoetrySlamto the entity PoetrySlams in the poetry slam service definition. The action sends a notification to all visitors of a specific poetry slam.// Action: Schedule to once send reminder to all visitors for a specific poetry slam event @( // Determines that poetryslam entity is used when the action is performed cds.odata.bindingparameter.name: 'poetryslam', // Defines that poetryslam entity is affected and targeted by the action Common.SideEffects : {TargetProperties: [ 'poetryslam/isJobStatusShown', 'poetryslam/jobStatusText' ]} ) action sendReminderForPoetrySlam() returns PoetrySlams;
-
Add the implementation of the read-handler of the poetry slam entity in the poetry slam service to set the value of the
isJobStatusShownfield.srv.on('READ', [PoetrySlams.drafts, PoetrySlams], async (req, next) => { // Read the PoetrySlams instances let poetrySlams = await next(); // In this method we enrich the data from the database by external data and calculated fields // In case none of these enriched fields are requested, we do not need to read from the external services // So we first check if the requested columns contain any of the enriched columns and return if not const requestedColumns = req.query.SELECT.columns?.map((item) => Array.isArray(item.ref) ? item.ref[0] : item.as ); const enrichedFields = [ 'isJobStatusShown' ]; if ( requestedColumns && !enrichedFields.some((item) => requestedColumns?.includes(item)) ) { return poetrySlams; } for (const poetrySlam of convertToArray(poetrySlams)) { // Display information about background execution if (poetrySlam.jobStatusText !== 'Job not triggered yet') { poetrySlam.isJobStatusShown = true; } else { poetrySlam.isJobStatusShown = false; } } });
-
Copy the file poetrySlamServiceJobSchedulerImplementation.js to directory srv/poetryslam/. It includes the implementation of the action sendReminderForPoetrySlams, which schedules a job with predefined parameters. The parameters include the scheduling data, like the time to execute the job, a description and the poetry slam ID. Additionally, it states that the action
sendRemindershall be triggered by the job. -
Add the job scheduling implementation handler to the srv/poetryslam/poetrySlamServiceImplementation.js file.
const jobSchedulerHandler = require('./poetrySlamServiceJobSchedulerImplementation'); module.exports = class extends cds.ApplicationService { async init() { ... await jobSchedulerHandler(this); // Forward handler for output ... } };
-
-
Enhance the SAP Fiori elements UI of the Poetry Slams application.
-
Open the app/poetryslams/annotations.cds file to add a section that shows the job execution status.
-
Annotate service.PoetrySlams with a new hidden field isJobStatusShown.
isJobStatusShown @UI.Hidden;
-
Add a new field group BackgroundExecution with the jobStatus.
FieldGroup #BackgroundExecution: { $Type: 'UI.FieldGroupType', Data : [{ $Type: 'UI.DataField', Value: jobStatusText }] }
-
Add a new facet BackgroundExecution that is only visible in case a job was already triggered for the current poetry slam.
{ $Type : 'UI.ReferenceFacet', Label : '{i18n>backgroundExecution}', ID : 'BackgroundExecution', Target : '@UI.FieldGroup#BackgroundExecution', ![@UI.Hidden]: {$edmJson: {$Not: {$Path: 'isJobStatusShown'}}} // Display Job Status if SendReminder triggered } -
Add the action to send the reminder for the poetry slam in the background to the Identification section.
{ $Type : 'UI.DataFieldForAction', Action: 'PoetrySlamService.sendReminderForPoetrySlam', Label : '{i18n>sendReminderForPoetrySlams}', ![@UI.Hidden]: {$edmJson: {$Not: {$Path: 'IsActiveEntity'}}} },
-
-
Add the UI text for the button into the /app/poetryslams/i18n/i18n.properties file.
backgroundExecution = Background Execution sendReminderForPoetrySlams = Send Event ReminderNote: In the reference example, the file /app/poetryslams/i18n/i18n_de.properties with the German texts is also available. You can adopt them accordingly.
-
-
Add the SAP Job Scheduling service as resource into the mta.yaml file. In addition, the resource is also required as dependency in the service, mtx modules, and the app router.
modules: - name: poetry-slams-srv requires: - name: poetry-slams-jobscheduler - name: poetry-slams-mtx requires: - name: poetry-slams-jobscheduler - name: poetry-slams requires: - name: poetry-slams-jobscheduler resources: # Authorization XSUAA service # Manages authentication, single sign-on (SSO), user management, and provides a way to manage authorizations based on scopes and role collections - name: poetry-slams-auth type: org.cloudfoundry.managed-service requires: ... processed-after: [poetry-slams-jobscheduler] # Ensure that poetry-slams-jobscheduler is created before poetry-slams-auth ... # Job scheduler Service - name: poetry-slams-jobscheduler type: org.cloudfoundry.managed-service parameters: service: jobscheduler service-plan: standard config: enable-xsuaa-support: true
Note: Since the job scheduler resource is referenced as a scope in the xs-security.json, it has to be created before the SAP Authorization and Trust Management Service (XSUAA) service. Therefore, ensure that
processed-after: [poetry-slams-jobscheduler]is set for poetry-slams-auth otherwise the deployment might throw an error.
-
Register the service in the multi-tenant environment mtx/sidecar/package.json (see SaaS Registry Dependencies):
"cds": { ... "requires": { ... "poetry-slams-jobscheduler": { "vcap": { "label": "jobscheduler" }, "subscriptionDependency": { "uaa": "xsappname" } } } }
-
Open the SAP BTP cockpit of the provider subaccount and add the required entitlements:
- Job Scheduling Service with the standard plan to schedule jobs.
-
Build and deploy the application. As a result, a Job Scheduling Service instance named poetry-slams-jobscheduler is created.
Note: For detailed instructions on how to deploy, refer to Deploy Your SAP BTP Multi-Tenant Application.
To ensure good quality, it is crucial to test the new functionality. Unit tests are available to test this feature:
-
Copy the test/srv/jobscheduler/jobSchedulerService.test.js file to your project. This file tests the implementation of the job scheduler service.
-
Copy the test/srv/poetryslam/poetrySlamServiceJobSchedulerImplementation.test.js file to your project. This file tests the implementation of the poetry slam service enhancements with the sendReminderForPoetrySlam action.
-
Copy the test/srv/lib/jobScheduler.test.js file to your project. This file tests the jobScheduler class.
-
Copy the test/srv/lib/jobSchedulerActionImplementation.test.js file to your project. This file tests the jobSchedulerActionImplementation class.
-
Copy the test/srv/lib/tenantManager.test.js file to your project. This file tests the tenantManager class.
-
To run the automated SAP Cloud Application Programming Model tests:
- Enter the command
npm installin a terminal in SAP Business Application Studio. - Enter the command
npm run test. All tests are carried out and the result is shown afterwards.
- Enter the command
For the "Job scheduling by the partner" use case, the job that is regularly scheduled needs to be created.
-
Open the SAP BTP cockpit of the provider subaccount.
-
Create a subscription of the Poetry Slam Manager in the provider subaccount.
As the generateConsumerJobs action runs in the context of the provider, a subscription of the PoetrySlamManager in the provider subaccount is required.
-
In the SAP BTP cockpit of the provider subaccount, navigate to Instances and Subscriptions.
-
Create a subscription to the Poetry Slam Manager with service plan default.
Note: No further setup or usage of the subscription is required.
-
-
Determine the application route of the poetry slams service.
-
Navigate to Cloud Foundry > Spaces.
-
Select the space hosting the deployed Poetry Slam Manager application.
-
Select the poetry-slams-srv application.
-
Copy the URL of the application route and note it as application route URL.
-
-
Setup a role collection to define who is allowed to maintain jobs and schedules.
-
Navigate to Security > Role Collections.
-
Create a new role collection called JobSchedulingManager.
-
Add the role "SAP_Job_Scheduling_Service_Admin" to the newly created role collection.
-
Assign Users and/or UserGroups to the new role collection.
-
-
In Instances and Subscriptions, select the service instance poetry-slams-jobscheduler. The Job Scheduling Service Dashboard opens.
-
Create a job with the following information:
Parameter Value Name: GenerateConsumerJobs Description: Manually created job to generate jobs for consumer subscriptions Action: application route URL/odata/v4/jobschedulerservice/generateConsumerJobs HTTP Method: POST Activate Job: Yes Note: the job is deleted in case the application will be undeployed.
-
Create a schedule for the job with the following information:
Parameter Value Description: Immediately Pattern: One Time Value: now Data (JSON): {} Note: Besides one-time schedules, recurring schedules are supported. A one-time schedule executes the job once at a specific time. Recurring schedules allow the job to run multiple times with a defined recurrence. For more details, refer to Schedule Types. The job remains available regardless of the scheduling type.
Note: With this creation, the job is executed directly.
As the application provider, you can analyze a job execution.
-
Open the SAP BTP cockpit of the provider subaccount.
-
In Security -> Role Collections, create a role collection called JobSchedulingManager. Edit this role collection, add the role "SAP_Job_Scheduling_Service_Admin" and Users and/or UserGroups who should be entitled to maintain jobs and schedules.
-
Open the poetry-slams-jobscheduler. The Job Scheduling Service Dashboard is shown.
-
Navigate to the Jobs view. The overview shows the triggered jobs with the subdomain and tenant ID (context of the job), the creation date, and the schedule counts.
-
Choose a job to view the details.
-
Navigate to the Schedules view.
-
Open a schedule. Depending of the job, in the Data (JSON) section, you'll find specific job information if available.
-
Navigate to the Run Logs view. An overview is shown with the executed runs. For each run, the scheduled time, execution time, completion time, and status are listed.
-
Choose a run to view its log. The log displays messages from the run.
Now it is time to take you on a guided tour through the job scheduling feature of Poetry Slam Manager:
Note: This exploration is intended for the application provider. The generated notification will be retrieved by the users of the customers.
-
Open the SAP BTP cockpit of the provider subaccount.
-
Open the poetry-slams-jobscheduler. The Job Scheduling Service Dashboard is shown.
-
Navigate to the Jobs view. The overview shows the triggered jobs with the subdomain and tenant ID (context of the job), the creation date and the schedule counts.
-
Click on the job GenerateConsumerJobs to view the details. This job runs in context of the provider tenant.
-
Navigate to the Schedules view.
-
Open the schedule with the name Immediately.
-
Navigate to the Run Logs view. An overview is shown with the executed runs. For each run, the scheduled time, the execution time, completion time and the status is listed.
-
Click on one run. The run log is displayed. It shows messages from the run.
Now it is time to take you on a guided tour through the background execution feature of Poetry Slam Manager:
Note: This exploration is intended for the application user.
-
Launch your SAP Build Work Zone site by opening the page URL you noted down during the multitenancy provisioning. On the site, you find Poetry Slams and Visitors, the partner applications.
-
Open the Visitors application.
-
Choose Create to create a new visitor.
-
Enter a name and your email address and create the visitor.
-
Choose Maintain Poetry Slams to navigate to the poetry slams application.
-
Create a new poetry slam.
-
Enter the mandatory data and save the poetry slam.
-
Publish the poetry slam.
-
Edit the poetry slam and create a new booking.
-
Select the newly created visitor and save your changes.
-
Select the booking from the list.
-
Choose Send Reminder. You get the information that the job execution was successfully triggered.
Note: A new section called Background Execution is shown on the object page. This section shows the event reminder status. For instance, it displays Job execution triggered. when the job is running. It displays Visitors: 2, Notifications sent 2. when the notifications are successfully sent.
Now, let's have a look how you as the application provider can analyze the background execution.
-
Open the SAP BTP cockpit of the provider subaccount.
-
Open the poetry-slams-jobscheduler. The Job Scheduling Service Dashboard is shown.
-
Navigate to the Jobs view. The overview shows the triggered jobs with the subdomain and tenant ID (context of the job), the creation date, and the schedule counts.
-
Choose the send_reminder_for_event() job to view the details. This job runs in context of the customer tenant.
-
Navigate to the Schedules view.
-
Open the schedule called Immediately for Poetry Slam Number . In the Data (JSON) section, the poetry slam ID, you'll find the poetry slam ID for which the reminder is sent.
Note: The data section is set in the poetry slam job scheduler implementation.
-
Navigate to the Run Logs view. An overview is shown with the executed runs. For each run, the scheduled time, execution time, completion time, and status is listed.
-
Choose a run to view its log. The log displays messages from the run.
Note: One message is added in the job scheduler action implementation. This message informs you about the number of subscribed tenants for whom jobs were successfully scheduled.
