Skip to Content
Technical Articles
Author's profile photo Yohei Fukuhara

How to call function modules using SAP Cloud SDK for Java

Hi All,

I am writing this blog to describe steps to build Java application calling function modules on SAP Cloud Platform CF with SAP Cloud SDK.

Function modules are on on-premise environment and called by JCo via SAP Cloud Connector.

There are so many useful information here.(2020/8/21 Added)


System architecture is as below image, which is on the SAP Help portal.

It takes time to test this for me, since I was unfamiliar with SAP Cloud Platform services like XSUAA and App Router.  To understand SAP Cloud Platform services, I posted an article about App Router, XSUAA and Java Application in Japanese.


I used both Windows and Ubuntu PC, just because my development environment is separated into Java and others.  It is not mandatory to use both windows and ubuntu.

Local PC(Java development on Windows)

  • OS: Windows10 64-bit
  • openJDK: 1.8.0_242
  • Chocolatey: 0.10.15
  • maven: 3.6.3
  • IDE: IntelliJ IDEA Community Edition 2019.3.5
  • CF cli: 6.51.0+2acd15650.2020-04-07
  • SAP Cloud SDK for Java: 3.19.1

Local PC(App router development on Ubuntu)

  • OS: Ubuntu18.04.01 LTS
  • nvm: 0.35.3
  • Node.js: 12.16.2
  • npm: 6.14.5
  • SAP Cloud SDK for JavaScript:1.19.0
  • SAP Cloud SDK cli: 0.1.8
  • CF cli: 6.51.0+2acd15650.2020-04-07

Cloud Foundry

  • Java Buildpack version: sap java build pack 1.25.0
  • CF (Europe – Frankfurt)

Netweaver ABAP

  • NetWeaver ABAP 7.53 SP0

Cloud Connector

  • SAP Cloud Connector 2.11.2

Seeing following stackoverflow question, invoking function modules/ BAPIs from localhost is not supported.

What you wanna do is technically not supported: You want to invoke a BAPI from your localhost via the transport protocol RFC using the JCo library (used behind the scenes via the SAP Cloud SDK). The usage of JCo requires to run your app on SAP Cloud Platform.

I’m not sure if invoking them is possible with Neo SDK.

when deploying locally you must add a dependency to Neo SDK (which also contains the JCO libraries).


1. Setup Cloud Connector

Access SAP Cloud Connector and setup connection from SAP Cloud Platform to ABAP Server.  The steps are same as the one of  blog post “Configure Cloud Connector for RFC connection from cloud to on-premise”.

2. Create Destination

Create Destination service by CF cli command “cf create-service”.  “lite” is service plan name.  The steps are same as the one of  blog post “Configure Cloud Connector for RFC connection from cloud to on-premise”.

3. Create Routes for Java and App Router

I did this step on Ubuntu PC.

Firstly create routes for Java application and App Router by cf cli create-route command.

Please replace from <space name> to your space name.  Name <host name of XXX> as you like.

cf create-route <space name> --hostname <host name of App Router>
cf create-route <space name> --hostname <host name of Java App>

4. Create Java Application

I did this step on Windows PC.

With maven, create a Java Application project.

mvn archetype:generate "" "-DarchetypeArtifactId=scp-cf-tomee" "-DarchetypeVersion=RELEASE"

I set following information during prompt.

  • groupId:
  • artifactId: test-rfc
  • version: 1.0-SNAPSHOT
  • package:

Change “manifest.yml” file.

  • Add the created route in step 3 to “routers” -> “route”
  • Change values of “random-route”
  • Add the created destination to “services”

- name: test-rfc
  memory: 1024M
  timeout: 300
    - route: https://<route host name>.<route domain name>
  random-route: false
  path: application/target/test-rfc-application.war
    - sap_java_buildpack
    TARGET_RUNTIME: tomee7
    JBP_CONFIG_SAPJVM_MEMORY_SIZES: 'metaspace:128m..'
#  - my-application-logs
  - <destination name>
#  - my-connectivity


Thought it is unusual, “Plugins Usage Analytics Maven Plugin” version 3.19.1 doesn’t exist on the maven repository.  So I changed the version on “<project root>/application/pom.xml”.  In addition, I changed skipUsageAnalytics value.

                <!-- changed from 3.19.1 to 3.18.0 -->
                            <!-- changed from false to true -->
                            Note: A random salt is auto-generated once the project is built for the first time.
                            Please keep the generated salt in the POM file, for example, when pushing to git.

                            To learn more, visit:

After project generation, build and deploy the Java application.

mvn clean package && cf push

Check if the deployment is successful using Curl.  Only this command run on Ubuntu PC.

$ curl
Hello World!

5. Create XSUAA service and App Router

I did this step on Ubuntu PC.

5.1. Create App Router Project

I created App Router using SAP Cloud SDK for Javascript cli. During prompt, input Java application name “test-rfc”.

It is not mandatory to use the cli.  App Router and relevant codes are very simple.

$ sap-cloud-sdk add-approuter
No 'manifest.yml' found.
Enter project name as maintained in Cloud Foundry: test-rfc
  ✔ Creating files
✅ Successfully added approuter to your project.

Generated files might need customization. Documentation available here:
- xs-security.json (for help check
- xs-app.json (for help check
- mainfest.yml (for help check

5.2. Change “xs-security.json”

Change “tenant-mode” value on “aprouter/xs-security.json” file.  I have never used “shared”.  Please refer to tutorial and help document for further detail.

  "xsappname": "test-rfc",
  "tenant-mode": "dedicated"

5.3. Create XSUAA service

Create XSUAA service using xs-security.json by cf cli command.

cf create-service xsuaa application <xsuaa name> -c xs-security.json


bind XSUAA service and the Java application.

cf bind-service test-rfc <xsuaa name>

5.4. Create App Router

Change manifest.yml file.

  - name: test-rfc-approuter
      - route: >-
          https://<App Router Route host name><App Router Route domain>
    path: .
    memory: 128M
      - nodejs_buildpack
#        "test-rfc-(.*)"
      destinations: >-
        [{"name":"test-rfc","url":"https://<Java Route host name>.<Java Route domain>","forwardAuthToken":true}]
      - <xsuaa name>

Deploy the App Router.

cf push

Now go to App router route url via browser and redirect to XSUAA service.  After authentication, “Hello World!” is displayed on browser.

7. Create Connectivity

I did this step on Ubuntu PC.

Create Connectivity service.  The Connectivity service is necessary to connect from cloud to on-premise environment according to Help document.

cf create-service connectivity lite <connectivity name>

8. Update Java Application

I did this step on Windows PC.

Change “<project root>/manifest.yml” to bind created services.  Make sure that “env” is also updated.


- name: test-rfc
  memory: 1024M
  timeout: 300
  random-route: false
    - route:
  path: application/target/test-rfc-application.war
    - sap_java_buildpack
    TARGET_RUNTIME: tomee7
    JBP_CONFIG_SAPJVM_MEMORY_SIZES: 'metaspace:128m..'
    xsuaa_connectivity_instance_name: "<xsuaa name>"
  - <destination name>
  - <xsuaa name>
  - <connectivity name>

Create “<project root>/application/src/main/java/com/sap/cloud/sdk/”.  Please replace from <destination name> to your destination name.  The servlet receive “name” url parameter, which is function module name.  If there is no “name” parameter, “RFC PING” is called.

I haven’t implemented security in this Java App, so the app can be called without App Router though it fails.  I posted about the security implementation in another article, though it is in Japanese.


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

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RfcServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private static final Logger logger = LoggerFactory.getLogger(RfcServlet.class);
    private static final Destination destinationRfc =
            DestinationAccessor.getDestination("<destination name>");

    protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
            throws IOException {"Start get method: " + request.getRequestURI());
        String parameter = request.getParameter("name");"Get parameter 'name': " + parameter);
        if (parameter == null) {
            parameter = "RFCPING";
        Iterable names = destinationRfc.getPropertyNames(); Gson().toJson(names));

        try {
            final RfmRequestResult rfmTest = new RfmRequest(parameter, false) //false is for non-commit
            response.getWriter().write(new Gson().toJson(rfmTest));
        } catch (RequestExecutionException e) {

Finally, build and deploy the Java application.

# from application directory
mvn clean package && cd .. && cf push



When I open the Java Application via App router, then result is like this.

https://<App Router route host name>.<App Router route domain>/rfc?name=RFC_TEST_EXTERNAL

There are many words “Error” on the screen. but actually it is not errors.  It just displays error mapping information.

If you access the app without App router, Internal Server Error occurs.

Assigned Tags

      1 Comment
      You must be Logged on to comment or reply to a post.
      Author's profile photo Tikeer Guo
      Tikeer Guo

      Dear Yohei Fukuhara,

      Thanks a lot for your effort and sharing, it is very helpful.

      Best regards,