Technical Articles
SAP Cloud SDK for JavaのVDMを使ってオンプレS/4HANA OData呼出
SAP Cloud SDK for JavaのVDMを使ってオンプレS/4HANA ODataを呼び出します。
Connect to OData Service on Cloud Foundry Using SAP Cloud SDKの内容を少し変えています。
今回のプログラムはGitHubに置いています(今回以外の内容もあるので注意)。
開発環境
以下の環境で実行しています。
- OS: Windows10 64-bit
- openJDK: 1.8.0_242
- Chocolatey: 0.10.15
- maven: 3.6.3
- IDE: IntelliJ IDEA Community Edition 2019.3.3
- CF cli: 6.37.0+a40009753.2018-05-25
- SAP Cloud SDK for Java: 3.15.1
手順
0. 前提
- 「SAP Cloud SDK for Javaの簡単な動かし方(CFへデプロイまで)」を実行済であること。
- BPのCustomerを登録済であること
- SAP Gatewayを有効にしていること
1. 環境変数設定
コマンドプロンプトで一時的な環境変数を設定します。証明書関連が面倒なのでHTTPSでなくHTTPアクセスにしています。クライアントを指定したい場合は”sap-client”を追加すればいいはず(未確認)。
set destinations=[{name: "Erp1809", url: "http://<host>:<port>", username: "xxx", password: "xxx", sap-language: "ja"}]
2. サーブレット作成
<project-root>/application/src/main/java/com/sap/cloud/sdk 以下に”GetCustomerServlet”のJava Classを作成。
URLのパラメータから”name”の値を受け取ってcustomerを部分一致で検索しています。”substringof”を使って部分一致検索をしているのですが、3.15.1時点のSDKでは専用のメソッドはないようです。
このODataはS/4HANA上の”/sap/opu/odata/sap/API_BUSINESS_PARTNER/A_Customer”に対応しています。
package com.sap.cloud.sdk;
import com.google.gson.Gson;
import com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor;
import com.sap.cloud.sdk.odatav2.connectivity.ODataException;
import com.sap.cloud.sdk.s4hana.connectivity.DefaultErpHttpDestination;
import com.sap.cloud.sdk.s4hana.connectivity.ErpHttpDestination;
import com.sap.cloud.sdk.s4hana.datamodel.odata.namespaces.businesspartner.Customer;
import com.sap.cloud.sdk.s4hana.datamodel.odata.services.DefaultBusinessPartnerService;
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;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@WebServlet("/customer")
public class GetCustomerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final Logger logger = LoggerFactory.getLogger(GetCustomerServlet.class);
private static final ErpHttpDestination destination =
DestinationAccessor.getDestination("Erp1809")
.asHttp().decorate(DefaultErpHttpDestination::new);
@Override
protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
throws IOException {
logger.info("Start get method: " + request.getRequestURI());
String parameter = request.getParameter("name");
logger.info("Get parameter 'name': " + parameter);
try{
final String searchParameter = "substringof(CustomerName, '" + parameter + "')";
final List<Customer> customers =
new DefaultBusinessPartnerService()
.getAllCustomer()
.withQueryParameter("$filter", searchParameter)
.select(Customer.CUSTOMER, Customer.CUSTOMER_FULL_NAME)
.top(5)
.execute(destination);
logger.info(new Gson().toJson(customers));
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8"); //日本語用
response.getWriter().write(new Gson().toJson(customers));
} catch (final ODataException e){
logger.error(e.getMessage(), e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write(e.getMessage());
}
}
}
3. ローカル実行
コンパイルしてtomee起動
# from directory application
mvn clean package && mvn tomee:run
以下のurlをブラウザで開く。
http://localhost:8080/customer?name=test
S/4のODataを呼び出し、以下のcustomer検索結果がJSONで表示される。
[{"Customer":"9","CustomerFullName":" test/ test"},{"Customer":"223","CustomerFullName":" HT Test/1234567 TOKYO"},{"Customer":"10000","CustomerFullName":" TEST/111-1111 TEST"},{"Customer":"10001","CustomerFullName":" TEST/111-1111 TEST"},{"Customer":"99993","CustomerFullName":" test/ tokyo"}]
コンソール上には以下のようなログを出します。
09:56:37.566 [http-nio-8080-exec-2] INFO com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor - Creating a new DestinationLoaderChain with EnvVarDestinationLoader as the primary DestinationLoader implementation.
09:56:38.797 [http-nio-8080-exec-2] INFO com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor - Using an instance of ScpCfDestinationLoader as the secondary DestinationLoader implementation.
09:56:40.662 [http-nio-8080-exec-2] INFO com.sap.cloud.sdk.GetCustomerServlet - Start get method: /customer
09:56:40.665 [http-nio-8080-exec-2] INFO com.sap.cloud.sdk.GetCustomerServlet - Get parameter 'name': test
09:56:43.857 [http-nio-8080-exec-2] INFO com.sap.cloud.sdk.GetCustomerServlet - [{"Customer":"9","CustomerFullName":" test/ test"},{"Customer":"223","CustomerFullName":" HT Test/1234567 TOKYO"},{"Customer":"10000","CustomerFullName":" TEST/111-1111 TEST"},{"Customer":"10001","CustomerFullName":" TEST/111-1111 TEST"},{"Customer":"99993","CustomerFullName":" test/ tokyo"}]
4. Cloud Foundryへデプロイ
4.1. Destination定義
SAP Cloud Platform Cloud Foundryでサブアカウント(今回はtrial)の Connectivity -> Destinations で以下のように定義(スペース配下にDestinationを作っても大丈夫)。
4.2. Destination インスタンス作成
CF cliでログインして”my-destination”というインスタンスを作成。このDestinationには何も定義しません(4.1でサブアカウント単位でしているから)。
cf login
cf create-service destination lite my-destination
4.3. manifest.yml更新
servicesで「4.2. Destination インスタンス作成」で作成したDestination インスタンスをbindします。また、routesとrandom-routeもついでに変更しました。routeをrandomにして作成し続けるとquotaを超えてエラーになるからです(cli から”cf routes”で既存のrouteを確認できます)。
---
applications:
- name: cloud-sdk-test
memory: 1024M
timeout: 300
routes:
- route: https://<rounte>.cfapps.eu10.hana.ondemand.com
random-route: false
path: application/target/cloud-sdk-test-application.war
buildpacks:
- sap_java_buildpack
env:
TARGET_RUNTIME: tomee7
SET_LOGGING_LEVEL: '{ROOT: INFO, com.sap.cloud.sdk: INFO}'
JBP_CONFIG_SAPJVM_MEMORY_SIZES: 'metaspace:128m..'
services:
# - my-application-logs
# - my-xsuaa
- my-destination
# - my-connectivity
4.4. デプロイ(cf push)
あとはcli で”cf push”でデプロイするだけです。
ブラウザで同じようにhttps://<route><domain>/customer?name=testを開くとローカルと同様の結果が出ます。