Salesforce と kintone 間で顧客データを同期する方法として、CDataドライバーを利用したWindowsフォームアプリケーション(C#/ADO.NET)によるものを別記事でご紹介しました。
CDataドライバーは、ADO.NETのみならず様々なテクノロジーで提供されています。今回は、Salesforce と kintone 間で顧客データを同期するアプリケーションの Java による例をご紹介したいと思います。
このアプリケーションの概要は次の通りです。
- JDK 8
- JavaFX によるデスクトップアプリケーション
- Eclipse 4.6
- Salesforce および kintone からデータを読み込む
- インポートしたい行を選択して、Salesforce から kintone へデータをインポートする
それでは、このサンプルアプリケーションの開発手順を見ていきます。
ソースコード
このサンプルアプリケーションのソースコードはこちらからどうぞ。
CData製品のインストール
CData Software をインストールします。今回必要になるのは、次の2つです。
開発環境の準備
Eclipse 4.6 を使用します。以下の機能を Eclipse にインストールしておいてください。
- e(fx)clipse - IDE
※ サイトのロケーションは http://download.eclipse.org/efxclipse/updates-released/2.4.0/site を使用
プロジェクト作成
新規プロジェクトを作成します。JavaFX Project を選択します。
デフォルトのまま順次「次へ」ボタンをクリックしていきます。最後のダイアログでは、「言語」に"FXML"、「Root-Type」に"javax.scene.layout.AnchorPane"、「ファイル名」に"MainPane"、「Controller Name」に"MainPaneController"を指定し、完了ボタンをクリックします。
処理の実装
データモデルクラス
Salesforce側はContact、kintone側は顧客リスト に対応するクラスを実装します。これは単純なDTOです。
package application;
public class Contact {
private String id;
private String accountId;
private String department;
private String email;
private String fax;
private String name;
private String phone;
private String accountName;
private String accountAddress;
private String accountBillingPostalCode;
// 以下略 それぞれのsetter/getter
}
package application;
public class 顧客リスト {
private int recordId;
private String fax_数字のみ_;
private String tel_数字のみ_;
private String メールアドレス;
private String レコード番号;
private String 会社名;
private String 住所;
private String 担当者名;
private String 部署名;
private String 郵便番号_数字のみ_;
// 以下略 それぞれのsetter/getter
}
MainPaneController
今回のアプリケーションの主たるクラスです。javafx.fxml.Initializableを実装して初期化できるようにします。さらに、Salesforce/kintoneに接続するためのJDBCURL、そしてそれらのデータを表示するためのTableViewのフィールドを追加します。
※JDBCURLの形式はマニュアルに記載されています。
public class MainPaneController implements Initializable {
private String salesforceJdbcUrl = "<SalesforceのJDBCURL>";
private String kintoneJdbcUrl = "<kintoneのJDBCURL>";
@FXML
private TableView<Contact> salesforceTable;
@FXML
private TableView<顧客リスト> kintoneTable;
データの読み込み
MainPaneControllerに、Salesforce/kintoneのデータをTableViewに読み込む処理を実装します。JDBCを使ったシンプルなものです。
private void loadSalesforceTableView() {
salesforceTable.getItems().clear();
try (
Connection conn = DriverManager.getConnection(salesforceJdbcUrl);
PreparedStatement pstmt = conn.prepareStatement(
"SELECT c.*, " +
"a.Name AccountName, a.BillingPostalCode AccountBillingPostalCode, CONCAT(a.BillingState, a.BillingCity, a.BillingStreet) AccountAddress " +
"FROM Contact c INNER JOIN Account a ON a.Id=c.AccountId");
ResultSet rs = pstmt.executeQuery();
) {
while (rs.next()) {
Contact c = new Contact();
c.setId(rs.getString("Id"));
c.setAccountId(rs.getString("AccountId"));
c.setDepartment(rs.getString("Department"));
c.setEmail(rs.getString("Email"));
c.setFax(rs.getString("Fax"));
c.setName(rs.getString("Name"));
c.setPhone(rs.getString("Phone"));
c.setAccountName(rs.getString("AccountName"));
c.setAccountAddress(rs.getString("AccountAddress"));
c.setAccountBillingPostalCode(rs.getString("AccountBillingPostalCode"));
salesforceTable.getItems().add(c);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
private void loadKintoneTableView() {
kintoneTable.getItems().clear();
try (
Connection conn = DriverManager.getConnection(kintoneJdbcUrl);
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM 顧客リスト");
ResultSet rs = pstmt.executeQuery();
) {
while (rs.next()) {
顧客リスト c = new 顧客リスト();
c.setRecordId(rs.getInt("RecordId"));
c.setFax_数字のみ_(rs.getString("Fax(数字のみ)"));
c.setTel_数字のみ_(rs.getString("Tel(数字のみ)"));
c.setメールアドレス(rs.getString("メールアドレス"));
c.setレコード番号(rs.getString("レコード番号"));
c.set会社名(rs.getString("会社名"));
c.set住所(rs.getString("住所"));
c.set担当者名(rs.getString("担当者名"));
c.set部署名(rs.getString("部署名"));
c.set郵便番号_数字のみ_(rs.getString("郵便番号(数字のみ)"));
kintoneTable.getItems().add(c);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
アプリケーションの初期化
MainPaneControllerのinitializeを実装します。主な処理はデータ読み込みのメソッドを呼び出すだけです。
@Override
public void initialize(URL location, ResourceBundle resources) {
salesforceTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
loadSalesforceTableView();
loadKintoneTableView();
}
インポート処理
インポート処理を実装します。やっていることは、Salesforce側のTableViewで選択された行のデータで、JDBCでシンプルにkintone側にINSERT/UPDATE文を実行しているだけです。
@FXML
private void importOnClick(MouseEvent event) {
try (Connection conn = DriverManager.getConnection(kintoneJdbcUrl)) {
conn.setAutoCommit(false);
for (Contact contact : salesforceTable.getSelectionModel().getSelectedItems()) {
顧客リスト kintoneItem = kintoneTable.getItems().stream()
.filter(o -> o.getメールアドレス().equals(contact.getEmail()))
.findFirst()
.orElse(new 顧客リスト());
PreparedStatement pstmt;
if (kintoneItem.getRecordId() == 0) {
pstmt = conn.prepareStatement("INSERT INTO 顧客リスト(メールアドレス, 会社名, 住所, 担当者名, 部署名, [郵便番号(数字のみ)], [Tel(数字のみ)], [Fax(数字のみ)]) VALUES(?, ? ,? ,? ,? ,? ,? ,?)");
} else {
pstmt = conn.prepareStatement("UPDATE 顧客リスト SET メールアドレス=?, 会社名=?, 住所=?, 担当者名=?, 部署名=?, [郵便番号(数字のみ)]=?, [Tel(数字のみ)]=?, [Fax(数字のみ)]=? WHERE RecordId=?");
pstmt.setInt(9, kintoneItem.getRecordId());
}
pstmt.setString(1, contact.getEmail());
pstmt.setString(2, contact.getAccountName());
pstmt.setString(3, contact.getAccountAddress());
pstmt.setString(4, contact.getName());
pstmt.setString(5, Optional.ofNullable(contact.getDepartment()).orElse(""));
pstmt.setString(6, Optional.ofNullable(contact.getAccountBillingPostalCode()).orElse("").replace("-", ""));
pstmt.setString(7, contact.getPhone());
pstmt.setString(8, contact.getFax());
pstmt.execute();
pstmt.close();
}
conn.commit();
} catch (Exception e) {
System.out.println(e.getMessage());
}
loadKintoneTableView();
}
画面の作成
最後に画面を作成します。application/MainPane.fxmlを開き、以下のコードを実装します。データモデルクラスの各プロパティとテーブルの列をマッピングしています。
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="660.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/8.0.102" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainPaneController">
<children>
<TableView fx:id="salesforceTable" layoutX="14.0" layoutY="53.0" prefHeight="600.0" prefWidth="485.0">
<columns>
<TableColumn prefWidth="150.0" text="担当者名">
<cellValueFactory><PropertyValueFactory property="name" /></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="150.0" text="メールアドレス">
<cellValueFactory><PropertyValueFactory property="email" /></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="150.0" resizable="false" sortable="false" text="会社名">
<cellValueFactory><PropertyValueFactory property="accountName" /></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="150.0" text="部署名">
<cellValueFactory><PropertyValueFactory property="department" /></cellValueFactory>
</TableColumn>
<TableColumn prefWidth="150.0" text="住所">
<cellValueFactory><PropertyValueFactory property="accountAddress" /></cellValueFactory>
</TableColumn>
</columns>
</TableView>
<Button layoutX="542.0" layoutY="263.0" mnemonicParsing="false" onMouseClicked="#importOnClick" prefHeight="35.0" prefWidth="116.0" text="インポート" />
<TableView fx:id="kintoneTable" layoutX="696.0" layoutY="53.0" prefHeight="600.0" prefWidth="485.0">
<columns>
<TableColumn editable="false" prefWidth="75.0" sortable="false" text="レコード番号">
<cellValueFactory><PropertyValueFactory property="レコード番号" /></cellValueFactory>
</TableColumn>
<TableColumn editable="false" prefWidth="150.0" sortable="false" text="担当者名">
<cellValueFactory><PropertyValueFactory property="担当者名" /></cellValueFactory>
</TableColumn>
<TableColumn editable="false" prefWidth="150.0" sortable="false" text="メールアドレス">
<cellValueFactory><PropertyValueFactory property="メールアドレス" /></cellValueFactory>
</TableColumn>
<TableColumn editable="false" prefWidth="150.0" sortable="false" text="会社名">
<cellValueFactory><PropertyValueFactory property="会社名" /></cellValueFactory>
</TableColumn>
<TableColumn editable="false" prefWidth="100.0" sortable="false" text="部署名">
<cellValueFactory><PropertyValueFactory property="部署名" /></cellValueFactory>
</TableColumn>
<TableColumn editable="false" prefWidth="150.0" sortable="false" text="住所">
<cellValueFactory><PropertyValueFactory property="住所" /></cellValueFactory>
</TableColumn>
</columns>
</TableView>
</children>
</AnchorPane>
ウィンドウのサイズを設定します。application/Main.java を開き、Sceneのサイズを変更します。
Scene scene = new Scene(root, 1200, 660);
実装は以上です。
実行
実行構成を作成します。[実行]->[実行構成]を開き、「Javaアプリケーション」を右クリックして「新規」を選択します。
クラスパスタブを開き、CDataのJDBCドライバーを2つ指定し、実行ボタンをクリックします。
実行すると、テーブルビューにSalesforceとkintoneのデータが表示されたウィンドウが立ち上がります。
データ移行したい行を選択して「インポート」ボタンをクリックすると、選択したデータが kintone に登録されます。