【salesforce】Tooling APIで静的リソースの登録と更新(JavaサンプルSOAP API)

#Tooling APIとは

　Tooling APIは、Force.comアプリケーション用のカスタム開発ツールを構築できるSOAPおよびRESTインターフェースを提供します。
　今回はTooling APIでSOAP APIを利用して、静的リソースの登録と更新を行います。Enterprise WSDLを利用します。

#開発流れ

　　1. Enterprise WSDL生成及び取得
　　2. 必要なJarファイルをプロジェクトにインポート
　　3. 1で取得したWSDLにより、Enterprise Jarファイルを生成及びプロジェクトにインポート
　　4. ソース実装

#説明
## 1. Enterprise WSDL生成及び取得
　　Salesforceのマニュアルをご参照ください。
　　※[ステップ 1: 組織の Web サービス WSDL の生成または取得](https://developer.salesforce.com/docs/atlas.ja-jp.salesforce1api.meta/salesforce1api/meta_quickstart_get_WSDLs.htm)

##2. 必要なJarファイルをプロジェクトにインポート
　　該当サンプルには「Force.com Web Service Connector」パッケージが必要です。
　　Mavenのインポート例は下記の設定pom.xmlファイルに追加します。
　　他のプロジェクト管理ツールの場合、[mvnrepository](https://mvnrepository.com/artifact/com.force.api/force-apex-api/48.1.0)をご参照ください。

```xml:pom.xml
<!-- https://mvnrepository.com/artifact/com.force.api/force-wsc -->
<dependency>
    <groupId>com.force.api</groupId>
    <artifactId>force-wsc</artifactId>
    <version>48.1.0</version>
</dependency>
```

##3. 1で取得したWSDLにより、Enterprise Jarファイルを生成及びプロジェクトにインポート
　　下記のソースにより、Enterprise Jarファイルを作成

```java
java –classpath force-wsc-30.0.0.jar;ST4-4.0.7.jar;antlr-runtime-3.5.jar com.sforce.ws.tools.wsdlc enterprise.wsdl enterprise.jar
```
　　プロジェクトにインポートには、eclipseはネット上たくさん例があるので、グーグルで検索して、こちらは割愛します。
　　以下はvscodeのインポート例です。

　　1. 上に生成したJarファイルを保存したいフォルダーに配布します。
　　2. プロジェクト保存フォルダー配下の「.classpath」ファイルに下記ソールと追記します。

```xml:.classpath
<classpathentry kind="lib" path="C:\xxx\.jar\enterprise.jar"/>
```

#4. ソース実装
　　4.1. 必要なクラスをインポート

```java
// 静的リソース読み込み用
import java.nio.file.Paths;
import java.io.IOException;
import java.nio.file.Files;

// Tooling API呼び出し用
import com.sforce.soap.enterprise.Connector;
import com.sforce.soap.enterprise.EnterpriseConnection;
import com.sforce.soap.enterprise.QueryResult;
import com.sforce.soap.enterprise.SaveResult;
import com.sforce.soap.enterprise.sobject.SObject;
import com.sforce.soap.enterprise.sobject.StaticResource;
import com.sforce.ws.ConnectionException;
import com.sforce.ws.ConnectorConfig;
```

　　4.2. EnterpriseConnectionを生成

```java:getEnterpriseConnection
    private static EnterpriseConnection getEnterpriseConnection() throws ConnectionException {        ConnectorConfig config = new ConnectorConfig();
        config.setUsername("username"); //実際にはsandboxのログインアカウントを指定
        config.setPassword("password"); //実際にはsandboxのログインパスワードを指定

        return Connector.newConnection(config);
    }
```

　　4.3. 静的リソースをアップロード

```java:createStaticResource
    private static void createStaticResource(EnterpriseConnection connection) throws IOException, ConnectionException{
        
        StaticResource sr = new StaticResource();
        sr.setName("test");
        // STATICRESOURCE_FILE_PATP:静的リソースファイルのフルパス
        byte[] Body = Files.readAllBytes(Paths.get(STATICRESOURCE_FILE_PATH));
        sr.setBody(Body);
        sr.setCacheControl("Public");
        sr.setContentType("application/json");

        SaveResult[] ret = connection.create(new SObject[]{sr});
        for(SaveResult r: ret) {
            System.out.println(r.getId());
            System.out.println(r.getSuccess());
            if (r.getErrors().length > 0) {
                System.out.println(r.getErrors()[0]);
            }
        }
    }
```

　　4.4. 静的リソースをアップグレード

```java:updateStaticResource
    private static void updateStaticResource(EnterpriseConnection connection) throws IOException, ConnectionException{
        // QUERY_STATICRESOURCE_SQL:静的リソースを検査用SOQL(select id form staticresource where name = 'test')
        QueryResult qr = connection.query(QUERY_STATICRESOURCE_SQL);
        SObject[] srs = qr.getRecords();
        StaticResource sr = (StaticResource)srs[0];
        byte[] Body = Files.readAllBytes(Paths.get(STATICRESOURCE_FILE_PATH));
        sr.setBody(Body);
        SaveResult[] ret = connection.update(new SObject[]{sr});
        for(SaveResult r: ret) {
            System.out.println(r.getId());
            System.out.println(r.getSuccess());
            if (r.getErrors().length > 0) {
                System.out.println(r.getErrors()[0]);
            }
        }
    }
```

　　4.5. メインメソッド

```java:main
    public static void main( String[] args )  throws IOException, ConnectionException {

        EnterpriseConnection connection = getEnterpriseConnection();
        // createStaticResource(connection);
        updateStaticResource(connection);
    }
```

#参考
[1. メタデータ API](https://developer.salesforce.com/docs/atlas.ja-jp.salesforce1api.meta/salesforce1api/apis_meta_introducing.htm)
[2. Force.com Web Service Connector](https://mvnrepository.com/artifact/com.force.api/force-wsc/48.1.0)
[3. SalesforceのSOAP APIをJavaから呼び出す](https://kikutaro777.hatenablog.com/entry/2015/11/07/115453)