Java Spring Boot × Salesforce SOAP API

Salesforce App Cloud Advent Calendar 2015の13日目の記事ということでSalesforceのSOAP APIをつかったJavaアプリ開発について投稿したいと思います。

#はじめに
## デモ動画
Salesforce APIでこんな感じのアプリをつくれます。
[![IMAGE ALT Heroku Demo #12 - Java × Salesforce SOAP API ver.1 ](http://img.youtube.com/vi/vI8BniQhmWY/0.jpg)](http://www.youtube.com/watch?v=vI8BniQhmWY)

>Heroku Demo #12 - Java × Salesforce SOAP API ver.1
>https://www.youtube.com/watch?v=vI8BniQhmWY

## サンプルコード
サンプルコードです。Herokuボタンも配置したのでクリックして自分のHeroku環境で動かしてみることができると思います。
<img width="1276" alt="スクリーンショット 2015-12-12 16.10.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/51fbcace-6b58-c6a6-d27b-9825da8828bb.png">

>tyoshikawa1106/java-salesforce-soap-api
>https://github.com/tyoshikawa1106/java-salesforce-soap-api


#Force.com Web Service Connector (WSC)の準備
JavaからSalesforceAPIを実行するにはForce.com Web Service Connectorを用意する必要があります。
<img width="1271" alt="スクリーンショット 2015-12-13 11.38.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/090ba4ba-b161-7d32-6bd2-2905ecc7b2e4.png">
>forcedotcom/wsc
>https://github.com/forcedotcom/wsc

##Building WSC
git cloneコマンドで必要なファイルをダウンロードします。

```
git clone https://github.com/forcedotcom/wsc.git
```

<img width="697" alt="スクリーンショット 2015-12-12 16.25.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/b16228a6-514f-ebac-0b30-008c7ca4d705.png">


wscフォルダをダウンロードしたら次のコマンドでビルドします。

```
cd wsc
mvn clean package -Dgpg.skip
```

<img width="698" alt="スクリーンショット 2015-12-12 16.29.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/06f2f532-c1a0-b918-fed3-24ecad442317.png">

実行時にいくつかWarningが表示されるかもしれませんが、ひとまず問題ありませんでした。これでビルドが完了してwscフォルダに必要なファイルが用意されました。

<img width="1005" alt="スクリーンショット 2015-12-12 16.31.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/06f76fa2-96ee-c6f5-431c-de58edee7f3b.png">

次はPartnerWSDLを取得します。Salesforce組織にログインして設定→開発→APIを選択してください。API WSDLのページが表示されます。『パートナー WSDL の生成』リンクから取得することが可能です。
<img width="1277" alt="スクリーンショット 2015-12-12 16.34.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/bbfe2dd0-6f42-3540-bfef-09fba5f6f816.png">


右クリックのリンク先を別名で保存という感じでダウンロードできると思います。
<img width="710" alt="スクリーンショット 2015-12-12 16.37.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/6227b300-9362-13fe-8fc9-eb86e0ee8a3d.png">


これでParterWSDLの取得も完了しました。『force-wsc-36.0.0.jar』と『partner.wsdl』を利用して『partner.jar』を生成します。

wscフォルダ内に次のように配置してください。
<img width="1110" alt="スクリーンショット 2015-12-12 16.39.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/d6949b24-eba8-e682-48a6-796a899ae152.png">

次のコマンドを実行すると『partner.jar』ファイルが生成されます。

```
java -classpath target/force-wsc-36.0.0-uber.jar com.sforce.ws.tools.wsdlc partner.wsdl partner.jar
```

<img width="873" alt="スクリーンショット 2015-12-12 16.49.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/2a04f02b-af8e-b040-ee2e-120551f9fe71.png">

これでPartner.jarファイルの準備も完了しました。
<img width="939" alt="スクリーンショット 2015-12-12 16.52.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/177eb10b-302c-887e-d8da-f9405982831d.png">

JavaのプロジェクトにPartner.jarファイルとforce-wsc-36.0.0.jarファイルを読みこませることでSaleforce APIが利用できます。

#Javaアプリの開発 (Spring Boot)
##プロジェクトの雛形作成
次のコマンドでJavaプロジェクトの雛形を作成できます。

```
mvn -B archetype:generate -DgroupId=com.example -DartifactId=SalesforceApiApp -Dversion=1.0.0-SNAPSHOT -DarchetypeArtifactId=maven-archetype-quickstart
```

![スクリーンショット 2015-12-12 22.27.44.png](https://qiita-image-store.s3.amazonaws.com/0/8407/e1db8674-4c24-a53d-a436-019c7b68ad04.png)

次のようなファイルが生成されます。
<img width="850" alt="スクリーンショット 2015-12-12 22.28.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/daf482c1-0ef5-657e-8fee-b0806240f90b.png">

##プロジェクトにJarファイルの追加
ここはイマイチ理解できてないのですが、次の手順で追加できました。

1. src / main / resources / libフォルダを作成
2. force-wsc-36.0.0.jarとpartner.jarを格納する

<img width="853" alt="スクリーンショット 2015-12-12 22.38.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/1a472da2-43b1-733d-3423-ca5e7347dc1e.png">

### pom.xmlを編集
dependencyタグにresources/libフォルダに追加したforce-wsc-36.0.0.jarとpartner.jarを宣言します。

<img width="1276" alt="スクリーンショット 2015-12-12 22.53.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/51fa2757-9471-d6d2-aa75-9463d3177f7a.png">

pom.xmlの全体はこんな感じです。

```xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>SalesforceApiApp</artifactId>
  <packaging>jar</packaging>
  <version>1.0.0-SNAPSHOT</version>
  <name>SalesforceApiApp</name>
  
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.0.RELEASE</version>
  </parent>

  <dependencies>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <dependency>
      <groupId>org.codehaus.jackson</groupId>
      <artifactId>jackson-core-asl</artifactId>
      <version>1.9.4</version>
    </dependency>
    <dependency>
      <groupId>org.codehaus.jackson</groupId>
      <artifactId>jackson-mapper-asl</artifactId>
      <version>1.9.4</version>
    </dependency>
    
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.14.0</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>com.sforce.soap.partner</groupId>
      <artifactId>partner</artifactId>
      <version>1.0</version>
      <scope>system</scope>
      <systemPath>${basedir}/src/main/resources/lib/partner.jar</systemPath>
    </dependency>
    <dependency>
      <groupId>com.force.api</groupId>
      <artifactId>force-wsc</artifactId>
      <version>1.0</version>
      <scope>system</scope>
      <systemPath>${basedir}/src/main/resources/lib/force-wsc-36.0.0.jar</systemPath>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <dependencies>
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
            <version>1.2.5.RELEASE</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>

  <properties>
    <java.version>1.8</java.version>
  </properties>
</project>
```

testフォルダにはJavaのテストを行うためのファイル一式が用意されていますが今回はそこまでやらないので削除して進めます。
<img width="1277" alt="スクリーンショット 2015-12-12 23.33.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/c07d875c-e92e-f116-44e6-5fd6ea2f0186.png">


##Spring BootのHello World
pom.xmlの準備ができたら次のコマンドで実行できます。Hello Worldと表示されると思います。

```
cd SalesforceApiApp
mvn spring-boot:run
```
![スクリーンショット 2015-12-12 23.40.13.png](https://qiita-image-store.s3.amazonaws.com/0/8407/de3f4ed4-c1f5-9915-3b45-92e560cddfc2.png)


##STS(Spring Tool Suite)でプロジェクトをインポート
Spring Bootの開発にはSTS(Spring Tool Suite)が便利です。STSはEclipseベースの開発ツールです。

<img width="1272" alt="スクリーンショット 2015-12-13 11.40.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/be694367-fd01-5d2e-2480-bc55eaf2c67a.png">

>Spring Tool Suite™
>https://spring.io/tools


起動した後はまずWorkspaceのパスを指定します。
<img width="587" alt="スクリーンショット 2015-12-12 22.59.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/1783d881-13a0-1f19-de93-f2cdd630441f.png">

これでSTSの使用準備ができました。
<img width="1279" alt="スクリーンショット 2015-12-12 23.01.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/0cc26e04-3bf0-2a3b-884a-b15f364776e2.png">

右クリックでメニューを表示してImportを選択します。
<img width="325" alt="スクリーンショット 2015-12-12 23.07.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/db43d349-19a0-f245-963f-d5b75fc69246.png">

Existing Maven Projectsを選択してNextボタンをクリックします。
<img width="520" alt="スクリーンショット 2015-12-12 23.08.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/79279a97-c4f4-6c0f-010a-62453800192e.png">

Root Directoryにプロジェクトのパスを指定します。Browseボタンでフォルダを指定できます。
<img width="1095" alt="スクリーンショット 2015-12-12 23.23.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/18f340ba-7d33-3911-1f0d-1f4030c1df1e.png">

pom.xmlにチェックがついていることを確認してFinishボタンをクリックします。
<img width="644" alt="スクリーンショット 2015-12-12 23.25.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/107ad734-087d-fe86-aa56-4e1d2ad11b67.png">

これでJava開発の準備ができました。
<img width="1279" alt="スクリーンショット 2015-12-12 23.44.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/e13bfa5c-46e4-9ded-0ca2-f0cb83ed2387.png">

##Webページの表示
実際にWebページ上でHello Worldを表示してみたいと思います。thymeleafを利用します。

<img width="1271" alt="スクリーンショット 2015-12-13 11.43.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/0de6bb20-e5c0-99b6-abe4-3fdfde556865.png">
>Tutorial: Using Thymeleaf (ja)
>http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf_ja.html

App.javaを次のように変更します。

```java:App.java
package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

@EnableAutoConfiguration
@ComponentScan
public class App {

  public static void main(String[] args) {
    SpringApplication.run(App.class, args);
  }
}
```

Controllerを作成します。
<img width="534" alt="スクリーンショット 2015-12-13 10.02.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/4552f983-ea59-54e7-c207-8480f84f6819.png">

内容は次のような感じです。

```java:SalesforceApiController.java
package com.example.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class SalesforceApiController {

    /**
     * Home Page【GET】
     * @return
     */
    @RequestMapping(value="/", method=RequestMethod.GET)
    public String showHome() {
        return "home";
    }
}
```

HTMLを用意します。(resourcesフォルダ内にtemplatesフォルダを作成。その中にhome.htmlを用意します。)

```html:home.html
<html lang="jp">
    <head>
        <title>Home</title>
    </head>
    <body>
        <div id="main">
            <h1>Hello World!!</h1>
        </div>
    </body>
</html>
```

ここまで準備ができたらApp.javaを右クリックしてRun AsのSpring Boot Appを選択します。
<img width="1276" alt="スクリーンショット 2015-12-13 10.14.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/e3f968a4-3582-27c3-d72b-99cb101aac46.png">

localhost:8080にアクセスするとhome.htmlの内容を表示できると思います。
<img width="1107" alt="スクリーンショット 2015-12-13 10.18.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/36ac1db3-0754-e037-31d3-00fc59ec12eb.png">

これでSTSにプロジェクトをインポートするところからJava Spring BootでHTMLとControllerを用意するまでの流れを確認できました。

## Salesforce APIの解説
Java Spring BootをつかったHello Worldの表示まで確認できたところでSalesforce APIの使い方を確認したいと思います。

###Salesforceへのログイン
Salesforce SOAP APIをつかってログインする場合は『ConnectorConfig』にユーザID、パスワード、authEndpointをセットして『PartnerConnection』をnewする感じでログインできます。

```java
public ConnectorConfig getConnectorConfig(String userId, String password, String authEndpoint) throws ConnectionException, AsyncApiException {
      ConnectorConfig partnerConfig = new ConnectorConfig();
      partnerConfig.setUsername(userId);
      partnerConfig.setPassword(password);
      partnerConfig.setAuthEndpoint(authEndpoint);
      new PartnerConnection(partnerConfig);
      return partnerConfig;
}
```

この処理を利用する際に以下のImportが必要になります。

```java
import com.sforce.async.AsyncApiException;
import com.sforce.soap.partner.PartnerConnection;
import com.sforce.ws.ConnectionException;
import com.sforce.ws.ConnectorConfig;
```

authEndpointにセットするURLは次のようになります。

```
// Product またはDev環境
https://login.salesforce.com/services/Soap/u/35.0
// Sandbox環境
https://test.salesforce.com/services/Soap/u/35.0
```

ConnectorConfigではSetした『userName』や『password』などをGetする関数も用意されています。またログイン時の『SesstionID』もここから取得できます。
<img width="769" alt="スクリーンショット 2015-12-13 10.45.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/bc8dabc2-2628-345d-8947-5f735befea72.png">


PartnerConnectionでは『getUserInfo』でログインしたユーザの情報を取得したりlogin(), logoutの関数などが用意されています。
<img width="739" alt="スクリーンショット 2015-12-13 10.48.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/8bb6fcc9-365a-2b6d-4c68-83cf817d2563.png">

###クエリの実行
SOAP APIではpartnerConnectionを使って次のようにクエリを実行できます。

```java
// 取引先(Account)取得クエリの作成
String soqlQuery = "SELECT Name, AccountNumber FROM Account ORDER BY Name ASC LIMIT 200";
// クエリの実行
QueryResult qr = partnerConnection.query(soqlQuery);
// 実行結果の取得
SObject[] records = qr.getRecords();
```

またAccountやContactなどのsObject型変数も宣言できました。

```java
Account acc = new Account();

Object accountName = records[i].getField("Name");
if (accountName != null) {
    acc.setName(String.valueOf(accountName));
} else {
    acc.setName("");
}
```

この辺りの処理を組み合わせていけばSalesforceにログインしてクエリを実行して取引先一覧を表示するところまで動かしてみることができると思います。

##Herokuデプロイについて
Herokuにデプロイするときは『Procfile』ファイルと『system.properties』ファイルを用意する必要があります。

```java:Procfile
web: java $JAVA_OPTS -jar target/*.jar --server.port=$PORT
```

```java:system.properties
java.runtime.version=1.8
```

詳細はこちらにまとめてあります。
>Java：Spring BootアプリのHerokuデプロイを試してみました
>http://tyoshikawa1106.hatenablog.com/entry/2015/11/26/210000

##まとめ
ちょっと長くなりましたが、Java Spring BootとSalesforce SOAP APIをつかったアプリ開発はこんな感じで始めることができます。

SalesforceのSOAP APIについての詳細はDeveloper Guideを確認してください。
<img width="1273" alt="スクリーンショット 2015-12-13 11.03.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/8407/21d08182-e864-93a5-ce94-86c5bcd5a9cb.png">
>SOAP API 開発者ガイド
>https://developer.salesforce.com/docs/atlas.ja-jp.196.0.api.meta/api/