Use the SAP Cloud SDK in the SAP Cloud Application Programming Model
- How to integrate the SAP Cloud SDK into the SAP Cloud Application Programming Model
- How to write a custom event handler for CAP Java
- How to deploy an application to SAP Cloud Platform Cloud Foundry
- How to create service that reads/writes business partners from S/4HANA and exposes them as SAP Cloud Application Programming Model
Prerequisites
- SAP Cloud Application Programming Model
- Basic knowledge of Spring Boot and Java (optional)
- An account on Cloud Foundry
- Understand how to Connect to an OData Service using SAP Cloud SDK
SAP Cloud Application Programming Model enables you to quickly create business applications by allowing you to focus on your business domain. It offers a consistent end-to-end programming model for full-stack development on SAP Cloud Platform.
However, this raises the question how this interacts and integrates with other SAP frameworks that SAP has introduced over the past year such as the SAP Cloud SDK.
In particular, you will learn how to integrate the SAP Cloud SDK into the SAP Cloud Application Programming Model. And how the SAP Cloud SDK allows you to develop, extend and communicate with other SAP solutions.
Also check out the full documentation on how the Cloud SDK integrates with CAP.
- Step 1
For local development, you need to do the following:
-
Install Node.js from https://nodejs.org (use the latest LTS release).
-
Install the
cds
development kit globally:ShellCopynpm i -g @sap/cds-dk
-
Now, run:
Shell/BashCopymvn archetype:generate -DarchetypeArtifactId=cds-services-archetype -DarchetypeGroupId=com.sap.cds -DarchetypeVersion=RELEASE \ -DartifactId=cap-business-service -DgroupId=org.your.org.cap.test
This will initialise the application using the maven archetype
cds-services-archetype
and create your project as follows:- The project is named
cap-business-service
. - The
db
folder stores database-related artifacts. - The
srv
folder stores your Java application.
- The project is named
Find more information about the SAP Cloud Application Programming Model in its documentation.
-
- Step 2
CAP applications use Core Data Services (CDS) to describe:
- Data structures by using entity definitions
- How data structures are consumed by using service definitions
In this step, you’ll define a data model, which defines the entity.
-
Right-click on the
db
folder and choose New File. -
Call it
datamodel.cds
and click OK to create the file. -
Add the following service definition to the file.
CDSCopynamespace my.bookshop; entity CapBusinessPartner { key ID : String; firstName : String; surname : String; sourceDestination: String; }
- Step 3
In this step, you’ll define a simple service, which exposes a projection on the entity defined in the data model.
-
Right-click the
srv
folder and choose New File. -
Call the file
cat-service.cds
and click OK. -
Add the following service definition to the
cat-service.cds
:CDSCopyusing my.bookshop as my from '../db/datamodel'; service cloud.sdk.capng { entity CapBusinessPartner as projection on my.CapBusinessPartner; }
-
Run the following command in the terminal to trigger the maven build process:
ShellCopymvn clean install
In your project directory, the data model has auto-generated the classes.
-
- Step 4
For integrating the SAP Cloud SDK in SAP Cloud Application Programming Model, you need to add the following dependency in your parent POM, which you find in the root directory of your project:
XMLCopy<dependencyManagement> <dependencies> <dependency> <groupId>com.sap.cloud.sdk</groupId> <artifactId>sdk-bom</artifactId> <version>use-latest-version-here</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Please make sure to always use the latest version available on Maven Central. Check out the release notes.
Since your application is running on SAP Cloud Platform Cloud Foundry, include the following dependencies to your
pom.xml
in thesrv
directory:XMLCopy<dependency> <groupId>com.sap.cloud.sdk</groupId> <artifactId>sdk-core</artifactId> </dependency> <dependency> <groupId>com.sap.cds</groupId> <artifactId>cds-integration-cloud-sdk</artifactId> </dependency>
For more information, visit the documentation of the SAP Cloud SDK.
- Step 5
- Create a new Java class
BusinessPartnerReadListener
with the following content:
JavaCopy@Component @ServiceName("cloud.sdk.capng") public class BusinessPartnerReadListener implements EventHandler { // TODO: uncomment the lines below and insert your API key, if you are using the sandbox service // private static final String APIKEY_HEADER = "apikey"; // private static final String SANDBOX_APIKEY = ""; @On(event = CdsService.EVENT_READ, entity = "cloud.sdk.capng.CapBusinessPartner") public void onRead(CdsReadEventContext context) throws ODataException { final Destination destination = DestinationAccessor.getDestination("MyErpSystem"); final Map<Object, Map<String, Object>> result = new HashMap<>(); final List<BusinessPartner> businessPartners = new DefaultBusinessPartnerService() .getAllBusinessPartner() .top(10) // TODO: uncomment the line below, if you are using the sandbox service // .withHeader(APIKEY_HEADER, SANDBOX_APIKEY) .executeRequest(destination); final List<CapBusinessPartner> capBusinessPartners = convertS4BusinessPartnersToCapBusinessPartners(businessPartners, "MyErpSystem"); capBusinessPartners.forEach(capBusinessPartner -> { result.put(capBusinessPartner.getId(), capBusinessPartner); }); context.setResult(result.values()); } @On(event = CdsService.EVENT_CREATE, entity = "cloud.sdk.capng.CapBusinessPartner") public void onCreate(CdsCreateEventContext context) throws ODataException { final Destination destination = DestinationAccessor.getDestination("MyErpSystem"); Map<String, Object> m = context.getCqn().entries().get(0); BusinessPartner bp = BusinessPartner .builder() .firstName(m.get("firstName").toString()) .lastName(m.get("surname").toString()) .businessPartner(m.get("ID").toString()) .build(); new DefaultBusinessPartnerService() .createBusinessPartner(bp) // TODO: uncomment the line below, if you are using the sandbox service // .withHeader(APIKEY_HEADER, SANDBOX_APIKEY) .executeRequest(destination); } private List<CapBusinessPartner> convertS4BusinessPartnersToCapBusinessPartners( final List<BusinessPartner> s4BusinessPartners, final String destinationName) { final List<CapBusinessPartner> capBusinessPartners = new ArrayList<>(); for (final BusinessPartner s4BusinessPartner : s4BusinessPartners) { final CapBusinessPartner capBusinessPartner = com.sap.cds.Struct.create(CapBusinessPartner.class); capBusinessPartner.setFirstName(s4BusinessPartner.getFirstName()); capBusinessPartner.setSurname(s4BusinessPartner.getLastName()); capBusinessPartner.setId(s4BusinessPartner.getBusinessPartner()); capBusinessPartner.setSourceDestination(destinationName); capBusinessPartners.add(capBusinessPartner); } return capBusinessPartners; } }
CDS Query Notation (CQN) is the common language in CAP to run queries against services. It can be used to talk to the services defined by your model, but also remote services, such as the database.
The event handler uses the following APIs, which are available for service providers in CAP Java:
- Event handler classes have to implement the marker interface
EventHandler
and register themselves as Spring Beans (@Component
). The marker interface is important, because it enables the CAP Java runtime to identify these classes among all Spring Beans. - Event handler methods are registered with
@On
,@Before
, or@After
annotations. Every event, such as an entity creation, runs through these three phases. Each phase has a slightly different semantic. - The annotation
@ServiceName
specifies the default service name all event handler methods apply to. Here this iscloud.sdk.capng
, as this was also the name when defining the service in the CDS model.
- Create a new Java class
- Step 6
The above class handles the READ and CREATE events (highlighted above).
-
The READ operation just returns the business partners from the remote OData service.
Here you are using the OData VDM from SAP Cloud SDK to fetch business partners from the target system. You can call this service
getAllBusinessPartner()
function to retrieve a list of all the business partners from the system. In this tutorial the destination is calledMyErpSystem
and you will learn a little later where it is set up.Later you will transform
BusinessPartner
toCapBusinessPartner
. -
The CREATE event extracts the payload from the CQN representation and saves into
businessPartner
object.Here you initialize the
BusinessPartnerService
instance and then prepare the query and call theexecuteRequest
function which creates the newbusinessPartner
.
-
- Step 7
In order to make a call to an OData service, there needs to be a service to call. You can set up a local mock server that mimics the business partner and a custom service by following the instructions at Extending SAP S/4HANA. This mock server does not support all the features of the actual OData services, but it suffices to try it out locally.
Once it is up and running, you should see the list of services at http://localhost:3000/.
- Step 8
-
Go to the root of your project by running the following command in the terminal:
Shell/BashCopycd ~/projects/cap-business-service
-
Start the application:
Shell/BashCopymvn clean spring-boot:run
A notification message saying “A service is listening to port 8080” will appear in the bottom right.
-
Go to http://localhost:8080.
-
Choose
$metadata
from the welcome page to inspect the OData metadata that is automatically served by the CAP Java runtime.
-
- Step 9
Do the GET request on http://localhost:8080/odata/v4/cloud.sdk.capng/CapBusinessPartner from Postman. It fetches the
businessPartner
data from the mock server.Try to insert some data into the running application. For example, use Postman to do the following post request on same link.
The POST request causes an OData Insert on the entity
CAPBusinessPartner
.The response will be the created record and should look similar to this output:
JSONCopy{ "@context": "$metadata#CapBusinessPartner/$entity", "ID": "1003764", "firstName": "abc", "surname": "xyz", "sourceDestination": "MyErpSystem" }
You can read the data by doing the GET request on same URL .
- Step 10
You can configure a mock server instance to Cloud Foundry by going inside the mock server directory and pushing the instance to cloud. Do this by running:
Shell/BashCopycf push
Now configure the mock server destination in Cloud Foundry.
-
Navigate to the Cloud Foundry subaccount.
-
In the menu on the left, go to Connectivity > Destinations.
-
Click New Destination and enter the following values into the input fields:
- Name:
MyErpSystem
- URL: URL to your
mock server
- Authentication: choose
BasicAuthentication
- Provide credentials of your technical user in the User and Password fields.
- Leave the other fields unchanged.
- Name:
-
Click Save.
You can get mock server URL by running:
Shell/BashCopycf app odata-mock-server
You need to bind destination service to your application in order to use it.
Use the Cloud Foundry CLI to create the destination service instance:
Shell/BashCopycf create-service destination lite MyErpSystem
-
- Step 11
-
Go to the
~/projects/cap-business-service
folder and create a new file calledmanifest.yml
.Save the file.
-
Add the following code to the newly created file:
YAMLCopy--- applications: - name: cap-business-service path: srv/target/cds-services-archetype-exec.jar random-route: true services: - MyErpSystem
The manifest describes the name of the application and the path where the application archive can be found. Spring Boot applications can be deployed from a single JAR archive, which is what you are making use of here.
-
Open the
pom.xml
file in thesrv
directory. -
Add the following dependency under the
dependencies
tag:XMLCopy<dependency> <groupId>com.sap.cds</groupId> <artifactId>cds-feature-cloudfoundry</artifactId> </dependency> <dependency> <groupId>com.sap.cds</groupId> <artifactId>cds-feature-hana</artifactId> </dependency>
-
Add the following annotation to your
Application
class:JavaCopy@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
This will allow you to deploy to Cloud Foundry without any database service binding.
-
Build your application once by running:
Shell/BashCopymvn clean install
- Push the application to the cloud by running:
Shell/BashCopy
cf push
The manifest will be automatically picked up.
Provide the credentials you usually log in to SAP Cloud Platform if you are asked to log in.
You can see the following, if the application was successfully deployed.
-
To retrieve the application URL run the following command:
Shell/BashCopycf app cap-business-service
You can find URL, next to routes.
Now you can do the GET / POST request in the same way as described in step 9.
-
- Create SAP Cloud Application Programming Model project
- Define a data model
- Define a service
- Integrate SAP Cloud SDK
- Create Java class for event handler
- Understanding the read and write methods
- Run the mock server
- Run the application
- Create/read data through Postman
- Deploy and configure mock server on cloud foundry
- Deploy application to Cloud Foundry