DataLoaderをバッチモードで実行する【V58】【Java11】

## 初めに
SalesforceのDataLoaderをバッチモードで実行する記事は山ほどあるが、以下の機能が欲しかったので残しておく

 - DataLoder Version 58.0.4
 - DataLoderのインストールフォルダに依存しない
 - Java 11サポート
 - SpringFrameworkを活用する

## セキュリティトークンの取得
SalesforceのMFAが強制適応になり、DataLoader接続にもセキュリティトークンが必要になる。
認証方法はパスワードの後ろにセキュリティトークンを追加で認証する。
※MFAを設定していない組織でもパスワード＋セキュリティトークンで認証できる

1. プロファイルのアイコンをクリックし、設定画面に移動する
![security_token1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680784/4840bd2e-6f2a-7e0d-d041-1a41fdacfec3.png)

1. セキュリティトークンのリセットをクリックする。
<font color="DeepPink">**※該当メニューが存在しない場合、プロファイルにIPアドレス制限が設定されているか確認すること**</font>
![security_token2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680784/ab1794e8-e002-76b8-e05a-6568f877fde8.png)

1.メールが送信されるので内容を確認する
![security_token3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680784/78c9325c-680a-79a4-db82-7dab2eb72d69.png)
※発行されたセキュリティトークンメールの例（今は無効になったトークンです）
![security_token4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680784/465f3b6b-193a-0deb-0abd-8ca756c4e80f.png)

## データローダバッチの構成
```
C:\DataLoaderProcess
  ├─config.properties              ⇒　データローダ環境設定ファイル
  ├─my.properties                  ⇒　独自の環境設定ファイル
  │─csvAccountExtractProcess.bat   ⇒　個別バッチ実行ファイル(手動実行可能)
  │─dataloader.key                 ⇒　暗号鍵
  │─dataloader-58.0.4.jar          ⇒　データローダJAR
  ├─process.bat                    ⇒　バッチ起動ファイル(ProcessId指定)
  ├─process-conf.xml               ⇒　データローダの実行設定ファイル
  └─log4j2.properties              ⇒　ログ出力用の設定ファイル
```

## データローダの取得
本記事にはJava 11をサポートする最後のバージョンであるV58.0.4を利用する
取得先：https://github.com/forcedotcom/dataloader/releases/tag/v58.0.4

欲しいのは[dataloader-58.0.4.jar]ファイルのみなので任意のフォルダにコピーしておく
この記事では[C:\DataLoaderProcess]にコピーした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680784/a6c8bfc5-d84a-6db0-b001-41fb1d7bf4ab.png)

※DataLoader V58は内部的にSpring-Framework 5.3.27を利用している。
独自のプロパティを活用する場合、以下のjarファイルをダウンロードして格納すること。
[spring-core-5.3.27.jar](https://mvnrepository.com/artifact/org.springframework/spring-core/5.3.27)
[spring-context-5.3.27.jar](https://mvnrepository.com/artifact/org.springframework/spring-context/5.3.27)

## 暗号化されたパスワードの生成

キーファイルを生成する
```PowerShell
cd C:\DataLoaderProcess
java -cp dataloader-58.0.4.jar com.salesforce.dataloader.security.EncryptionUtil -k dataloader.key
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680784/e664ba50-ad07-c813-a5d8-a9da468700ae.png)

メモ帳とかにパスワードとセキュリティトークンを結合した文字列を保管しておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680784/5cd5b625-e1ed-1ceb-d8fe-4a3cef3a7d92.png)

暗号化パスワードを生成する
```PowerShell
java -cp dataloader-58.0.4.jar com.salesforce.dataloader.security.EncryptionUtil -e パスワード+セキュリティトークン dataloader.key
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680784/c80f923f-154a-0636-17fe-1c1c02b4eefa.png)

## 設定ファイルを作成する

### config.properties
```properties
# Data LodaerLoader Config
# https://help.salesforce.com/apex/HTViewHelpDoc?id=loader_params.htm

# 接続先情報
# sandboxの場合：https://test.salesforce.com
sfdc.endpoint=https://login.salesforce.com
sfdc.username=<ログインユーザ名>
sfdc.password=<コマンドで生成した暗号化パスワード>
process.encryptionKeyFile=./dataLoader.key
```

### my.properties
```properties
# 独自の環境設定

outputdirectory=C:/DataLoaderProcess
```

### log4j2.properties
```properties
name = Salesforce Data Loader
monitorInterval = 5
property.basePath = ${sys:java.io.tmpdir}
# RollingFileAppender name, pattern, path and rollover policy
appender.rolling.type = RollingFile
appender.rolling.name = fileAppender
appender.rolling.fileName= ./log/sdl.log
appender.rolling.filePattern= ./log/sdl-%d{yyyy-MM-dd}.log
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = %d %-5p [%t] %C{2} %M (%F:%L) - %m%n
appender.rolling.policies.type = Policies

# CONSOLE Appender
appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d %-5p [%t] %C{2} %M (%F:%L) - %m%n

# RollingFileAppender rotation policy
appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
appender.rolling.policies.size.size = 100KB

# Configure root logger
rootLogger.level = info
rootLogger.appenderRef.rolling.ref = fileAppender
rootLogger.appenderRef.stdout.ref = STDOUT
```

### process-conf.xml
```xml
<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p" 
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/util
           http://www.springframework.org/schema/util/spring-util.xsd
           http://www.springframework.org/schema/tool
           http://www.springframework.org/schema/tool/spring-tool.xsd">

    <!-- 独自の環境設定をロード -->
    <context:property-placeholder location="classpath:my.properties"/>

    <!-- CSV出力ジョブを定義 -->
    <bean id="csvAccountExtractProcess"
          class="com.salesforce.dataloader.process.ProcessRunner"
          scope="prototype">
      <description>csvAccountExtractジョブは、Salesforceから取引先情報を取得し、CSVファイルに保存します。</description>
        <property name="name" value="csvAccountExtract"/>
        <property name="configOverrideMap">
            <map>
                <entry key="sfdc.entity" value="Account"/>
                <entry key="sfdc.extractionRequestSize" value="500"/>
                <entry key="sfdc.extractionSOQL" value="Select Id, Name, NumberOfEmployees, Industry, AnnualRevenue, CreatedDate FROM Account"/>
                <entry key="process.operation" value="extract"/>
                <entry key="dataAccess.type" value="csvWrite"/>
                <entry key="dataAccess.name" value="./extractAccount.csv"/>
            </map>
        </property>
    </bean>
</beans>
```

### process.bat
```batch
@echo off

SET MIN_JAVA_VERSION=11
echo Data Loader requires Java JRE %MIN_JAVA_VERSION% or later. Checking if it is installed...
java -version 1>nul 2>nul || (
echo Did not find java command.
EXIT -1
)

java -cp ".\dataloader-58.0.4.jar;.\spring-core-5.3.27.jar;.\spring-context-5.3.27.jar;." com.salesforce.dataloader.process.DataLoaderRunner .\ %1 run.mode=batch
EXIT /b %ERRORLEVEL%
```

### csvAccountExtractProcess.bat
```batch
@echo off

CALL process.bat csvAccountExtractProcess
```
## バッチファイルの実行
csvAccountExtractProcess.batファイルを実行して起動

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680784/a42cd6b8-9d3b-cd1f-730b-565da71bdefe.png)

## Proxy環境の注意
社内でProxyを利用する場合、XMLスキマー検証時にエラーが発生する場合がある。
回避策として、process.batファイルの以下の箇所にPROXY設定を追加する。

```batch
java -Dhttp.proxyHost=<PROXY HOST> -Dhttp.proxyPort=<PROXY PORT> -cp ".\dataloader-58.0.4.jar;." com.salesforce.dataloader.process.DataLoaderRunner .\ %1 run.mode=batch
```