今日の学習内容

Day7 で S/4HANA 練習システムに作成したカスタム OData V4 API を、BTP 上の CAP Java アプリから実際に呼び出す実装を行いました。複数のエラーを解決しながら、最終的に BTP へのデプロイと XSUAA 認証の設定まで完了しました。

① CAP Java から S/4HANA カスタム API を呼び出す

ZBookService.java

Day7 で作成した ZTBOOK テーブルの OData V4 API を呼び出すサービスクラスです。

@Service
public class ZBookService {

    private static final String S4_URL =
        "https://S42021.TOPSAP.NET:44360/sap/opu/odata4/sap/zsb_book" +
        "/srvd/sap/zsd_book/0001/Book";

    public String getBooks() throws Exception {
        // SSL 証明書の検証をスキップ(練習環境のみ!)
        TrustManager[] trustAll = new TrustManager[]{
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() { return null; }
                public void checkClientTrusted(X509Certificate[] c, String a) {}
                public void checkServerTrusted(X509Certificate[] c, String a) {}
            }
        };
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, trustAll, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier((h, s) -> true);

        RestTemplate restTemplate = new RestTemplate();

        // UTF-8 対応 Base64 認証
        String credentials = USERNAME + ":" + PASSWORD;
        String encoded = Base64.getEncoder().encodeToString(
            credentials.getBytes(StandardCharsets.UTF_8)
        );

        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Basic " + encoded);
        headers.set("Accept", "application/json");

        HttpEntity<String> entity = new HttpEntity<>(headers);

        ResponseEntity<String> response = restTemplate.exchange(
            S4_URL, HttpMethod.GET, entity, String.class
        );

        return response.getBody();
    }
}

② 遭遇したエラーと解決方法

エラー 原因 解決方法
Username cannot be encoded to ISO-8859-1 パスワードに日本語・特殊文字が含まれている StandardCharsets.UTF_8 で手動 Base64 エンコード
certificate_expired (NotAfter: Jan 01 2026) 練習システムの SSL 証明書が期限切れ(きげんぎれ) TrustManager で SSL 検証をスキップ(練習環境のみ)
unreported exception must be caught throws Exception の宣言(せんげん)が必要 try-catch で囲む
Specified unknown buildpack: sap_java_buildpack Trial 環境では buildpack 名が異なる sap_java_buildpack_jakarta に変更
Table "CATALOGSERVICE_BOOKS" not found BTP 上で H2 DB の初期化(しょきか)が実行されていない application.yaml に schema-locations を設定

③ XSUAA 認証の設定

XSUAA(SAP の認証・認可サービス)は BTP 上のアプリのログイン・権限(けんげん)管理を行います。

xs-security.json の作成

{
  "xsappname": "my-cap-java",
  "tenant-mode": "dedicated",
  "scopes": [
    { "name": "$XSAPPNAME.Books.Read",  "description": "本の閲覧権限" },
    { "name": "$XSAPPNAME.Books.Write", "description": "本の編集権限" }
  ],
  "role-templates": [
    {
      "name": "Viewer",
      "description": "閲覧者",
      "scope-references": ["$XSAPPNAME.Books.Read"]
    },
    {
      "name": "Editor",
      "description": "編集者",
      "scope-references": [
        "$XSAPPNAME.Books.Read",
        "$XSAPPNAME.Books.Write"
      ]
    }
  ]
}

manifest.yml に XSUAA をバインド

applications:
  - name: my-cap-java
    memory: 512M
    buildpacks:
      - sap_java_buildpack_jakarta
    path: srv/target/my-cap-java-exec.jar
    random-route: true
    services:
      - my-cap-java-xsuaa    ← XSUAA をバインド

application.yaml に XSUAA 設定を追加

spring:
  sql:
    init:
      schema-locations: classpath:schema-h2.sql
      mode: always
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: ${vcap.services.my-cap-java-xsuaa.credentials.url}/oauth/token

cds:
  security:
    authentication:
      mode: always

④ BTP へのデプロイ手順(てじゅん)

# ① BTP CF にログイン
cf login -a https://api.cf.ap21.hana.ondemand.com

# ② アプリをビルド
mvn package -DskipTests

# ③ BTP にデプロイ
cf push

# ④ 動作確認
cf app my-cap-java | grep routes
cf services

⑤ 動作確認結果

エンドポイント 状態
/odata/v4/CatalogService/Books ✅ 200 OK
/api/zbooks ✅ S/4HANA データ取得成功
XSUAA バインド ✅ create succeeded

⑥ XSUAA の概念(がいねん)まとめ

ユーザー(ブラウザ)
    ↓ ログイン
XSUAA(SAP 認証サーバー)
    ↓ JWT トークン発行(はっこう)
CAP Java アプリ
    ↓ トークン検証(けんしょう)
データ返却(へんきゃく)

今の状態(開発中): auth: mocked → 誰でもアクセス可
本番環境(ほんばんかんきょう): auth: xsuaa → 認証必須

この記事は「SAP BTP 学習」シリーズの第8回です。6ヶ月間の独学で SAP BTP 開発へのキャリアチェンジを目指しています。