2015-05-24

Olingo + Lightning ConnectでODataに触れてみた

SalesforceのSummer15のリリースでLightning Connectが利用できるようになったようなので

ODataの勉強がてら触ってみましたー。

 

Lightning Connectは任意のOData Providerが提供するODataサービスを使って

Salesforceから外部データをCRUDできますよーっていう機能。

OData自体はインターフェースが仕様に準拠していれば裏はなんでもOKっていう

HTTP版ODBC的なプロトコルです。

ODataに関しては以下のリンクが詳しいです。

OData って何?

 

SFDCでのLightning Connectの設定に関しては以下のリンクが詳しいです。

Lightning Connectを手軽に試してみる « TerraSky Tech Blog

Salesforce連携のためのOData入門

 

今回は自前でOData Providerを作って、それに対してSFDCから接続してみます。

以下のリンクが自前でクライアント、サーバ側を構築する際のライブラリになります。

Libraries · OData - the Best Way to REST

今回はJavaのApache Olingo Libraryを使ってサンプルをベースにOData Providerを作っていきます。

※ちなみにOData全然知らないので解説で所々間違いが有ると思いますのでご注意を!

0. 準備

JDKとかmavenとかインストールしておきます。

1. サンプルのmavenプロジェクトを作成

SFDCでは現時点(2015/05/15)ではOData v2.0にしか対応していないので

v2.0のチュートリアルに従って進めていきます。

まず、Sample Project Setupに従って以下のmvnコマンドを実行します。

mvn archetype:generate \
  -DinteractiveMode=false \
  -Dversion=1.0.0-SNAPSHOT \
  -DgroupId=com.sample \
  -DartifactId=my-car-service \
  -DarchetypeGroupId=org.apache.olingo \
  -DarchetypeArtifactId=olingo-odata2-sample-cars-service-archetype \
  -DarchetypeVersion=RELEASE

プロジェクトがいい感じに作成されたら、ビルドします。

cd my-car-service
mvn clean install

そうするといい感じにtarget内にwarが出来上がるので

このwarをtomcatとかのwebのルートにデプロイすればセルフなOData Providerが動きます。

 

herokuでwarを動かしたい場合はpom.xmlのpluginにwebapp-runnerを追加して、Procfileに

web: java $JAVA_OPTS -jar target/dependency/webapp-runner.jar --port $PORT target/*.war

と書いてpushすればOK。herokuでwar動かす時の詳細は以下を参照。

https://devcenter.heroku.com/articles/java-webapp-runner

2. サンプルの説明

ソースを見ると4つクラスがあり、それぞれ以下のような役割を持っています。

CarDataStore.java : データストアのクラス(必須ではないけど、役割的に分けている)

CarEdmProvider.java : Entity Data Model Providerでメタデータ表示したり管理したり

CarODataSingleProcessor.java : データ読み書きを管理する。

CarServiceFactory.java : サービスファクトリ。ここからサービスが起動する。

CarEdmProvider.java

OData Providerではクライアントが適切にサービスを利用できるように

フィードを取得できるURIやエンティティのプロパティやリレーション等の

スキーマ定義などを外部に公開します。

それらの情報を定義するクラスがEdmProviderになります。

スキーマの例は以下のリンクで見ることが出来ます。

http://services.odata.org/V2/OData/OData.svc/

http://services.odata.org/V2/OData/OData.svc/$metadata

 

これらのXML(ODataではCSDLと呼びます)をJavaでゴリゴリ書いていく感じです。

CSDLに関する詳細仕様は以下を参照ください。(何故かversion2のドキュメントが無かった…)

http://www.odata.org/documentation/odata-version-3-0/common-schema-definition-language-csdl/

 

サンプルのCarEdmProviderではEdmProviderを継承しており、

EdmProviderの各メソッドをオーバーライドしています。

それぞれのメソッドは以下のような役割を持ちます。

 

getSchemas → スキーマ全体の定義

getEntityType → 個々のエンティティに関するスキーマを定義します。

getComplexType → 複合項目(プリミティブのセット)の定義をします。

getAssociation → エンティティのリレーションを定義します。

getEntitySet → エンティティの集合の定義をします。

getAssociationSet → リレーションのセットを定義します。

getFunctionImport → 抽出用の関数を定義します。ストアドプロシージャみたいな感じです。

getEntityContainerInfo → EntitySetとAssociationSetを定義します。

CarODataSingleProcessor.java

読み書きに関するオペレーションの定義を行います。

ODataSingleProcessorクラスを継承しており、各メソッドをオーバーライドしています。

サンプルでは以下のメソッドをオーバーライドしており、それぞれ以下の役割を持ちます。

 

readEntitySet → 複数フィードのエンティティの読み取り

readEntity → 単数フィードのエンティティの読み取り

CarServiceFactory.java

OData serviceのファクトリクラスです。

サンプルの{ROOT}/WEB-INF/web.xml内に

...
  <servlet>
    <servlet-name>CarServiceServlet</servlet-name>
    <servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class>
    <init-param>
      <param-name>javax.ws.rs.Application</param-name>
      <param-value>org.apache.olingo.odata2.core.rest.app.ODataApplication</param-value>
    </init-param>
    <init-param>
      <param-name>org.apache.olingo.odata2.service.factory</param-name>
      <param-value>com.sample.CarServiceFactory</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>CarServiceServlet</servlet-name>
    <url-pattern>/CarService.svc/*</url-pattern>
  </servlet-mapping>
...

という記述があり、CXFNonSpringJaxrsServletにODataApplicationとCarServiceFactoryを

パラメータとして渡して、サーブレットをマッピングすることで

OData ProviderとしてWebアプリケーションを起動させています。

CarServiceFactoryはODataServiceFactoryクラスを継承しており

createServiceメソッドで上記のEdmProviderとODataSingleProcessorを

パラメータとしてcreateODataSingleProcessorServiceを実行しています。

3. Lightning Connectとの連携

今回はherokuにOData Providerを立ててみたので、それをエンドポイントとして設定していきます。

LC_create_external_datasource

 

あとは同期するとこんな感じで外部オブジェクトが作成されます。

LC_external_object

サンプルのソースだとCars-Manufacturers間のリレーションが張られないので

手動でManufacturerIdを外部参照にします。

 

LC_external_key_setting

そうするといい感じに参照が張られます。

LC_car_record

その他

今回のサンプルではXMLをJavaで書くようなゴリゴリ系でしたが

アノテーションを使ってJava Beansで書くような方法もあります。

https://olingo.apache.org/doc/odata2/tutorials/AnnotationProcessorExtension.html

 

また、CarDataStore.javaでは静的にデータを返してますが、

実際にはこの部分をDBから動的にデータを返却するようにします。

あと、実用には認証機構も必要ですかねー。

このエントリーをはてなブックマークに追加