Java (WSC)のBulk APIでデータ項目の対応付けを行う

  • 2
    Like
  • 0
    Comment
More than 1 year has passed since last update.

Salesforceとのデータ連携を行うためのBulk APIには、項目の対応付け(マッピング)を行うための仕組みがあります(会社のChatterで流れてきて初めて知りました…)

Bulk API開発者ガイド:データ項目の対応付け

変換仕様ファイルを食わせる(アップロードする)ことで、そのジョブにおいて、CSVファイルの項目とSalesforceの項目を対応付けたり、デフォルト値を設定したり、日時のフォーマットを指定したりできるものみたいです。

というわけで、これをJava(Force.com Web Services Connector, 以下WSC)で試してみました。

基本的には、以下のサンプルコードをベースにしてます(というか、9割9分同じです)

https://developer.salesforce.com/docs/atlas.ja-jp.api_asynch.meta/api_asynch/asynch_api_code_walkthrough.htm

変換仕様のアップロード

上記サンプルコード中の runSample の引数として、変換仕様ファイルのパスを渡すようにして、変換仕様のアップロードを行なうためのメソッド BulkConnection#createTransformationSpecFromStream を呼び出し。

    public void runSample(String sobjectType, String userName,
                          String password, String sampleFileName, String specFileName)
            throws AsyncApiException, ConnectionException, IOException {
        BulkConnection connection = getBulkConnection(userName, password);
        JobInfo job = createJob(sobjectType, connection);

        try (InputStream in = new FileInputStream(specFileName)) {
            connection.createTransformationSpecFromStream(job, in);
        }

        List<BatchInfo> batchInfoList = createBatchesFromCSVFile(connection, job,
                sampleFileName);
        closeJob(connection, job.getId());
        awaitCompletion(connection, job, batchInfoList);
        checkResults(connection, job, batchInfoList);
    }

あとは、インポートファイル、変換仕様ファイルもサンプルそのままで実行。
ただし、このサンプルは取引先責任者(Contact)用の呼び出しなので、 main() メソッドで渡しているオブジェクトタイプは、AccountでなくContactである必要があります。

さて、これで問題なく動いてくれる(つまり取引先責任者が作成される)ことを期待したのですが、2点ほど手を加えてエラーを解消する必要がありました。

エラー1: Records not processed

まず以下のエラーに遭遇します。

エラー
Exception in thread "main" [AsyncApiException  exceptionCode='InvalidBatch'
 exceptionMessage='Records not processed'
]

    at com.sforce.async.BulkConnection.parseAndThrowException(BulkConnection.java:158)
    at com.sforce.async.BulkConnection.doHttpGet(BulkConnection.java:711)
    at com.sforce.async.BulkConnection.getBatchResultStream(BulkConnection.java:582)
    at bulkspec.BulkExample.checkResults(BulkExample.java:71)
    at bulkspec.BulkExample.runSample(BulkExample.java:58)
    at bulkspec.BulkExample.main(BulkExample.java:38)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

このエラーが出ている時にSalesforce上で一括データ読み込みジョブを確認すると、処理済みレコード数0(レコードの失敗も0)のジョブが実行されてしまったことが分かります。

解決策:バッチ作成メソッドをcreateBatchFromStreamからcreateBatchFromForeignCsvStreamに変更

createBatch() メソッドの中で呼び出しているメソッドを直します。

Before
BatchInfo batchInfo = connection.createBatchFromStream(jobInfo, tmpInputStream);
After
BatchInfo batchInfo = connection.createBatchFromForeignCsvStream(jobInfo, tmpInputStream, "UTF-8");

ちなみに、最後の引数は null でもOKでした。

エラー2: INVALID_FIELD: Failed to deserialize field at col 0.

次に以下のエラーに遭遇します。

エラー2
Failed with error: INVALID_FIELD:Failed to deserialize field at col 0. Due to, '10 Feb 40' is not a valid value for the type xsd:date:Birthdate --
Failed with error: INVALID_FIELD:Failed to deserialize field at col 0. Due to, '10 Feb 40' is not a valid value for the type xsd:date:Birthdate --

解決策:変換仕様ファイルを修正

どうもサンプルの変換仕様ファイル or インポートファイルが間違っている模様。

ということで、6行目のBirthdateの変換仕様を修正すればOK。

Before
Birthdate,Date of Birth,,dd MM yy
After
Birthdate,Date of Birth,,dd MMM yy

Feb (=2月) のような月の変換は MM だとうまく変換してくれないみたいですね。

逆に、上記のように変換仕様ファイルを修正するのではなく、インポートファイルの方の Feb02 に変えてもOKです。この場合は、 MM で月(0112)を変換してくれます。