Some suppliers may have special logic to enhance the outbound delivery number, customer material, header VAT amount and so on in the received transmsion from customer.This blog would introduce how to make use of the side-by-side extensibility offered by SAP Self-Billing Cockpit. SAP Self-Billing Cockpit allows you to implement your custom business logic by using RESTful APIs.You can create your RESTful APIs on BTP or SAP S/4HANA.
You can download the OpenJDK maintained by SAP: SapMachine
Execute mvn -v in system command line and you would see something like:
... Maven home: ~/apache-maven-3.8.4 Java version: 17.0.8, vendor: JetBrains s.r.o., runtime: ~/Library/Java/JavaVirtualMachines/jbr-17.0.8/Contents/Home Default locale: en_CN, platform encoding: UTF-8 OS name: "mac os x", version: "14.2.1", arch: "aarch64", family: "mac"
The maven archive path and determined JDK version should be listed there.
Execute command: mvn archetype:generate -DgroupId=org.example -DartifactId=selfbilling-extension -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false and then an empty project contains basic structure and dependencies should be created.
Create a file named settings.xml in project's root and add following content:
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <!-- Id: com.sap:artifactory:1.0.0:settings.xml --> <mirrors> <mirror> <id>mirror1</id> <url>https://common.repositories.cloud.sap/artifactory/build-milestones/</url> <mirrorOf>*,!artifactory</mirrorOf> </mirror> </mirrors> <profiles> <profile> <id>milestone.build</id> <pluginRepositories> <pluginRepository> <id>artifactory</id> <url>https://common.repositories.cloud.sap/artifactory/build-milestones/</url> </pluginRepository> </pluginRepositories> <repositories> <repository> <id>artifactory</id> <url>https://common.repositories.cloud.sap/artifactory/build-milestones/</url> </repository> </repositories> <properties> <tycho.disableP2Mirrors>true</tycho.disableP2Mirrors> <tycho.localArtifacts>ignore</tycho.localArtifacts> </properties> </profile> </profiles> <activeProfiles> <activeProfile>milestone.build</activeProfile> </activeProfiles> </settings>
This file overrides default maven repository settings and helps you download Self Billing Cockpit SDK.
Open your IDE and import the project. If project is configured correctly, IDE should completes project loading and resolving dependencies successfully.
Add following configuration to pom.xml:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.sap.cf.sales.self.billing.sdk</groupId> <artifactId>customer-extension-springboot</artifactId> <version>1.0.0-20230426024010</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <!-- put the full qualifier name of your starter class here, see 3.1 --> <mainClass>org.example.App</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
package org.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
Self Billing SDK allows you implement your business by implementing the extension interfaces. SDK can detect all the implementation of extension interfaces and expose RESTful API of them. Currently SDK provides following extension interfaces:
Extension Name Interface Class Exposed APISBINV Material Mapping | ISbinvMaterialMappingExtension | /api/material-mapping/sbinv |
SBINV Transmission Receiving | ISbinvTransmissionReceivingExtension | /api/transmission-receiving/sbinv |
SBWAP Material Mapping | ISbwapMaterialMappingExtension | /api/material-mapping/sbwap |
SBWAP Transmission Receiving | ISbwapTransmissionReceivingExtension | /api/transmission-receiving/sbwap |
Example implementation of SBWAP transmission receiving extension interface:
package org.example.extension; import com.sap.cf.sales.self.billing.sdk.customerextension.model.dto.SbwapTransmissionMessage; import com.sap.cf.sales.self.billing.sdk.customerextension.service.ISbwapTransmissionReceivingExtension; import org.springframework.stereotype.Service; // 1.annotate your class with @Service annotation @Service // 2.implement predefined extension interface public class SbwapTransmissionReceivingExtension implements ISbwapTransmissionReceivingExtension { @Override public SbwapTransmissionMessage process(SbwapTransmissionMessage msg) { // 3.do your business here... // clean illegal characters in transmission id msg.getTransmissions().forEach(trans -> trans.setTransmissionId( removeIllegalCharacters(trans.getTransmissionId()))); return msg; } private String removeIllegalCharacters(String s) { return s.replaceAll("[#%+.*?-]*", ""); } }
Run the starter class App.java in IDE and wait for the console printing Started App, then you could test exposed extension API.
Test API in console using curl:
curl --request POST \ --header "Content-Type: application/json" \ --data '{ "transmissions": [{ "transmissionId": "Transmission*912182", "senderId": "AMotor", "previousTransmissionId": null, "transmissionDate": null, "sdDocuments": [{ }] }] }' http://localhost:8080/api/transmission-receiving/sbwap
The post result should be:
{ "transmissions": [{ "transmissionId": "Transmission912182", "senderId": "AMotor", "previousTransmissionId": null, "transmissionDate": null, "sdDocuments": [{ ...... }] }] }
To deploy application to SAP BTP, you should have owned your Cloud Foundry space in BTP and login to the space.
Create a file named manifest.xml in root folder and add:
--- applications: - name: example_extension # put your application name here memory: 1024MB path: target/example-extension-1.0-SNAPSHOT.jar # update this field to refer to it, you could check the project root/target path to find the packaged artifact buildpacks: - https://github.com/cloudfoundry/java-buildpack.git timeout: 180 env: JBP_CONFIG_COMPONENTS: '{jres: ["JavaBuildpack::Jre::SapMachineJRE"]}' JBP_CONFIG_SAP_MACHINE_JRE: '{ jre: { version: 11.+ } }'
Replace placeholders and run command cf push to push application to BTP. You can check the deployment status in console:
... Instances starting... name: example-extension requested state: started routes: example-extension.cfapps.eu10.hana.ondemand.com last uploaded: Thu 29 Feb 11:32:41 CST 2024 stack: cflinuxfs4 buildpacks: name version detect output buildpack name https://github.com/cloudfoundry/java-buildpack.git 9e8f9be-https://github.com/cloudfoundry/java-buildpack.git#9e8f9be java java type: web sidecars: instances: 1/1 memory usage: 1024M start command: JAVA_OPTS="-agentpath:$PWD/.java-buildpack/sap_machine_jre/bin/jvmkill-1.17.0_RELEASE=printHeapHistogram=1 -Djava.io.tmpdir=$TMPDIR -XX:ActiveProcessorCount=$(nproc) -Djava.ext.dirs= -Djava.security.properties=$PWD/.java-buildpack/java_security/java.security $JAVA_OPTS" && CALCULATED_MEMORY=$($PWD/.java-buildpack/sap_machine_jre/bin/java-buildpack-memory-calculator-3.13.0_RELEASE -totMemory=$MEMORY_LIMIT -loadedClasses=19499 -poolType=metaspace -stackThreads=250 -vmOptions="$JAVA_OPTS") && echo JVM Memory Configuration: $CALCULATED_MEMORY && JAVA_OPTS="$JAVA_OPTS $CALCULATED_MEMORY" && MALLOC_ARENA_MAX=2 SERVER_PORT=$PORT eval exec $PWD/.java-buildpack/sap_machine_jre/bin/java $JAVA_OPTS -cp $PWD/.:$PWD/.java-buildpack/container_security_provider/container_security_provider-1.20.0_RELEASE.jar org.springframework.boot.loader.JarLauncher state since cpu memory disk details #0 running 2024-02-29T03:33:02Z 0.0% 0 of 0 0 of 0 ...
Test cloud service with curl:
curl --request POST \ --header "Content-Type: application/json" \ --data <payload> \ https://example-extension.cfapps.eu10.hana.ondemand.com/api/transmission-receiving/sbwap
The host could be found in deployment console output.
Form explanation:
SELFB_DEST_SBINV_MATERIAL_MAPPING | SBINV Material Mapping |
SBINV_TRANS_EXT | SBINV Transmission Receiving |
SELFB_DEST_SBWAP_MATERIAL_MAPPING | SBWAP Material Mapping |
SBWAP_TRANS_EXT | SBWAP Transmission Receiving |
The response status 405 doesn't matter here.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
22 | |
6 | |
6 | |
5 | |
5 | |
4 | |
3 | |
3 | |
3 | |
3 |