Skip to Content
Technical Articles

Deep Dive 15 – Production-ready integration of SAP Leonardo Machine Learning Foundation services with an SAP S/4HANA side-by-side extension built with the SAP Cloud SDK

The following steps will explain how to integrate SAP Leonardo Machine Learning Foundation functional services with an SAP Cloud Platform side-by-side extension using the SAP Cloud SDK.

Updated May 2019: SAP S/4HANA Cloud SDK transformed to become the SAP Cloud SDK: All references have been updated.

Updated Oct 2018: Using SAP Leonardo Machine Learning Foundation became even more simple! Newly added LeonardoMlFoundation class is the key. See below!

Note: This post is part of a series. For a complete overview visit the SAP Cloud SDK Overview. Furthermore, an extended version of this blogpost is part of the book Extending SAP S/4HANA.

Goal of this Blog Post

This blog post covers the following steps:

  1. Introduce SAP Machine Learning Foundation services.
  2. Differentiate between the sandbox services offered for prototyping on API Hub (see Quickly build a prototype with SAP Leonardo Machine Learning Foundation, SAP API Business Hub, and SAP Cloud SDK ) from the integration using Cloud Foundry service binding used in this article.
  3. Build a microservice wrapping the translation service from SAP Leonardo Machine Learning Foundation on SAP Cloud Platform Cloud Foundry.

SAP Machine Learning Foundation services

Machine learning is currently on everybody’s mind, figuring as a driver for efficiency improvements and an enabler of wholly new solutions. Certainly the quality of machine learning services has increased tremendously in the past 10 years. Advances in hardware and data management have led to multiple breakthroughs, fueling a virtuous circle of software improvements and, in turn, further development of hardware and data management. All this was carried by ever increasing interest by the business community. Today we have reached a quality level that make machine learning applications usable for automation purposes: When you reach 75% accuracy on image classification this is a nice trick and good research result, but you still need humans to check the result of the computer and correct every fourth result. When you reach 97% you go beyond human capabilities and can actually automate, and only have an exception in every 30th result. You still need exception handling, but mind the complexity of the task and that humans are even more error-prone doing it.

This quality improvement applies particularly to lots of so called one-second-tasks, like reading text, classifying pictures, seeing similarity, translation and so forth. Some of these tasks are sufficiently generic that they can be offered as ready-to-use services, with improvements being taken care of by the supplier – in this case SAP Leonardo Machine Learning functional services on the SAP Cloud Platform leveraging SAP Leonardo Machine Learning Foundation. In this blog post the translation service will be used to translate ‘hello’ to ‘hallo’ – not a huge challenge for the service, feel free to stress it or try other services!

Outline of this post

The post will help you to set up the technical integration with between a S/4HANA side-by-side extension on the SAP Cloud Platform and a SAP Leonardo Machine Learning Foundation service. The first step will be creating a skeleton side-by-side extension project and deploying it on the SAP Cloud Platform to test the viability of your development environment and create the application’s environment on the SAP Cloud Platform to which machine learning services can be bound. Then a SAP Leonardo Machine Learning Foundation service instance will be created and bound to the application. Then finally the access to the machine learning service will be added to the Java code of the side-by-side extension.

Creating the side-by-side extension

The starting point is the generation of the hello-world application skeleton with maven (see Step 3 https://blogs.sap.com/2017/05/19/step-3-with-sap-s4hana-cloud-sdk-helloworld-on-scp-cloudfoundry/ for a detailed introduction):

mvn archetype:generate -DarchetypeGroupId=com.sap.cloud.s4hana.archetypes \
  -DarchetypeArtifactId=scp-cf-tomee -DarchetypeVersion=LATEST

The project is directly runnable after its creation: A hello world servlet is provided for quick and easy testing. This is what we will leverage now to quickly continue setting up and testing our environment. Compile and run the code for a quick initial test (in application subdirectory):

mvn package

mvn tomee:run  # or: mvn tomee:debug

The service should be accessible at http://localhost:8080/hello . Continue to deploy it to SAP Cloud Platform (in main directory, where manifest.yml is located):

cf push

The application host name will be provided by the output on the command line (mine was named: mlf-cf-blog-tomee-innovative-wonder.cfapps.sap.hana.ondemand.com, making it accessible at http://mlf-cf-blog-blog-tomee-innovative-corpulence.cfapps.sap.hana.ondemand.com/hello ).

Bind the required machine learning services

On SAP Cloud Platform you have a wide variety of services you can choose to use in your applications. There are various versions of the SAP Leonardo Machine Learning Foundation service:

  • ML Foundation
  • ML Foundation Beta
  • ML Foundation Trial Beta

These are Cloud Foundry service constructs that in the case of SAP Leonardo Machine Learning Foundation bundle a couple of machine learning services in one Cloud Foundry service construct. You can use either of them and the beta service will have more machine learning services to choose from. The trial service is a service available on the trial edition account of SAP Cloud Platform Cloud Foundry. Be aware that the beta (some are even ‘alpha’) services are not production ready and subject to changes to their API without warning and may even disappear before graduating to the production-ready non-beta service construct.

To make the machine learning services available to your application we will bind the Cloud Foundry service construct to your application. To do this go to the overview screen for your application deployed with cf push above and open the ‘Service Bindings’ screen with the menu on the left. There hit ‘Bind Service’ to bind a new instance. Here the view on a trial account after searching for ‘ml’ (2018-07-18):

Select the ML Foundation service type you want to use – here on the trial there is only ‘ml-foundation-trial-beta’ available. Then hit ‘Next’, use the standard plan, ignore the parameters screen, and choose a name on the next screen. You’re pretty free to choose any name you want. Instances will be listed with their type and name on Cloud Foundry output.

Now we can move on to integrating the service into the SAP S/4HANA side-by-side extension using SAP Cloud SDK you created!

Integrate the service into a SAP Cloud SDK side-by-side extension

Open the project skeleton generated before with your favorite IDE, and browse to the HelloWorldServlet. You can generate project files with maven, too:

# in main directory:
mvn install # required to make eclipse:eclipse or idea:idea work

mvn eclipse:eclipse

mvn idea:idea

Then copy the HelloWorldServlet to create a new servlet named TranslationServlet, for example. Also change the url path prefix from '/hello' to, for example, '/translate'.

In that new servlet you can now add access to a SAP Leonardo Machine Learning Service. The SAP Cloud SDK provides a helper that handles authentication and service information extraction from the environment, called LeonardoMlFoundation, creating service classes of type LeonardoMlServiceIt is available in an additional dependency that you have to add to the application/pom.xml :

...
        <dependency>
            <groupId>com.sap.cloud.s4hana</groupId>
            <artifactId>s4hana-all</artifactId>
        </dependency>

        <!-- Dependency added for SAP Leonardo Machine Learning Foundation service access facilitation -->
        <dependency>
            <groupId>com.sap.cloud.s4hana.services</groupId>
            <artifactId>scp-machine-learning</artifactId>
        </dependency>
...

Here is an instantiation for the translation service available on the beta edition of the SAP Leonardo Services:

LeonardoMlService mlService =
  LeonardoMlFoundation.create(
    CloudFoundryLeonardoMlServiceType.TRIAL_BETA,
    LeonardoMlServiceType.TRANSLATION);

The service (stub) creation is parameterized to indicate the requirement for a specific type of the SAP Leonardo Machine Learning Foundation service. First you have to select which of the different editions you are targeting, then which particular service you want to access. Available editions are:

  • TRIAL_BETA  standard services and beta services available on SAP Cloud Platform trial accounts
  • BETA  standard and beta services available on SAP Cloud Platform subscriber accounts
  • STANDARD  standard services available on SAP Cloud Platform subscriber accounts
  • TRIAL standard services available on SAP Cloud Platform trial accounts (as of 2018-10-27 edition is no longer available on trial account)

The different services are listed on the SAP API Business Hub: SAP Leonardo Machine Learning functional services. Here we use the translation service.

Besides, on the SAP API Business Hub you have the option of exploring the services in a sandbox setup – this is a quite different setup and requires different access authentication. Please don’t confuse SAP Cloud Platform Cloud Foundry service access and the SAP API Business Hub sandbox. One is the full-blown enterprise Cloud Platform, the other just an as-simple-as-possible deployment of the services.

If you later want to access a different service using the ScpCfService class, you have to edit the last parameter to access a different service:

LeonardoMlService mlService =
  LeonardoMlFoundation.create(
    CloudFoundryLeonardoMlServiceType.TRIAL_BETA,
    LeonardoMlServiceType.TRANSLATION);
// alternative 
LeonardoMlService mlService =
  LeonardoMlFoundation.create(
    CloudFoundryLeonardoMlServiceType.TRIAL_BETA,
    LeonardoMlServiceType.IMAGE_OCR);

Be aware that some of these services are made available as beta services and might be changed or disappear without notice. All services you find in the non-beta version of the SAP Leonardo Machine Learning Foundation service construct are released and their API will not be subject to this limitation.

Back to the tutorial: In this tutorial we are going to use the translation service. It is a service specialized in business-context translations provided by SAP. This service requires the requestor to abide to a specific API with defined messages for requesting a translation and the response message also conforms to the API. This machine translation service API definition on SAP API Business Hub is available for your reference. Here you see the construction of the translation-request JSON message, ready to be serialized with Google Gson:

// construct { units: [ input ], 
//             sourceLanguage: "en", targetLanguages: [ "de" ] }
List<Object> units = new ArrayList<>();
units.add(Collections.singletonMap("value", input));

Map<String, Object> entity = new HashMap<>();
entity.put("units", units);
entity.put("sourceLanguage", "en");
entity.put("targetLanguages", 
  Collections.singletonList("de"));

In the following we will call the service via service (stub) instance created by the SAP Cloud SDK. This shows the structure of how to use the service instance:

private void leonardoMlRequest() {
    LeonardoMlService mlService =
            LeonardoMlFoundation.create(...);

    HttpPost postRequest = new HttpPost();

    // construct message - depends on service
    Object entity = ...

    postRequest.setEntity(new StringEntity(new Gson().toJson(entity), ContentType....));

    postRequest.setHeader("Accept", ContentType....); // probably json, but might vary depending on service

    Object result = mlService.invoke(postRequest, new Function<HttpResponse, String>()
    {
        @Override
        public String apply( HttpResponse httpResponse )
        {
            try {
                // retrieve entity content (here shown for json, but might be different depending on service)
                final String responseBody = HttpEntityUtil.getResponseBody(httpResponse);
                logger.debug(responseBody);
                ... extract result ...
                return result;
            } catch (Exception e) {
                throw new RuntimeException("Failed to retrieve response: " + e.getMessage(), e);
            }
        }
    });
    
    ... use result ...
}

Here you can see that you can concentrate on executing the main request. You don’t have to handle the OAuth authentication required when accessing Cloud Foundry services – LeonardoMlService does that for you.

After receiving the response and passing the error check, we have to parse the response according to the format documented in machine translation service API definition on SAP API Business Hub. You can see a proposed way of parsing it using Google Gson on the bottom of this article in the listing of the servlet class.

Now you can compile and run the code for a quick initial test (in application subdirectory):

mvn package

export ALLOW_MOCKED_AUTH_HEADER=true # or windows: set ALLOW_MOCKED_AUTH_HEADER=true

# VCAP_SERVICES needs mocking too if you test locally.
# Get the values for <ENTER VALUE> from the SAP Cloud Platform Cockpit in the application screen under environment variables:
export VCAP_SERVICES='{ "ml-foundation-trial-beta": [{"name": "mlf-trial-beta","instance_name": "mlf-trial-beta","binding_name": null, "credentials": {"clientid": "<ENTER VALUE>", "clientsecret": "<ENTER VALUE>", "serviceurls": { "TRANSLATION_URL": "https://mlftrial-machine-translation.cfapps.eu10.hana.ondemand.com/api/v2/text/translation", "TEXT_CLASSIFIER_URL": "https://mlftrial-text-classifier.cfapps.eu10.hana.ondemand.com/api/v2/text/classification", },     "url": "<ENTER VALUE>" }, } ] }'
# or without leading quotes on windows: set VCAP_SERVICES={ "ml-foundation-trial-beta": [{"name": "mlf-trial-beta","instance_name": "mlf-trial-beta","binding_name": null, "credentials": {"clientid": "<ENTER VALUE>", "clientsecret": "<ENTER VALUE>", "serviceurls": { "TRANSLATION_URL": "https://mlftrial-machine-translation.cfapps.eu10.hana.ondemand.com/api/v2/text/translation", "TEXT_CLASSIFIER_URL": "https://mlftrial-text-classifier.cfapps.eu10.hana.ondemand.com/api/v2/text/classification", },     "url": "<ENTER VALUE>" }, } ] }

mvn tomee:run  # or: mvn tomee:debug

The service should be accessible at http://localhost:8080/tranlsate?input=hello . You can even deploy it to SAP Cloud Platform (in main directory, where manifest.yml is located):

cf push

Be aware that also here, if you don’t set up the security environment required for production that provides tenant information (see Secure your application on SAP Cloud Platform Cloud Foundry ) you will see Error: Failed to determine cache key. and you need to mock auth headers to make your application run:

# call 'cf apps' to get a listing of your apps with their names
cf set-env <enter your app name> ALLOW_MOCKED_AUTH_HEADER true

The application host name will be provided by the output on the command line (mine was named mlf-cf-blog-tomee-innovative-wonder.cfapps.sap.hana.ondemand.com, making it accessible at http://mlf-cf-blog-tomee-innovative-wonder.cfapps.sap.hana.ondemand.com/translate?input=hello ).

The resulting microservice is most simple but hopefully very transparent and instructive. Here is a test from a browser:

This blog post has given you an introduction to starting your own machine learning integration project with SAP Cloud Platform, and the environment facilitates connecting with SAP S/4HANA easily – see SAP Cloud SDK tutorial step 4 to see how easy. Go make your SAP S/4HANA extensions intelligent!

PS: I hope you tried ‘Hello World’ already.

Appendix: The TranslateServlet source code.


import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.sap.cloud.sdk.cloudplatform.connectivity.HttpEntityUtil;
import com.sap.cloud.sdk.cloudplatform.logging.CloudLoggerFactory;
import com.sap.cloud.sdk.services.scp.machinelearning.CloudFoundryLeonardoMlServiceType;
import com.sap.cloud.sdk.services.scp.machinelearning.LeonardoMlFoundation;
import com.sap.cloud.sdk.services.scp.machinelearning.LeonardoMlService;
import com.sap.cloud.sdk.services.scp.machinelearning.LeonardoMlServiceType;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.slf4j.Logger;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.function.Function;

@WebServlet("/translate")
public class TranslateServlet extends HttpServlet
{
    private static final long serialVersionUID = 1L;
    private static final Logger logger = CloudLoggerFactory.getLogger(TranslateServlet.class);

    @Override
    protected void doGet( final HttpServletRequest request, final HttpServletResponse response )
            throws IOException
    {
        logger.info("I am running!");
        String input = request.getParameter("input");
        if (Strings.isNullOrEmpty(input)) {
            response.setStatus(HttpStatus.SC_BAD_REQUEST);
        } else {

            try {
                LeonardoMlService mlService =
                        LeonardoMlFoundation.create(
                                CloudFoundryLeonardoMlServiceType.TRIAL_BETA,
                                LeonardoMlServiceType.TRANSLATION);

                HttpPost postRequest = new HttpPost();

                // construct { units: [ input ], sourceLanguage: "en", targetLanguages: [ "de" ] }
                List<Object> units = new ArrayList<>();
                units.add(Collections.singletonMap("value", input));

                Map<String, Object> entity = new HashMap<>();
                entity.put("units", units);
                entity.put("sourceLanguage", "en");
                entity.put("targetLanguages", Collections.singletonList("de"));

                postRequest.setEntity(new StringEntity(new Gson().toJson(entity), ContentType.APPLICATION_JSON));

                postRequest.setHeader("Accept", ContentType.APPLICATION_JSON.getMimeType());

                String translationValue = mlService.invoke(postRequest, new Function<HttpResponse, String>()
                {
                    @Override
                    public String apply( HttpResponse httpResponse )
                    {
                        try {
                            // retrieve entity content (requested json with Accept header, so should be text)
                            final String responseBody = HttpEntityUtil.getResponseBody(httpResponse);
                            logger.debug(responseBody);

                            final Map<String, Object> responseObject = new Gson().fromJson(responseBody, Map.class);
                            final List<Object> respUnits = (List<Object>) responseObject.get("units");
                            final Map<String, Object> respUnit = (Map<String, Object>) respUnits.get(0);
                            final List<Map<String, Object>> translations =
                                    (List<Map<String, Object>>) respUnit.get("translations");
                            final Map<String, Object> translation = translations.get(0);
                            return (String) translation.get("value");
                        } catch (Exception e) {
                            throw new RuntimeException("Failed to retrieve response: " + e.getMessage(), e);
                        }
                    }
                });

                response.getWriter().println(translationValue);

            } catch (Exception e) {
                logger.error("Failure: " + e.getMessage(), e);

                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                response.getWriter().println("Error: " + e.getMessage());
            }
        }
    }
}
10 Comments
You must be Logged on to comment or reply to a post.
  • I try to combine your example with my Cloud Application Programming Model Project as separate function. I’m always getting ResourceExhausted on the invoke function, more details here: https://answers.sap.com/questions/786294/machine-learning-api-in-cloud-application-programm.html

    Kr, Wouter

    • Hi Wouter,

      thank you for trying this! I am sorry but I can only endorse Mitja and his assessment that the Metaspace seems to be exhausted. I have to take some time to quickly run through this blog again to see if something changed since the last time. I’ll let you know the result.

      Best,
      Georg

    • Hi Wouter,

      I tried running the blog as described here and it still works. I also tried changing the metaspace parameter in the manifest.yml file to 256mb and a ‘cf push’ changed that on the platform, too.

      Continuing discussion on the answers platform.

      Best,
      Georg

  • Hi,

    I have tried consuming ML services in cloud SDk in WebIDE but my build is failing with the error: The “Task for mta build” process finished with code 1. Can you please help me out with the same?

    Regards,
    Aparna

      • Created app with guid 86ccbfb7-07f4-4e5d-96dc-b86079f19258
        Updated app with guid 86ccbfb7-07f4-4e5d-96dc-b86079f19258 ({"route"=>"3fb99dab-d1f6-4c4e-8c75-41eb246771d4", :verb=>"add", :relation=>"routes", :related_guid=>"3fb99dab-d1f6-4c4e-8c75-41eb246771d4"})
        Uploading bits for app with guid 86ccbfb7-07f4-4e5d-96dc-b86079f19258
        Updated app with guid 86ccbfb7-07f4-4e5d-96dc-b86079f19258 ({"state"=>"STOPPED"})
        Updated app with guid 86ccbfb7-07f4-4e5d-96dc-b86079f19258 ({"environment_json"=>"[PRIVATE DATA HIDDEN]"})
        Updated app with guid 86ccbfb7-07f4-4e5d-96dc-b86079f19258 ({"environment_json"=>"[PRIVATE DATA HIDDEN]"})
        Updated app with guid 86ccbfb7-07f4-4e5d-96dc-b86079f19258 ({"environment_json"=>"[PRIVATE DATA HIDDEN]"})
        Updated app with guid 86ccbfb7-07f4-4e5d-96dc-b86079f19258 ({"environment_json"=>"[PRIVATE DATA HIDDEN]"})
        Updated app with guid 86ccbfb7-07f4-4e5d-96dc-b86079f19258 ({"environment_json"=>"[PRIVATE DATA HIDDEN]"})
        Creating build for app with guid 86ccbfb7-07f4-4e5d-96dc-b86079f19258
        Updated app with guid 86ccbfb7-07f4-4e5d-96dc-b86079f19258 ({"state"=>"STARTED"})
        Cell 1ec24588-56e0-4f11-869d-514274cdd1bb creating container for instance 3bdcab6f-7cae-407f-9732-7a0b3dfe8cd2
        Cell 1ec24588-56e0-4f11-869d-514274cdd1bb successfully created container for instance 3bdcab6f-7cae-407f-9732-7a0b3dfe8cd2
        Downloading app package...
        Downloaded app package (9M)
        Compiling Java application...
        Java XS Buildpack Version: 1.7.10
        Downloaded 'Tomcat Runtime', version '8.5.32' in 0.3 s.
        Downloaded 'XS Authenticator', version '1.7.5' in 0.0 s.
        Downloaded 'SAPJWT', version '1.1.20' in 0.1 s.
        Downloaded 'SAP JVM Memory Calculator', version '1.7.6' in 0.1 s.
        Downloaded 'XS Hystrix Plugin Hook', version '1.7.6' in 0.0 s.
        Downloaded 'JVMKill', version '1.12.0.RELEASE' in 0.1 s.
        Exit status 0
        Uploading droplet, build artifacts cache...
        Uploading droplet...
        Uploading build artifacts cache...
        Uploaded build artifacts cache (129B)
        Creating droplet for app with guid 86ccbfb7-07f4-4e5d-96dc-b86079f19258
        Uploaded droplet (108.4M)
        Uploading complete
        Cell 1ec24588-56e0-4f11-869d-514274cdd1bb stopping instance 3bdcab6f-7cae-407f-9732-7a0b3dfe8cd2
        Cell 1ec24588-56e0-4f11-869d-514274cdd1bb destroying container for instance 3bdcab6f-7cae-407f-9732-7a0b3dfe8cd2
        Cell b1921372-b387-4581-aae6-ee4db25a2d82 creating container for instance 2f29edc9-f541-4ac1-58f2-056c
        Cell b1921372-b387-4581-aae6-ee4db25a2d82 successfully created container for instance 2f29edc9-f541-4ac1-58f2-056c
        Cell 1ec24588-56e0-4f11-869d-514274cdd1bb successfully destroyed container for instance 3bdcab6f-7cae-407f-9732-7a0b3dfe8cd2
        Starting health monitoring of container
        2019/05/14 09:56:40 Found var: default
        2019/05/14 09:56:40 Found var: :8080
        2019/05/14 09:56:40 Found var: http://localhost:3000
        App urls: [7BDPLWWWwniWaDegranslationServlet.cfapps.eu10.hana.ondemand.com]
        2019/05/14 09:56:40 Starting Reverse Proxy...
        2019/05/14 09:56:40 Found var: 8000
        2019/05/14 09:56:40 Found var: /home/vcap/app/META-INF/.sap_java_buildpack/sapjvm/bin/java -cp /home/vcap/app/META-INF/.sap_java_buildpack/sapjvm/lib/tools.jar:/home/vcap/app/META-INF/.sap_java_buildpack/appcontroller/javadebug.jar com.sap.vscode.java.debugger.adaptar.VSCodeJavaDebuger /home/vcap/app/sources/
        2019/05/14 09:56:40 Starting app: bash -c 'JBP_CONFIG_SAPJVM_MEMORY_SIZES="metaspace:64m.." JRE_HOME="META-INF/.sap_java_buildpack/sapjvm"    JBP_CLASSPATH="" JBP_CONFIG_SAPJVM_MEMORY_INITIALS="heap:100%,metaspace:100%"    JAVA_HOME="META-INF/.sap_java_buildpack/sapjvm" JBP_CONFIG_SAPJVM_MEMORY_SETTINGS=""    CATALINA_HOME="META-INF/.sap_java_buildpack/tomcat" JAVA_OPTS=" -Dcom.sap.jvm.vmtag="null.dev.7BDPLWWWwniWaDegranslationServlet"    -Djava.io.tmpdir=$TMPDIR -Dhttp.port=3000 -Daccess.logging.enabled=false -Dlogback.configurationFile=file:META-INF/.sap_java_buildpack/tomcat/conf/logback.xml    -DSAPJVM_EXTENSION_COMMAND_HANDLER=com.sap.xs2rt.dropletaddon.JvmExtensionCommandHandler    -Djava.protocol.handler.pkgs=com.sap.xs.statistics.stream.handling.protocols -agentpath:/app/META-INF/.sap_java_buildpack/jvm_kill/jvmkill-1.12.0.RELEASE-trusty.so=printHeapHistogram=1"    JBP_CONFIG_SAPJVM_MEMORY_WEIGHTS="heap:75,metaspace:10,stack:5,native:10" ./META-INF/.sap_java_buildpack/tomcat/bin/catalina.sh    run' 
        Working dir: /home/vcap/app
        2019/05/14 09:56:40 Starting java debug
        2019/05/14 09:56:40 map[debug_port:8000]
        2019/05/14 09:56:40 Start listening on port: :8080
        Container became healthy
        { "written_at":"2019-05-14T09:56:43.237Z","written_ts":2848159451855546,"component_type":"application","component_id":"86ccbfb7-07f4-4e5d-96dc-b86079f19258","space_name":"dev","component_name":"7BDPLWWWwniWaDegranslationServlet","component_instance":"0","organization_id":"-","correlation_id":"-","organization_name":"-","space_id":"5c3235c5-d97e-4329-a57a-276a08e4056e","container_id":"10.0.74.237","type":"log","logger":"org.apache.catalina.startup.Catalina","thread":"main","level":"INFO","categories":[],"msg":"Initialization processed in 1639 ms" }
        { "written_at":"2019-05-14T09:56:43.356Z","written_ts":2848159567512845,"component_type":"application","component_id":"86ccbfb7-07f4-4e5d-96dc-b86079f19258","space_name":"dev","component_name":"7BDPLWWWwniWaDegranslationServlet","component_instance":"0","organization_id":"-","correlation_id":"-","organization_name":"-","space_id":"5c3235c5-d97e-4329-a57a-276a08e4056e","container_id":"10.0.74.237","type":"log","logger":"org.apache.catalina.core.StandardService","thread":"main","level":"INFO","categories":[],"msg":"Starting service [Catalina]" }
        { "written_at":"2019-05-14T09:56:43.356Z","written_ts":2848159568011934,"component_type":"application","component_id":"86ccbfb7-07f4-4e5d-96dc-b86079f19258","space_name":"dev","component_name":"7BDPLWWWwniWaDegranslationServlet","component_instance":"0","organization_id":"-","correlation_id":"-","organization_name":"-","space_id":"5c3235c5-d97e-4329-a57a-276a08e4056e","container_id":"10.0.74.237","type":"log","logger":"org.apache.catalina.core.StandardEngine","thread":"main","level":"INFO","categories":[],"msg":"Starting Servlet Engine: Apache Tomcat/8.5.32" }
        { "written_at":"2019-05-14T09:56:46.600Z","written_ts":2848162811830672,"component_type":"application","component_id":"86ccbfb7-07f4-4e5d-96dc-b86079f19258","space_name":"dev","component_name":"7BDPLWWWwniWaDegranslationServlet","component_instance":"0","organization_id":"-","correlation_id":"-","organization_name":"-","space_id":"5c3235c5-d97e-4329-a57a-276a08e4056e","container_id":"10.0.74.237","type":"log","logger":"org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/]","thread":"localhost-startStop-1","level":"ERROR","categories":[],"msg":"Error configuring application listener of class [com.sap.cloud.sdk.cloudplatform.cache.CacheMonitor]","stacktrace":["java.lang.LinkageError: loader constraint violation: when resolving method \"org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;\" the class loader \"<unnamed>\" (instance of org.apache.catalina.loader.ParallelWebappClassLoader@1ff8911a, child of java.net.URLClassLoader@3930015a) of the current class, org/slf4j/LoggerFactory, and the class loader \"System\" (instance of sun.misc.Launcher$AppClassLoader@4b85612c, child of sun.misc.Launcher$ExtClassLoader@25f38edc, urls: 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/logback-classic.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/logback-core.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/jul-to-slf4j.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/slf4j-api.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/xs-logging.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/xsrt-droplet-addon.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/com.fasterxml.jackson-core.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/com.fasterxml.jackson-databind.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/com.fasterxml.jackson-annotations.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/xs-jdsr-statistics-api.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/xs-jdsr-passport.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/xs-jdsr-protocol-handlers.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/cf-java-logging-support-core.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/cf-java-logging-support-logback.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/commons-lang3.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/jackson-jr-objects.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/bootstrap.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/tomcat-juli.jar') for the method's defining class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type org/slf4j/ILoggerFactory used in the signature","\tat org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:418)","\tat org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)","\tat org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)","\tat com.sap.cloud.sdk.cloudplatform.monitoring.JmxMonitor.<clinit>(JmxMonitor.java:23)","\tat sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)","\tat sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)","\tat sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)","\tat java.lang.reflect.Constructor.newInstance(Constructor.java:423)","\tat org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:151)","\tat org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4714)","\tat org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5256)","\tat org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)","\tat org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1421)","\tat org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1411)","\tat java.util.concurrent.FutureTask.run(FutureTask.java:266)","\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)","\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)","\tat java.lang.Thread.run(Thread.java:836)"] }
        { "written_at":"2019-05-14T09:56:46.606Z","written_ts":2848162818182517,"component_type":"application","component_id":"86ccbfb7-07f4-4e5d-96dc-b86079f19258","space_name":"dev","component_name":"7BDPLWWWwniWaDegranslationServlet","component_instance":"0","organization_id":"-","correlation_id":"-","organization_name":"-","space_id":"5c3235c5-d97e-4329-a57a-276a08e4056e","container_id":"10.0.74.237","type":"log","logger":"org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/]","thread":"localhost-startStop-1","level":"ERROR","categories":[],"msg":"Error configuring application listener of class [com.sap.cloud.sdk.cloudplatform.monitoring.ExceptionMonitor]","stacktrace":["java.lang.NoClassDefFoundError: com/sap/cloud/sdk/cloudplatform/monitoring/JmxMonitor : cannot initialize class because prior initialization attempt failed","\tat sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)","\tat sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)","\tat sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)","\tat java.lang.reflect.Constructor.newInstance(Constructor.java:423)","\tat org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:151)","\tat org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4714)","\tat org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5256)","\tat org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)","\tat org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1421)","\tat org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1411)","\tat java.util.concurrent.FutureTask.run(FutureTask.java:266)","\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)","\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)","\tat java.lang.Thread.run(Thread.java:836)","Caused by: java.lang.ExceptionInInitializerError: java.lang.LinkageError: loader constraint violation: when resolving method \"org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;\" the class loader \"<unnamed>\" (instance of org.apache.catalina.loader.ParallelWebappClassLoader@1ff8911a, child of java.net.URLClassLoader@3930015a) of the current class, org/slf4j/LoggerFactory, and the class loader \"System\" (instance of sun.misc.Launcher$AppClassLoader@4b85612c, child of sun.misc.Launcher$ExtClassLoader@25f38edc, urls: 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/logback-classic.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/logback-core.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/jul-to-slf4j.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/slf4j-api.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/xs-logging.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/xsrt-droplet-addon.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/com.fasterxml.jackson-core.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/com.fasterxml.jackson-databind.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/com.fasterxml.jackson-annotations.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/xs-jdsr-statistics-api.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/xs-jdsr-passport.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/xs-jdsr-protocol-handlers.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/cf-java-logging-support-core.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/cf-java-logging-support-logback.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/commons-lang3.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/jackson-jr-objects.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/bootstrap.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/tomcat-juli.jar') for the method's defining class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type org/slf4j/ILoggerFactory used in the signature\n\tat org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:418)\n\tat org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)\n\tat org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)\n\tat com.sap.cloud.sdk.cloudplatform.monitoring.JmxMonitor.<clinit>(JmxMonitor.java:23)\n\tat sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)\n\tat sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)\n\tat sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)\n\tat java.lang.reflect.Constructor.newInstance(Constructor.java:423)\n\tat org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:151)\n\tat org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4714)\n\tat org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5256)\n\tat org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)\n\tat org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1421)\n\tat org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1411)\n\tat java.util.concurrent.FutureTask.run(FutureTask.java:266)\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\n\tat java.lang.Thread.run(Thread.java:836)\n","\tat java.lang.Class.setExceptionThrownDuringClinit(Class.java:3685)","\t... 14 more"] }
        { "written_at":"2019-05-14T09:56:46.609Z","written_ts":2848162820609614,"component_type":"application","component_id":"86ccbfb7-07f4-4e5d-96dc-b86079f19258","space_name":"dev","component_name":"7BDPLWWWwniWaDegranslationServlet","component_instance":"0","organization_id":"-","correlation_id":"-","organization_name":"-","space_id":"5c3235c5-d97e-4329-a57a-276a08e4056e","container_id":"10.0.74.237","type":"log","logger":"org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/]","thread":"localhost-startStop-1","level":"ERROR","categories":[],"msg":"Error configuring application listener of class [com.sap.cloud.sdk.frameworks.hystrix.HystrixBootstrapListener]","stacktrace":["java.lang.LinkageError: loader constraint violation: when resolving method \"org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;\" the class loader \"<unnamed>\" (instance of org.apache.catalina.loader.ParallelWebappClassLoader@1ff8911a, child of java.net.URLClassLoader@3930015a) of the current class, org/slf4j/LoggerFactory, and the class loader \"System\" (instance of sun.misc.Launcher$AppClassLoader@4b85612c, child of sun.misc.Launcher$ExtClassLoader@25f38edc, urls: 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/logback-classic.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/logback-core.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/jul-to-slf4j.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/slf4j-api.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/xs-logging.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/xsrt-droplet-addon.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/com.fasterxml.jackson-core.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/com.fasterxml.jackson-databind.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/com.fasterxml.jackson-annotations.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/xs-jdsr-statistics-api.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/xs-jdsr-passport.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/xs-jdsr-protocol-handlers.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/cf-java-logging-support-core.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/cf-java-logging-support-logback.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/commons-lang3.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/lib/jackson-jr-objects.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/bootstrap.jar', 'file:/home/vcap/app/META-INF/.sap_java_buildpack/tomcat/bin/tomcat-juli.jar') for the method's defining class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type org/slf4j/ILoggerFactory used in the signature","\tat org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:418)","\tat org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)","\tat org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)","\tat com.sap.cloud.sdk.cloudplatform.logging.CloudLoggerFactory.<clinit>(CloudLoggerFactory.java:21)","\tat com.sap.cloud.sdk.frameworks.hystrix.HystrixBootstrapListener.<clinit>(HystrixBootstrapListener.java:22)","\tat sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)","\tat sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)","\tat sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)","\tat java.lang.reflect.Constructor.newInstance(Constructor.java:423)","\tat org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:151)","\tat org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4714)","\tat org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5256)","\tat org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)","\tat org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1421)","\tat org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1411)","\tat java.util.concurrent.FutureTask.run(FutureTask.java:266)","\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)","\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)","\tat java.lang.Thread.run(Thread.java:836)"] }
        { "written_at":"2019-05-14T09:56:46.609Z","written_ts":2848162821206669,"component_type":"application","component_id":"86ccbfb7-07f4-4e5d-96dc-b86079f19258","space_name":"dev","component_name":"7BDPLWWWwniWaDegranslationServlet","component_instance":"0","organization_id":"-","correlation_id":"-","organization_name":"-","space_id":"5c3235c5-d97e-4329-a57a-276a08e4056e","container_id":"10.0.74.237","type":"log","logger":"org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/]","thread":"localhost-startStop-1","level":"ERROR","categories":[],"msg":"Skipped installing application listeners due to previous error(s)" }
        { "written_at":"2019-05-14T09:56:46.610Z","written_ts":2848162821574074,"component_type":"application","component_id":"86ccbfb7-07f4-4e5d-96dc-b86079f19258","space_name":"dev","component_name":"7BDPLWWWwniWaDegranslationServlet","component_instance":"0","organization_id":"-","correlation_id":"-","organization_name":"-","space_id":"5c3235c5-d97e-4329-a57a-276a08e4056e","container_id":"10.0.74.237","type":"log","logger":"org.apache.catalina.core.StandardContext","thread":"localhost-startStop-1","level":"ERROR","categories":[],"msg":"One or more listeners failed to start. Full details will be found in the appropriate container log file" }
        { "written_at":"2019-05-14T09:56:46.630Z","written_ts":2848162842293259,"component_type":"application","component_id":"86ccbfb7-07f4-4e5d-96dc-b86079f19258","space_name":"dev","component_name":"7BDPLWWWwniWaDegranslationServlet","component_instance":"0","organization_id":"-","correlation_id":"-","organization_name":"-","space_id":"5c3235c5-d97e-4329-a57a-276a08e4056e","container_id":"10.0.74.237","type":"log","logger":"org.apache.catalina.core.StandardContext","thread":"localhost-startStop-1","level":"ERROR","categories":[],"msg":"Context [] startup failed due to previous errors" }
        { "written_at":"2019-05-14T09:56:46.813Z","written_ts":2848163025415876,"component_type":"application","component_id":"86ccbfb7-07f4-4e5d-96dc-b86079f19258","space_name":"dev","component_name":"7BDPLWWWwniWaDegranslationServlet","component_instance":"0","organization_id":"-","correlation_id":"-","organization_name":"-","space_id":"5c3235c5-d97e-4329-a57a-276a08e4056e","container_id":"10.0.74.237","type":"log","logger":"org.apache.catalina.startup.Catalina","thread":"main","level":"INFO","categories":[],"msg":"Server startup in 3488 ms" }
        7bdplwwwwniwadegranslationservlet.cfapps.eu10.hana.ondemand.com - [2019-05-14T09:56:57.979+0000] "GET / HTTP/1.1" 404 0 0 "https://webidecp-p1942374760trial.dispatcher.hanatrial.ondemand.com/" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36" "-" "10.0.74.237:61032" x_forwarded_for:"-" x_forwarded_proto:"https" vcap_request_id:"ea073fb3-a87c-44db-67fc-865b1a942b7f" response_time:0.076003855 app_id:"86ccbfb7-07f4-4e5d-96dc-b86079f19258" app_index:"0" x_correlationid:"-" x_b3_traceid:"4c9d2e48c4799a2d" x_b3_spanid:"4c9d2e48c4799a2d" x_b3_parentspanid:"-" b3:"4c9d2e48c4799a2d-4c9d2e48c4799a2d"
        
      • Hi Florian,

        I have posted the error log. Please let me know if you can find something that can help resolve the issue.

        Thanks & Regards,

        Aparna

        • Hi Aparne,

          sorry for the late reply!

          Looking at your error messages it seems like your are missing the following dependencies in your pom.xml:

          <dependency>
              <groupId>com.sap.cloud.s4hana.cloudplatform</groupId>
              <artifactId>core</artifactId>
          </dependency>
          
          <dependency>
              <groupId>org.slf4j</groupId>
              <artifactId>slf4j-api</artifactId>
          </dependency>

           

          Greetings

          Chris

  • Hi! Nice blog, Georg, thank you a lot!

    I was trying to get some ideias to study and a little question emerged into my mind.

    If i want to deploy my own machine learning model, will i integrate it with s4/hana in the same way?

    Regards,

    Wesley.