Enterprise Resource Planning Blogs by SAP
Get insights and updates about cloud ERP and RISE with SAP, SAP S/4HANA and SAP S/4HANA Cloud, and more enterprise management capabilities with SAP blog posts.
cancel
Showing results for 
Search instead for 
Did you mean: 
Clark_Huang
Advisor
Advisor

Background


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 CockpitSAP 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.

Extensiblity Archtecture DiagramExtensiblity Archtecture Diagram

Solution

1.Setup Development Environment

  1. 1.Install JDK

You can download the OpenJDK maintained by SAP: SapMachine

  • Requires version >= 11
  1. 2.Install Maven
  1. 3.Test

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.

2.Setup Project

  • Generate empty maven project

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.

  • Configure maven repository

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.

  • Import project to your IDE

Open your IDE and import the project. If project is configured correctly, IDE should completes project loading and resolving dependencies successfully.

  • Add maven dependencies

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>

3.Implement Business

  • Add Spring Boot main class in src folder
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);
  }
}
  • Implement extensions

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 API
SBINV Material MappingISbinvMaterialMappingExtension/api/material-mapping/sbinv
SBINV Transmission ReceivingISbinvTransmissionReceivingExtension/api/transmission-receiving/sbinv
SBWAP Material MappingISbwapMaterialMappingExtension/api/material-mapping/sbwap
SBWAP Transmission ReceivingISbwapTransmissionReceivingExtension/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("[#%+.*?-]*", "");  
  }
}
  • Test

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": [{
      ......
    }]
  }]
}

4. Deploy to BTP

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.

5. Integrate to Self Billing Cockpit

  • Goto SAP BTP Cockpit and open your subaccount
  • Click on Connectivity -> Destinations button to configure destinations
  • Click on Create Destination

BTP Subaccount DestinationBTP Subaccount Destination

Form explanation:

  • Name: you could find the name meanings here:
Destination Name Extension Name
SELFB_DEST_SBINV_MATERIAL_MAPPINGSBINV Material Mapping
SBINV_TRANS_EXTSBINV Transmission Receiving
SELFB_DEST_SBWAP_MATERIAL_MAPPINGSBWAP Material Mapping
SBWAP_TRANS_EXTSBWAP Transmission Receiving
  • URL: it is the RESTful API exposed by your extension application in BTP.
  • Proxy Type: Internet is mandatory here.
  • Authentication: If you have access control in your application, please fill Authentication field with your authentication parameters.

 

  • Click on Save button and click on Check Connection on the bottom of the page. If connection is valid, you could see: Connection to "SBWAP_TRANS_EXT" established. Response returned: "405: Method Not Allowed".

The response status 405 doesn't matter here.

  • Now you could run Self Billing process to test your extensions now.

 

Blog Post Series for SAP Self-Billing Cockpit