Salesforce と kintone 間で顧客データを同期する方法として、CDataドライバーを利用したWindowsフォームアプリケーション(C#/ADO.NET)によるものを別記事でご紹介しました。
CDataドライバーは、ADO.NETのみならず様々なテクノロジーで提供されています。今回は、Salesforce と kintone 間で顧客データを同期するアプリケーションの Java による例をご紹介したいと思います。
このアプリケーションの概要は次の通りです。
- JDK 8
- JPA を利用
- JavaFX によるデスクトップアプリケーション
- Eclipse 4.6
- Salesforce および kintone からデータを読み込む
- インポートしたい行を選択して、Salesforce から kintone へデータをインポートする
それでは、このサンプルアプリケーションの開発手順を見ていきます。
ソースコード
このサンプルアプリケーションのソースコードはこちらからどうぞ。
CData製品のインストール
CData Software をインストールします。今回必要になるのは、次の2つです。
開発環境の準備
Eclipse 4.6 を使用します。以下の機能を Eclipse にインストールしておいてください。
- Dali Java 永続化ツール - EclipseLink JPA サポート
- Dali Java 永続化ツール - JPA サポート
- e(fx)clipse - IDE
※ サイトのロケーションは http://download.eclipse.org/releases/neon 、http://download.eclipse.org/efxclipse/updates-released/2.4.0/site を使用
また、[ウィンドウ]->[設定]->[Java永続化]->[JPA]->[エラー/警告] で、[プロジェクト]のセクションを開き、「複数の永続化単位」の設定を「無視」にしておきます。
プロジェクト作成
新規プロジェクトを作成します。JavaFX Project を選択します。
デフォルトのまま順次「次へ」ボタンをクリックしていきます。最後のダイアログでは、「言語」に"FXML"、「Root-Type」に"javax.scene.layout.AnchorPane"、「ファイル名」に"MainPane"、「Controller Name」に"MainPaneController"を指定し、完了ボタンをクリックします。
プロジェクトが作成されたら、プロジェクトを右クリックしてプロパティを開き、プロジェクト・ファセットで「ファセット・フォームへ変換...」をクリックします。プロジェクト・ファセット「JPA」にチェックを入れ、「より詳しい構成が必要...」リンクから次画面へ進みます。
JPAファセットのウィザードで、「ライブラリーをダウンロード...」ボタンをクリックします。
EclipseLink 2.5.2 を選択し、次へボタンをクリックします。
ライセンス受諾チェックを入れ、完了ボタンをクリックします。
これによりワークスペースに EclipseLink がダウンロードされ、ユーザライブラリとして使用可能になります。
[JPA実装]のユーザー・ライブラリで「EclipseLink 2.5.2」を選択し、「注釈付きクラスを自動的に発見」を選択してOKボタンをクリックします。
JDBCドライバーの登録
Eclipse に JDBC ドライバーを登録します。
[ウィンドウ]->[設定]->[データ管理]->[接続]->[ドライバー定義] を開き、追加ボタンをクリックします。
汎用JDBCドライバーを選択し、ドライバー名を "CData Salesforce Driver" とします。
「Jarリスト」タブを開きjarファイルを指定します。CData製品のインストール先/lib/cdata.jdbc.salesforce.jar を選択します。
次に「プロパティー」タブを開き、ドライバークラスと接続URLを設定します。それぞれ以下の値を設定します。
- ドライバークラス:cdata.jdbc.salesforce.SalesforceDriver
- 接続 URL:jdbc:salesforce:User=<ユーザ名>;Password=<パスワード>;Security Token=<セキュリティトークン>;
kintone のドライバーも同様に登録します。ドライバークラス名や接続URLについては、マニュアルに記載があります。
データベース接続の作成
先程登録したJDBCドライバーを使用して、データベース接続を作成します。
ビュー「データ・ソース・エクスプローラ」を開きます。データベース接続を右クリックして「新規」を選択します。
接続プロファイル・タイプで汎用JDBCを選択し、名前を "CData Salesforce JDBC" とし、次へボタンをクリックします。
ドライバーは、先程作成した CData Salesforce Driver を選択します。
「データベース」はここではSAMPLEのままでかまいません。「ユーザー名」にユーザ名を入力し、完了ボタンをクリックします。
同様にして、kintone のデータベース接続も作成します。
エンティティクラスの生成
Eclipse の機能を使用して、テーブル情報からエンティティクラスを生成します。
プロジェクトのプロパティからJPAを開き、接続に "CData Salesforce JDBC" を指定し、「接続からデフォルト・カタログを上書き」「接続からデフォルト・スキーマをオーバーライド」にチェックを入れ、それぞれ "CData" と "Salesforce" を選択してOKボタンをクリックします。
次にプロジェクトを右クリック->新規で「その他」を選択し、[JPA]->[テーブルから JPAエンティティー]を選択して次へボタンをクリックします。
カスタム・エンティティーの生成ダイアログが開くので、「接続」で "CData Salesforce JDBC"、「スキーマ」で "Salesforce" を選択します。すると「テーブル」に Salesforce のオブジェクトの一覧が表示されます。
「Account」にチェックを入れ、次へボタンをクリックします。
※なおここで時間がかかる場合がありますが、そのまま待っていれば次の画面が表示されます。
「クラス名」が "Account" になっていることを確認し、完了ボタンをクリックします。
これで Account(取引先) のエンティティクラスが生成されました。
同様にして Contact(取引先責任者) のエンティティクラスも生成します。
kintone の顧客リストのエンティティクラスも同様に作成しますが、プロジェクトのJPAプロパティで接続、カタログ、スキーマを kintone のものに設定してから実施します。
kintone の顧客リストのエンティティクラスも同様に作成します。
ここまでで3つのエンティティクラスが作成されました。
プロジェクトのJPAプロパティの接続等を未設定に戻しておきます。
永続化ユニットの定義
META-INF/persistence.xml を開き、以下を記述します。<Salesforceの接続URL> と <kintoneの接続URL> にはそれぞれJDBCドライバーの登録時に設定したものを指定します。
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="salesforce" transaction-type="RESOURCE_LOCAL">
<class>application.Contact</class>
<class>application.Account</class>
<properties>
<property name="eclipselink.jdbc.native-sql" value="true"/>
<property name="javax.persistence.jdbc.url" value="<Salesforceの接続URL>"/>
<property name="javax.persistence.jdbc.driver" value="cdata.jdbc.salesforce.SalesforceDriver"/>
</properties>
</persistence-unit>
<persistence-unit name="kintone" transaction-type="RESOURCE_LOCAL">
<class>application.顧客リスト</class>
<properties>
<property name="eclipselink.jdbc.native-sql" value="true"/>
<property name="javax.persistence.jdbc.url" value="<kintoneの接続URL>"/>
<property name="javax.persistence.jdbc.driver" value="cdata.jdbc.kintone.KintoneDriver"/>
</properties>
</persistence-unit>
</persistence>
処理の実装
エンティティクラス Contact の修正
Salesforce 側はContact(取引先責任者)が処理対象のオブジェクトですが、一部の項目はAccount(取引先)から取得したいものがあるため、Contactクラスを修正してAccountの項目を取得できるようにします。以下のコードを追加します。
@JoinColumn(name="AccountId", referencedColumnName="Id")
private Account account;
public String getAccountName() {
if (account == null) {
return "";
}
return account.getName();
}
public String getAccountAddress() {
if (account == null) {
return "";
}
return account.getBillingState() + account.getBillingCity() + account.getBillingStreet();
}
public String getAccountBillingPostalCode() {
if (account == null) {
return "";
}
return account.getBillingPostalCode();
}
MainPaneControllerの初期化
application/MainPaneController.java を開きます。空の実装になっているので、以下の初期化コードを入れます。
※適宜import文を追加します。
public class MainPaneController implements Initializable {
@FXML
private TableView<Contact> salesforceTable;
@FXML
private TableView<顧客リスト> kintoneTable;
@Override
public void initialize(URL location, ResourceBundle resources) {
salesforceTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
kintoneTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
EntityManager em = Persistence.createEntityManagerFactory("kintone").createEntityManager();
kintoneTable.getItems().addAll(em.createNamedQuery("顧客リスト.findAll", 顧客リスト.class).getResultList());
em = Persistence.createEntityManagerFactory("salesforce").createEntityManager();
salesforceTable.getItems().addAll(em.createNamedQuery("Contact.findAll", Contact.class).getResultList());
}
}
インポート処理
インポート処理を実装します。以下のメソッドを追加します。
@FXML
private void importOnClick(MouseEvent event) {
EntityManager em = Persistence.createEntityManagerFactory("kintone").createEntityManager();
em.getTransaction().begin();
for (Contact contact : salesforceTable.getSelectionModel().getSelectedItems()) {
顧客リスト kintoneItem = kintoneTable.getItems().stream()
.filter(o -> o.getメールアドレス().equals(contact.getEmail()))
.findFirst()
.orElse(new 顧客リスト());
kintoneItem.setメールアドレス(contact.getEmail());
kintoneItem.set会社名(contact.getAccountName());
kintoneItem.set住所(contact.getAccountAddress());
kintoneItem.set担当者名(contact.getName());
kintoneItem.set部署名(Optional.ofNullable(contact.getDepartment()).orElse(""));
kintoneItem.set郵便番号_数字のみ_(Optional.ofNullable(contact.getAccountBillingPostalCode()).orElse(""));
kintoneItem.setTel_数字のみ_(contact.getPhone());
kintoneItem.setFax_数字のみ_(contact.getFax());
kintoneItem.set備考("");
kintoneItem.set経度("");
kintoneItem.set緯度("");
if (kintoneItem.getRecordId() == 0) {
em.persist(kintoneItem);
}
}
em.getTransaction().commit();
kintoneTable.getItems().clear();
kintoneTable.getItems().addAll(em.createNamedQuery("顧客リスト.findAll", 顧客リスト.class).getResultList());
}
c#版と同じく、メールアドレスをキーとして、Salesforce側のデータをkintone側に設定しています。
CDataドライバーを使用することにより、Salesforceおよびkintoneのデータをデータベーステーブルとして扱えるようになるため、このようにJPAを通した管理を行うこともできます。
画面の作成
最後に画面を作成します。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 に登録されます。