SAP Home Learn Build Integrate Model Operate Extend with AI ConnectTutorial navigator Knowledge Graph API Devtoberfest Developer Advocates App Space

Manage my Account SAP Devs YouTube ↗ Learnings ↗ Community ↗ Provide Feedback ↗
Logout
⤢ Open full site

Extensibility and Type-Safe Expand with the Virtual Data Model for OData

Use the latest features of the SAP Cloud SDK regarding extensibility, eager and type-safe expand as well as dependency injection with the Virtual Data Model for OData for any SAP S/4HANA system.

Overview

🎓 intermediate 30 min. JavaIntermediateSAP Cloud Sdk

You will learn

  • How to use custom field extensions from S/4HANA in the virtual data model for OData
  • How to join connected entities from the virtual data model in eager fashion
  • How to leverage dependency injection to decouple your client code better from the SDK-provided classes
Charles Dubois C Charles Dubois November 15, 2024
Created by January 21, 2020
Contributors

Prerequisites

Prerequisites

Please note that the sandbox service does not support extending it by adding custom fields, you might have to use an actual S/4 system to try the tutorial out.

Steps

Intro

Use advanced features of the Virtual Data Model for OData.


Step 1 Get ready

To successfully go through this tutorial, you will use the following GetBusinessPartnerCommand for all three features to the business partner API. The call itself requests the first and last name from all business partners who are customers.

This file needs to be put under your <projectroot>/application/src/main/java/com/sap/cloud/sdk/tutorial directory.

Java
package com.sap.cloud.sdk.tutorial;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.List;

import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
import com.sap.cloud.sdk.cloudplatform.resilience.ResilienceConfiguration;
import com.sap.cloud.sdk.cloudplatform.resilience.ResilienceDecorator;
import com.sap.cloud.sdk.cloudplatform.resilience.ResilienceRuntimeException;
import com.sap.cloud.sdk.datamodel.odata.client.exception.ODataException;
import com.sap.cloud.sdk.tutorial.datamodel.odata.namespaces.businesspartner.BusinessPartner;
import com.sap.cloud.sdk.tutorial.datamodel.odata.namespaces.businesspartner.field.BusinessPartnerField;
import com.sap.cloud.sdk.tutorial.datamodel.odata.services.BusinessPartnerService;
import com.sap.cloud.sdk.tutorial.datamodel.odata.services.DefaultBusinessPartnerService;

import java.util.List;

public class GetBusinessPartnersCommand {

    private final BusinessPartnerService businessPartnerService;
    private final Destination destination;

    public GetBusinessPartnersCommand(Destination destination) {
        this(destination, new DefaultBusinessPartnerService());
    }

    public GetBusinessPartnersCommand(Destination destination, BusinessPartnerService businessPartnerService) {
        this.businessPartnerService = businessPartnerService;
        this.destination = destination;
    }

    public List<BusinessPartner> execute() {
        return ResilienceDecorator.executeSupplier(this::run, ResilienceConfiguration.of(GetBusinessPartnersCommand.class));
    }

    private List<BusinessPartner> run() {
        try {
            return businessPartnerService.getAllBusinessPartner()
                    .filter(BusinessPartner.CUSTOMER.ne(""))
                    .select(BusinessPartner.FIRST_NAME,
                            BusinessPartner.LAST_NAME)
                     .executeRequest(destination);

        } catch (final ODataException e) {
            throw new ResilienceRuntimeException(e);
        }
    }
}

You will be also using the following controller that consumes our GetBusinessPartnerCommand.

This file needs to be put under your &lt;projectroot&gt;/application/src/main/java/com/sap/cloud/sdk/tutorial/controllers directory:

Java
package com.sap.cloud.sdk.tutorial.controllers;

import com.google.gson.Gson;
import com.sap.cloud.sdk.tutorial.GetBusinessPartnersCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
import com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor;
import com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException;
import com.sap.cloud.sdk.datamodel.odata.client.exception.ODataException;

import com.sap.cloud.sdk.tutorial.datamodel.odata.namespaces.businesspartner.BusinessPartner;

@RestController
@RequestMapping( "/businesspartners" )
public class BusinessPartnerController
{
    private static final Logger logger = LoggerFactory.getLogger(BusinessPartnerController.class);
    private static final String DESTINATION_NAME = "MyErpSystem";

    @RequestMapping( method = RequestMethod.GET , produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<?> getBusinessPartner()
    {
        try {
            final Destination destination = DestinationAccessor.getDestination(DESTINATION_NAME);

            final List<BusinessPartner> businessPartners =
                    new GetBusinessPartnersCommand(destination).execute();
            return ResponseEntity.ok( new Gson().toJson(businessPartners));

        } catch (final DestinationAccessException e) {
            logger.error(e.getMessage(), e);
            return ResponseEntity.internalServerError().body("Failed to fetch destination.");
        } catch (final ODataException e) {
            logger.error(e.getMessage(), e);
            return ResponseEntity.internalServerError().body("Failed to fetch business partners.");
        } catch (final Exception e) {
            logger.error(e.getMessage(), e);
            return ResponseEntity.internalServerError().body("Unexpected error occurred while fetching business partners.");
        }
    }

}

When you call this servlet on the server, you can see a result like this:

Result
Result

If you have a similar result, you are ready to proceed with this tutorial.

Step 2 Custom field extensibility
+
Step 3 Type-safe and eager expand
+
Step 4 Test yourself
+

Resources

Discussion

Share feedback on this tutorial or join the conversation in SAP Community.

Submit detailed feedback Discuss in Community
Steps
Step 1 of 4
1. Get ready 2. Custom field extensibility 3. Type-safe and eager expand 4. Test yourself

Learn more →