Technical Articles
SAP Cloud SDK for JavaのVDM Generatorを使う
SAP Cloud SDK for JavaのVDM Genaratorを使ってVDMを作成し、オンプレS/4HANA ODataを呼び出します。
今回のプログラムは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へデプロイまで)」および「SAP Cloud SDK for JavaのVDMを使ってオンプレS/4HANA OData呼出」実行済であること。
- 銀行マスタを登録済であること
- SAP Gatewayを有効にしていること
- Destination サービスを設定済であること
1. メタデータ保存
1.1. ディレクトリ作成
<project-root>/applicationの下に”edmx”というディレクトリを作成します。
1.2. メタデータダウンロード
今回はS/4 HANAのODataを呼び出すので、S/4 HANAにログインしてメタデータを照会します。「Generate .edmx and/or .xml file for Fiori App developed using SAP Web IDE」を参考にしました。
銀行系は軽くて手頃かと思い”/sap/opu/odata/sap/FCLM_BM_SRV/”を使っています。http://<host>:<port>/sap/opu/odata/sap/FCLM_BM_SRV/$metadata?sap-language=E でメタデータをダウンロード。”Bank.xml”という名前で保存しています。日本語ではなく英語でログインしましてダウンロードしないと後続でエラーになりました。
2. IDEにPluginインストール
IntelliJ IDEAのPluginとして“IntelliJ Lombok plugin”をインストールします。IntelliJ IDEAのメニュー File -> Settings を選択し、Pluginのメニューから上記を検索してインストール。
これがないと、いろいろなエラーが起きます。
3. POM.xml調整
<project-root>/application/POM.xmlのdependenciesパス配下に以下を追加します。
<!-- for vdm generator -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
また、同じファイルの build -> plugins パス配下に以下を追加します。バージョンはリンク先のMaven Repositoryを見て合わせてください。
※V4の場合はData Model OData V4 Services Generatorも必要かも。
<plugin>
<groupId>com.sap.cloud.sdk.datamodel</groupId>
<artifactId>odata-generator-maven-plugin</artifactId>
<version>3.15.1</version>
<executions>
<execution>
<id>generate-consumption</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputDirectory>${project.basedir}/edmx</inputDirectory>
<outputDirectory>${project.build.directory}/vdm</outputDirectory>
<deleteOutputDirectory>true</deleteOutputDirectory>
<packageName>com.vdm</packageName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/vdm</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
4. VDMクラス生成
パッケージ生成します。
# from application directory
mvn clean package
するとvdmクラスが生成されています(IntelliJ IDEAから参照)。
そして、ディレクトリをソースとして認識させます。
5. サーブレット作成
<project-root>/application/src/main/java/com/sap/cloud/sdkにGetBankServlet のJava Classを作成します。
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 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.List;
// generated by SAP Cloud SDK VDM generator
import com.vdm.namespaces.bank.Bank;
import com.vdm.services.DefaultBankService;
@WebServlet("/bank")
public class GetBankServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final Logger logger = LoggerFactory.getLogger(GetBankServlet.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());
try{
final List<Bank> banks =
new DefaultBankService()
.getAllBank()
.select(Bank.BANK_KEY, Bank.BANK_NAME)
.filter(Bank.BANK_COUNTRY.eq("JP"))
.top(5)
.execute(destination);
logger.info(new Gson().toJson(banks));
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8"); //日本語用
response.getWriter().write(new Gson().toJson(banks));
} catch (final ODataException e){
logger.error(e.getMessage(), e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write(e.getMessage());
}
}
}
6. ローカル実行
あとは今までと変わらず、ローカルで実行します。
ローカルで実行する場合は環境変数でDestinationの設定をしておいてください。
set destinations=[{name: "Erp1809", url: "http://<host>:<port>", username: "xxx", password: "xxx", sap-language: "ja"}]
で、tomee 起動します。
mvn clean package && mvn tomee:run
ブラウザで http://localhost:8080/bankを開いてJSONで以下が出力されました。
[{"BankInternalId":"0000000","BankName":"銀行 冨田"},{"BankInternalId":"0000001","BankName":"bank ale3 test"},{"BankInternalId":"0000777","BankName":"ダミー銀行"},{"BankInternalId":"0001001","BankName":"ミズホ"},{"BankInternalId":"0001026","BankName":"ミズホ"}]
CFにデプロイしても同じなので割愛します。
sap-cloud-sdkを利用してS/4HANA ODataの取得を試みています。
下記のようなリクエストのサービスではご紹介いただいた方法で、VDMクラスを生成してoDataを取得することができました。
https://<hostname>/sap/odata/sap/<servicename>/<entity>
一方、下記のようなリクエストのサービスのoData取得で取得方法がわかりませんでした。
https://<hostname>/sap/odata/sap/<servicename>/<entity>(startDate=datetime'2022-01-01T00:00:00',endDate=datetime'2022-06-10T00:00:00')/Set
この場合でもmetadataからVDMクラスを生成することはできました。
しかし、VDMクラスが備えているメソッドの利用方法がわかりません。
本Blogの例では、VDMクラスはgetAll<entity名>のようなメソッドを備えており、これを利用することでoDataを取得していましたが、これに相当するメソッドがありませんでした。
おそらくNavigation Propertyが入ったリクエストのため、リクエストの表現方法が異なるためだと思います。
Navigation Propertyや必須のパラメータが入ったリクエストの取得方法の参考ページなどあれば教えていただけますでしょうか。
結論から言うと、私にわかりません。
以前、同様のことを調べて諦めた記憶があります。2年前のことなので、記憶が曖昧ですが、当時はできないと結論づけました(調査時間が足りなかったか、技術的にサポートしていないパターンかのどちらかです)。ただ、2年間ほど調べていないので、現在はできるかもしれないです。
ご回答ありがとうございます。
承知しました。