Skip to Content
Technical Articles

Consuming OData v4 Services using SAP Cloud SDK

Recently we announced the OData v4 support in SAP Cloud SDK. In this blog post, I want to walk you through the SAP Cloud SDK capabilities for consuming OData v4 services. First, we’ll have a look at how to get started with the SDK. Then we will dive into the OData v4 topics and in the last part, I’ll give you the links to some valuable documents and the available channels for reaching out to the SAP Cloud SDK team.

Version 4 of the OData protocol brings a lot of improvements and new capabilities and is already supported by several APIs. The SAP Cloud SDK team worked hard to provide stable support for consuming OData v4 and leveraging some new features.

The SAP Cloud SDK makes it very easy for application developers to communicate with OData endpoints by providing the tools needed to generate tailored client libraries for use in Java and JavaScript (TypeScript) apps. The advantage of using such a client library is that it comes with packaged classes representing the operations and related entities of the given OData endpoint. These classes enable type-safe access for Java and TypeScript while the SAP Cloud SDK takes care of the technical details and the communication channel between your app and the OData endpoint, such as authentication, destination handling, resilience, etc.

Generating the Client

The first thing you need to do in order to communicate with an OData service is to generate the client library for the endpoint. APIs shouldn’t change very often so starting up with a manual generation step using the SAP Cloud SDK command-line interface (option 1) is perfectly fine.

Later, when moving towards production and everything should be automated, you can configure the generation step as part of your automated build process by either using the Maven plugin (option 2) or invoking the SAP Cloud SDK programmatically (option 3).

Every OData endpoint has an API description (.edmx file) that should be used as the input for the generator. For most SAP products, the API descriptions are also available on the SAP API Business Hub.

All three options produce the same output so it doesn’t matter which one you’ll pick.

Option 1: The Command-line Interface

A very fast and easy way to try the generator is the command-line interface (CLI). You can download the latest version of the generator from Maven Central and test it directly.

java -jar odata-v4-generator-cli.jar -i /path/to/input/folder -o /path/to/output/folder

 

Option 2: Maven Plugin

In an automated setup, it might be helpful to configure the OData client generation as part of the build process. In this case, you can configure the Maven plugin to generate the classes and copy them to the right location before packaging the project.

<plugin>
    <groupId>com.sap.cloud.sdk.datamodel</groupId>
    <artifactId>odata-v4-generator-maven-plugin</artifactId>
    <!-- Please use the latest version here-->
    <version>${sap-cloud-sdk-version}</version>
    <executions>
        <execution>
            <id>generate-consumption</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputDirectory>${project.basedir}/edmx</inputDirectory>
                <outputDirectory>${project.build.directory}/vdm</outputDirectory>
                <deleteOutputDirectory>true</deleteOutputDirectory>
                <packageName>com.mycompany.vdm</packageName>
                <defaultBasePath>odata/v4/</defaultBasePath>
            </configuration>
        </execution>
    </executions>
</plugin>

It is important to consider that the generation output directory configured as ${project.build.directory}/vdm in the above example, needs to be configured as a Maven source directory. Otherwise, Maven won’t be able to find the classes during compilation.

Option 3: Invoking the Generator from Java

We packaged the OData client generator as a standalone module so that it can be included as pom.xml dependency.

<dependency>
    <groupId>com.sap.cloud.sdk.datamodel</groupId>
    <artifactId>odata-v4-generator</artifactId>
</dependency>

Now it is very easy to use the generator in your Java code.

final Path inputDirectory = Paths.get("application/src/main/resources/");
final Path outputDirectory = Paths.get("application/src/main/java/");
final Path serviceNameMapping = inputDirectory.resolve("serviceNameMappings.properties");

new DataModelGenerator()
    .withInputDirectory(inputDirectory.toFile())
    .withOutputDirectory(outputDirectory.toFile())
    .withServiceNameMapping(serviceNameMapping.toFile())
    .pojosOnly(false)
    .withNameSource(DefaultNamingStrategy.NameSource.NAME)
    .withPackageName("org.example")
    .withDefaultBasePath("/my/path/")
    .execute();

 

Add the generated Client to your Project

Once the client generation is completed, the new client can be used to access the OData endpoint.

Put the generated Java source files from the output folder into your project that is using the SAP Cloud SDK so that they are picked up by Java. For example, move them to the application/src/main/java folder.

Include the following dependencies in your application/pom.xml file as the generated code relies on this functionality.

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.apache.olingo</groupId>
    <artifactId>odata-commons-api</artifactId>
    <version>4.7.1</version>
</dependency>

The generated classes can now be used to build OData requests.

Enabling Autocompletion in your IDE

To gain the full comfort of working with the generated OData client library, you can configure the generation output directory as a sources directory in your IDE so that you get autocompletion enabled.

If you haven’t used the Lombok library, it might be helpful to install their annotation support in your IDE in order to avoid compilation problems.

Now you are ready to go.

Building up Requests

It is recommended to use the SAP Cloud SDK for the technical details of your service consumption and the generated client library for the type-safe access to the business functionality of the OData endpoint.

private static final HttpDestination destination = DefaultHttpDestination.builder("https://my.service.url").build();
private static final MyService service = new DefaultMyService().withServicePath("/my/base/path");

@Test
public void testGetAll() {
    service.getAllItem()
            .select(Item.ID,
                    Item.DESCRIPTION,
                    Item.TO_SUB_ITEMS
                            .select(SubItem.DESCRIPTION))
            .filter(Item.ID.lessThan(10), Item.DESCRIPTION.length().greaterThan(20))
            .top(5)
            .skip(5)
            .execute(destination);
}

In this example, the classes MyService, Item, and SubItem are parts of the generated OData client library. The service class is already wired with the SAP Cloud SDK connectivity implementation so you don’t need to do anything more than to specify the destination and to build the business logic.

New Features with OData v4

The full list of protocol improvements that come with OData v4 is listed here. The SAP Cloud SDK incrementally adds support for the most used features in the SAP ecosystem. Here are examples of the first two supported capabilities.

Using complex filtering capabilities with type-specific functions

The below example shows how the function length() (specific for the type String) is applied to the field DESCRIPTION. Check out the autocompletion suggestions in your IDE to see what functions are available for the different field types.

HttpDestination destination = DefaultHttpDestination.builder("https://my.service.url").build();
MyService service = new DefaultMyService().withServicePath("/my/base/path");

service.getAllItem()
    .select(Item.ID,
        Item.DESCRIPTION,
        Item.TO_SUB_ITEMS
            .select(SubItem.DESCRIPTION))
    .filter(Item.DESCRIPTION.length().greaterThan(20))
    .top(5)
    .skip(5)
    .execute(destination);

 

Selectively expand nested entity collections

The below example shows how to get all users and only expand their trips which start in 2020.

new DefaultPersonService().getPersons().select(
    Person.FIRST_NAME,
    Person.LAST_NAME,
    Person.TRIPS.select(Trip.NAME).filter(Trip.STARTS_AT.dateYear().equalTo(2020)))
  .execute(destination)

 

More examples will be provided as new capabilities are added to SAP Cloud SDK.

Bringing it all together

At this point, I’ve demonstrated how to generate an OData client library, include it into your project, construct queries, and use some new OData v4 features. As the SAP Cloud SDK adds support for additional protocol features, we’ll provide more details on how to use them in additional blog posts.

Now that you are able to consume an OData service, try out the additional sweets the SAP Cloud SDK offers for your cloud-native project.

Do you want to learn more or have a specific question? The SAP Cloud SDK team is happy to help on cloudsdk@sap.com.

Be the first to leave a comment
You must be Logged on to comment or reply to a post.