Product Information
SAP S/4HANA Cloud SDK: Version 1.10.0 is Available
The new version of the SAP S/4HANA Cloud SDK Java libraries is available since today. You can update your dependencies to version 1.10.0 and consume the new version from Maven Central.
In this blog post, we will walk you through the highlights of this release. For a complete overview, visit our release notes for the Java libraries. The release notes also include the change log of all our releases so far.
At the end of the article, you will find a set of instructions on how to update to the new version.
Please note: version 1.10.0 is planned to be the last version of the SAP S/4HANA Cloud SDK Java libraries that supports Java 7. Future releases will only support Java 8.
Java Libraries: Release Highlights
Release of Virtual Data Model (VDM) generator
This version releases the VDM generator for OData services for productive use. The VDM generator is thus no longer considered experimental.
The VDM generator gives you the option to quickly generate your own VDM for your custom OData services. As you may know from the corresponding blog post, the SAP S/4HANA Cloud SDK provides a Java virtual data model for OData services of SAP S/4HANA Cloud. The VDM allows to easily access SAP S/4HANA Cloud APIs in a fluent and type-safe manner. The VDM delivered with the SAP S/4HANA Cloud SDK gives easy, fluent, and type-safe access to the public API of SAP S/4HANA Cloud (and SAP S/4HANA) published in the SAP API Business Hub. With the VDM generator, you can leverage these benefits also for any other OData v2 service. These custom services can, for example, be based on custom business objects or custom CDS views, created with the in-app extensibility capabilities of an SAP S/4HANA Cloud system. See this blog post for a detailed walk-through of using the generator.
The productive release of the VDM generator requires only the metadata document for each OData services for which to generate a VDM. You can simply download the metadata document as an EDMX file from your OData service by appending /$metadata
to the URL. In contrast to the experimental release, Swagger files are now optional and can be used to describe the service further, but are not required. Store the EDMX files with file extension .edmx
in one folder that we will use as input for the generator.
Afterwards, to run the generator, follow these simple steps:
- Download the command line interface of the generator, rename it to
odata-generator-cli.jar
, and put it in a folder of your choice. Note: please check for the latest version of the generator on Maven Central. - Run
java -jar odata-generator-cli.jar -h
on the command line within that folder to see the available options of the command line interface. - Run the generator as follows:
java -jar odata-generator.jar -i /path/to/input/folder -o /path/to/output/folder
.
You can also specify the parameter-p my.package.name
to choose the package name. - Wait for the generator to finish with a success message. This will only take one or two seconds.
- Put the generated Java source files from the output folder into your project that is using the SAP S/4HANA Cloud SDK so that they are picked up by Java. For example, move them to the
application/src/main/java
folder. - Finally, you need to add Lombok to the dependencies of your project (and, if needed, to your IDE). Add the following to the
dependencies
section of yourapplication/pom.xml
file:<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency>
Now, you can use the generated classes in your Java code to access your custom OData service with the same simplicity, type-safety, and ease-of-use that you know from the VDM for the public API of SAP S/4HANA Cloud.
The above is just one possible option to use the generator. There is also a Maven plugin com.sap.cloud.s4hana.datamodel:odata-generator-maven-plugin
available to generate the VDM as part of the Maven lifecycle. Furthermore, you can call the generator from any Java application via the DataModelGenerator
builder class.
In comparison to the experimental release of the VDM generator, the productive release in this version 1.10.0 brings many improvements. The previously required Swagger JSON file that describes an OData service in more detail is now optional.
The generator will by default use the label from the OData metadata (sap:label
attribute) to derive the VDM name of entities and their properties for more speaking names. You can use the old strategy to use the name instead with the corresponding command line interface (CLI) option --use-odata-names
(if you are using the Maven plugin, add the following parameter to the plugin configuration: <nameSource>NAME</nameSource>
). This may be required, for example, when labels would lead to duplicate names.
You can finetune the names of generated Java classes and properties by supplying a custom NamingStrategy
to define the mapping of metadata names and labels to Java identifiers. Supply the fully qualified name of your class implementing this interface via the parameter --name-strategy-class
(CLI) or namingStrategy
(Maven plugin) and supply the class on the classpath when running the generator.
Improvements to Update Requests with the VDM
The VDM makes it easy to call any operation of an OData service. This version of the SAP S/4HANA Cloud SDK brings several improvements for update requests made with the VDM.
Update using PATCH
Requests
All update requests with the VDM are now made using the HTTP PATCH
request method. Patch requests in principle only require sending changed fields. In version 1.10.0, the VDM for this purpose sends all fields of the entity that are not null (i.e., have not been initialized). This strategy allows developers to control the fields that are being sent by constructing an entity that only contains those fields. We plan to improve the update handling in the future to make it easier to send update requests.
Optimistic Concurrency Control
The VDM now supports optimistic concurrency control for update requests. The OData v2 specification uses ETags for optimistic concurrency control. The VDM transparently retrieves the ETag
version identifier during read-by-key requests such as getting a physical inventory item and supplies it as If-Match
header during update requests such as update physical inventory item. The OData service will only execute the update request if the version identifier is still the same as given in the header.
You can force overwrites (if the OData service supports it) by telling the update request to ignore the version identifier. You can manually get and set the ETag
version identifier manually on all entities.
Further Improvements
Similarly to other Cloud Platform abstractions provided by the SAP S/4HANA Cloud SDK, we introduced an AuthTokenAcccessor
to transparently access the current authorization token on SAP Cloud Platform Cloud Foundry.
We fixed an issue where destinations on SAP Cloud Platform Cloud Foundry were not retrieved correctly in a multi-tenant setup.
Several further improvements are listed in the full release notes.
How to Update: Java Libraries
To update the version of the SAP S/4HANA Cloud SDK Java libraries used in an existing project, proceed as follows:
- Open the pom.xml file in the root folder of your project.
- Locate the dependency management section and therein the
sdk-bom
dependency. - Update the version of that dependency to
1.10.0
.
With this, you are already done thanks to the “bill of material” (BOM) approach. Your dependency should look like this:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.sap.cloud.s4hana</groupId>
<artifactId>sdk-bom</artifactId>
<version>1.10.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
<!-- possibly further managed dependencies ... -->
</dependencyManagement>
You can now recompile your project (be aware of the compatibility notes, though) and leverage the new features of the SAP S/4HANA Cloud SDK in version 1.10.0.
Of course, you can also generate a new project that uses version 1.10.0 from the start by running the Maven archetypes for Neo or Cloud Foundry with -DarchetypeVersion=1.10.0
(or RELEASE
).
Thanks Henning!
Could you help with the below issue, that I am facing while running the CLI. I use the Northwind metadata file save as Northwind.edmx for my test.
Please let me know your thoughts.
$ java -jar odata-generator-cli-2.1.1.jar -i input/ -o output/
[main] INFO com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DataModelGenerator - Generating EVERYTHING with parameters:
[main] INFO com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DataModelGenerator - input directory: /Users/asuvarna/Downloads/CLI/input
[main] INFO com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DataModelGenerator - output directory: /Users/asuvarna/Downloads/CLI/output
[main] INFO com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DataModelGenerator - delete output directory: false
[main] INFO com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DataModelGenerator - overwrite files: false
[main] INFO com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DataModelGenerator - package name: com.sap.cloud.sdk.s4hana.datamodel.odata
[main] INFO com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DataModelGenerator - default base path: null
[main] INFO com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DataModelGenerator - service name mapping file: /Users/asuvarna/Downloads/CLI/serviceNameMappings.properties
[main] INFO com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DataModelGenerator - naming strategy class: com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DefaultNamingStrategy
[main] INFO com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DataModelGenerator - name source (default strategy): LABEL
[main] INFO com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DataModelGenerator - annotation strategy class: com.sap.cloud.sdk.s4hana.datamodel.odata.generator.annotation.DefaultAnnotationStrategy
[main] INFO com.sap.cloud.sdk.s4hana.datamodel.odata.generator.ODataToVdmGenerator - Loading OData service Northwind
[main] INFO com.sap.cloud.sdk.s4hana.datamodel.odata.generator.ODataToVdmGenerator - Reading metadata file: /Users/asuvarna/Downloads/CLI/input/Northwind.edmx
[main] INFO com.sap.cloud.sdk.s4hana.datamodel.odata.generator.ODataToVdmGenerator - Reading swagger file: /Users/asuvarna/Downloads/CLI/input/Northwind.json
Warning: validation was turned on but an org.xml.sax.ErrorHandler was not set, which is probably not what is desired. Parser will use a default ErrorHandler to print the first 0 errors. Please call the setErrorHandler method to fix this.
Error: URI=file:/Users/asuvarna/Downloads/CLI/input/Northwind.edmx Line=2: Document root element "edmx:Edmx", must match DOCTYPE root "null".
Error: URI=file:/Users/asuvarna/Downloads/CLI/input/Northwind.edmx Line=2: Document is invalid: no grammar found.
Exception in thread "main" com.sap.cloud.sdk.s4hana.datamodel.odata.generator.ODataGeneratorReadException: TODO:
at com.sap.cloud.sdk.s4hana.datamodel.odata.generator.ServiceDetailsResolver.getMetadataServiceUrl(ServiceDetailsResolver.java:163)
at com.sap.cloud.sdk.s4hana.datamodel.odata.generator.ServiceDetailsResolver.readFromMetadataFile(ServiceDetailsResolver.java:119)
at com.sap.cloud.sdk.s4hana.datamodel.odata.generator.ServiceDetailsResolver.createServiceDetails(ServiceDetailsResolver.java:77)
at com.sap.cloud.sdk.s4hana.datamodel.odata.generator.ODataToVdmGenerator.buildService(ODataToVdmGenerator.java:153)
at com.sap.cloud.sdk.s4hana.datamodel.odata.generator.ODataToVdmGenerator.loadServicesFromInput(ODataToVdmGenerator.java:131)
at com.sap.cloud.sdk.s4hana.datamodel.odata.generator.ODataToVdmGenerator.generate(ODataToVdmGenerator.java:64)
at com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DataModelGenerator.execute(DataModelGenerator.java:531)
at com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DataModelGeneratorCli.handleOptions(DataModelGeneratorCli.java:173)
at com.sap.cloud.sdk.s4hana.datamodel.odata.generator.DataModelGeneratorCli.main(DataModelGeneratorCli.java:113)
Hello Ameya,
the error message is not as descriptive as it should be, but the fix is rather simple: the generator expects a default base path, which you can provide on the command line as follows (using the newest version, should be the same for version 2.1.1 as well):
You may have to run the generator once, open the newly created file serviceNameMappings.properties and remove the .svc part from each value (see below), and then run the command again.
Best regards,
Henning
Thank you Henning.
I was able to get through the VDM generation, but I was getting some other issues with Northwind.
I attempt to use ES5 sample Sflights OData service and wrote the following code for the same. I attempted to use the VDM as well as the non VDM approach for SFLIGHT
VDM approach:
final SapClient sapClient = new SapClient("002"); // adjust SAP client to your respective S/4HANA system
final SapClient sapClient = new SapClient("002"); // adjust SAP client to your respective S/4HANA system
try {
//.execute(new ErpConfigContext(ErpDestination.getDefaultName(), sapClient));
final List<FlightBooking> flightBookings = new DefaultFlightsService().getAllFlightBooking()
.top(100)
.execute(new ErpConfigContext(new ErpConfigContext("ES5QueryEndpoint").getDestinationName(), sapClient));
response.setContentType("application/json");
response.getWriter().write(new Gson().toJson(flightBookings));
} catch(final ODataException e) {
logger.error(e.getMessage(), e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write(e.getMessage());
}
Non VDM Approach:
final SapClient sapClient = new SapClient("002"); // adjust SAP client to your respective S/4HANA system
try {
//final ErpEndpoint endpoint = new ErpEndpoint(new ErpConfigContext(ErpDestination.getDefaultName(), sapClient));
final List<FlightBooking> flightBookings = ODataQueryBuilder
.withEntity("/sap/opu/odata/IWFND/RMTSAMPLEFLIGHT/", "FlightCollection")
.select("carrid", "connid", "fldate")
.top(100)
.build()
.execute(new ErpConfigContext(new ErpConfigContext("ES5QueryEndpoint").getDestinationName(), sapClient))
.asList(FlightBooking.class);
response.setContentType("application/json");
response.getWriter().write(new Gson().toJson(flightBookings));
} catch(final ODataException e) {
logger.error(e.getMessage(), e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write(e.getMessage());
}
In either case on executing the app in Cloud Foundry, I am getting the following error:
{ "written_at":"2018-09-11T02:28:59.185Z","written_ts":1013541154150550,"component_id":"4ccf03b0-bd2f-49ec-8f3d-f6dabfa9cac1","component_name":"cf_vmd_northwind","DCComponent":"","organization_name":"-","component_type":"application","space_name":"dev","component_instance":"0","organization_id":"-","correlation_id":"-","CSNComponent":"","space_id":"9e8aaf0c-b80f-436c-ba3b-46718a17809a","Application":"cf_vmd_northwind","container_id":"10.0.73.30","type":"log","logger":"com.sap.cloud.sdk.odatav2.connectivity.cache.metadata.GuavaMetadataCache","thread":"http-bio-0.0.0.0-8080-exec-6","level":"ERROR","categories":[],"msg":"Error occurred during populating metadata : org.apache.olingo.odata2.api.edm.EdmException: 'Airline Name' name pattern not valid." }
Please help in identifying where I am going wrong?
Regards,
Ameya
Hi Ameya,
thanks for your question! It seems that the metadata file received from Service on your
getAllFlightBooking()
call has an "invalid" property name.Which version of the S/4HANA Cloud SDK are you using? If you are using version 1.10.0, please update to the latest version (2.3.1 as of now), as this also updates the parsing logic used by the SDK. Maybe the problem is already fixed by that. Please consider the 2.0.0 migration guide as well as the general release notes containing compatibility issues between the versions.
If this does not fix your issue, please provide the metadata file and, if possible, also the actual endpoint and your code, so that we can reproduce and understand your issue.
Greetings
Chris
Hi Chris,
I am using 2.3.1. Basically used the latest archetype. I am trying to create a VDM based app for Sample Flights service from ES5.
https://sapes5.sapdevcenter.com/sap/opu/odata/IWFND/RMTSAMPLEFLIGHT/$metadata
Regards,
Ameya
Hi Ameya,
this seems to be an issue in the specified metadata file. Looking into the OData V2 spec for properties and more specifically for the domain of the name attribute it must not contain any spaces, which the property "Airline Name" actually does.
As this is a problem on the side of the provided service on ES5, you would need to contact them with your findings so that they can fix it.
In your first post you also mentioned issues with the Northwind. Would you mind elaborating on this issue?
Greetings
Chris
Thank you Chris!
I was successfully able to connect VDM to GWSAMPLE_BASIC service.
https://sapes5.sapdevcenter.com/sap/opu/odata/IWbep/GWSAMPLE_BASIC/$metadata
Regards,
Ameya
Is there an extra space in the section Afterwards, to run the generator, follow these simple steps? I think it should be
/path/to/input/folder
rather than/path/to/input /folder
. Someone might think it was 3 parameters rather than 2!Hello Mike,
thanks for noticing, I have fixed this. Indeed, as you pointed out, this needs to be a single item.
Best regards,
Henning