Disclaimer: This blog post is only applicable for the SAP Cloud SDK version of at most 2.19.2. We plan to continuously migrate these blog posts into our List of Tutorials. Feel free to check out our updated Tutorials on the SAP Cloud SDK.
LeonardoMlFoundation
class is the key. See below!mvn archetype:generate -DarchetypeGroupId=com.sap.cloud.s4hana.archetypes \
-DarchetypeArtifactId=scp-cf-tomee -DarchetypeVersion=LATEST
mvn package
mvn tomee:run # or: mvn tomee:debug
cf push
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):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
HelloWorldServlet
to create a new servlet named TranslationServlet
, for example. Also change the url path prefix from '/hello'
to, for example, '/translate'
.LeonardoMlFoundation
, creating service classes of type LeonardoMlService
. It 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>
...
LeonardoMlService mlService =
LeonardoMlFoundation.create(
CloudFoundryLeonardoMlServiceType.TRIAL_BETA,
LeonardoMlServiceType.TRANSLATION);
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);
// 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"));
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 ...
}
LeonardoMlService
does that for you.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
cf push
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
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());
}
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
26 | |
22 | |
19 | |
13 | |
10 | |
9 | |
9 | |
8 | |
7 | |
7 |