前回までの内容で、iDempiere(JPiere)の動作環境の構築および開発環境が整いました。
今回から、iDempiere(JPiere)に搭載している機能を用いて動作確認や機能追加カスタマイズ(実装)していきます。
今回はProcess機能に焦点をあて、独自のProcess機能を実装してみたので、その実装手順と検証内容を紹介したいと思います。
iDempiere(JPiere)のProcess機能の種類
Process機能はSOAP通信もしくはRESTful APIを使用して外部システムから実行することができます。
また、画面のメニューに登録することによりWAS経由で画面から実行することもできます。
今回は、SOAP通信を使用して外部システムから起動するというシナリオを想定し、ProcessおよびWebService連携について焦点をあてます。
実装するProcess機能
今回実装するProcess機能は、2つの引数を受け取り(値はデバッグ画面に表示)処理結果のメッセージを返却するというシンプルな処理です。
実装はJava言を使用し、iDempiereでの画面設定をへて、SOAP通信によりプロセスを実行します。
なお、Process機能の動作確認するため、SoapUIオープンソース版を使用します。
実装から動作確認までの手順
実装後のソース構成
これから順番に実装内容を紹介しますが、以下の手順でソースコードを追加した結果、以下のファイル構成になります。
参考ページ
以下の技術文書を参考にさせていただきました。
Process機能の実装
それでは、Process機能を実装していきます。
まずは、Process機能をEclipseのプラグインウィザード(Plug-in Project)から実装していきます。
Plug-in Projectの追加
ProjectExplorerから新規作成を選択し、プラグインウィザード(Plug-in Project)をクリックします。
org.idempierefan.plugin.processを追加します。
また、ソースコードを配置するLocationを指定します。併せてOSGIフレームワークも有効にします。
Java11が選択されていることを確認し、Finishボタンにより登録します。
Overview画面が表示されれば、Plug-in Projectの追加は完了です。
※ MANIFEST.MFファイルの内容
つづいて、org.idempierefan.plugin.processの設定を行います。
Plug-inに関連するパッケージの追加
Dependenciesタブをクリックし、Addボタンから、org.adempiere.base
を追加します。
つづいて、Run Configurationsにorg.idempierefan.plugin.processを追加します。
server.productをひらき、Plug-insタブ
からorg.idempierefan.plugin.process
のチェックボックスをONにします。
ここまでで、初期のPlug-inの設定は完了です。
それでは、Process機能の実装にはいります。
Process機能ソースコード実装
Process本体の実装とProcess機能を提供するFactoryの実装を行います。
Process本体の実装手順
最初にProcess機能本体のパッケージを追加します。
Nameにorg.idempierefan.plugin.process
を入力します。
つづいて、本体のクラスを追加します。
ここで指定するクラス名は、画面から起動する際に設定するプロセスの指定クラス名になります。
CalcProcess
という名称にします。
※ 追加したクラスの初期状態
package org.idempierefan.plugin.process;
public class CalcProcess {
}
具体的な実装を行います。
CalcProcessは、SvrProcessを拡張する形で実装します。
基本的には、prepareおよびdoIt関数内にコードを記述していきます。
prepare関数:引数を受け取る処理を記述
doIt関数:業務ロジックの処理を記述
※ 実装途中の状態
package org.idempierefan.plugin.process;
import org.compiere.process.SvrProcess;
public class CalcProcess extends SvrProcess {
@Override
protected void prepare() {
// TODO Auto-generated method stub
}
@Override
protected String doIt() throws Exception {
// TODO Auto-generated method stub
return null;
}
}
CalcProcessクラスの実装結果
prepare()
関数でargValue1
およびargValue2
のパラメータをクラスメンバ変数に格納します。
doIt()
関数で、値が受け取れたことをデバッグ表示し、Post values SUCCESS!
を返却します。
SOAP通信のレスポンスにPost values SUCCESS!
がセットされます。
package org.idempierefan.plugin.process;
import org.compiere.process.ProcessInfoParameter;
import org.compiere.process.SvrProcess;
public class CalcProcess extends SvrProcess {
private String value1;
private String value2;
@Override
protected void prepare() {
log.warning("[x] prepare method.");
ProcessInfoParameter[] params = getParameter();
for (ProcessInfoParameter p : params) {
String paramName = p.getParameterName();
if (paramName.equalsIgnoreCase("argvalue1")) {
value1 = p.getParameterAsString();
log.warning(" [-] Found argValue1 Parameter.");
} else if (paramName.equalsIgnoreCase("argvalue2")) {
value2 = p.getParameterAsString();
log.warning(" [-] Found argValue2 Parameter.");
}
// TODO : Error handling for unexpected parameters.
}
}
@Override
protected String doIt() throws Exception {
log.warning("[x] doIt method.");
log.warning(value1 != null ? " [-] argValue1: " + value1 : "argValue1 NULL");
log.warning(value2 != null ? " [-] argValue2: " + value2 : "argValue2 NULL");
return "Post values SUCCESS!";
}
}
Process機能Factoryソースコード実装
つづいて、Process機能のFactoryを実装します。
上記CalcProcessクラスとは別のパッケージを用意します。
- パッケージ名:org.idempierefan.plugin.processfactory
- FactoryClass:ProcessFactoryImpl
なお、今回実装するFactoryクラスは、AnnotationBasedProcessFactoryを拡張します。
基本的には、getPackages関数内にコードを記述していきます。
@Component
アノテーションも対象のインターフェースクラスおよび優先順を技術文書通りに付与します。
getPackages関数:Processクラスのパッケージ名を記述
ProcessFactoryクラスの実装結果
package org.idempierefan.plugin.processfactory;
import org.adempiere.base.AnnotationBasedProcessFactory;
import org.adempiere.base.IProcessFactory;
import org.osgi.service.component.annotations.Component;
@Component(immediate = true, service = IProcessFactory.class, property = {"service.ranking:Integer=0"})
public class ProcessFactoryImpl extends AnnotationBasedProcessFactory {
public ProcessFactoryImpl() {
}
@Override
protected String[] getPackages() {
return new String[] {"org.idempierefan.plugin.process"};
}
}
ProcessFactoryクラスのOSGIコンポーネット定義の作成
実装したProcessのインスタンスがプロセスとして認識できるようにFactoryを実装します。
META-INFと同じ階層に、OSGI-INFフォルダを作成します。
フォルダを作成したら、org.idempierefan.plugin.processfactory.ProcessFactoryImpl.xmlファイルをComponent Definitionにより追加し、定義情報を記述します。
org.idempierefan.plugin.processfactory.ProcessFactoryImpl.xml定義
以下の内容を、Source
タブを開いて貼り付けます。
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.idempierefan.plugin.processfactory.ProcessFactoryImpl">
<property name="service.ranking" type="Integer" value="0"/>
<service>
<provide interface="org.adempiere.base.IProcessFactory"/>
</service>
<implementation class="org.idempierefan.plugin.processfactory.ProcessFactoryImpl"/>
</scr:component>
フォルダ構成 ※ 再掲載
上記手順により、Process本体およびFactoryのコードを記述した結果、以下の状態になっていると思います。
OSGI-INFフォルダビルド対象追加
OSGI-INFフォルダをビルド対象に追加します。
MANIFEST.MFファイルを開き、Buildタブ内の設定でOSGI-INF
のチェックをONにします。
ソースコードおよび定義ファイルの追加は以上です。
ここまで追加したソースコードが正しく動作するか、iDempiereのサービスを起動します。
EclipseからRun Configurations
を開き、Runボタンによりサービスを起動します。
iDempiere画面からのプロセス機能の定義
続いて、iDempiereの画面からProcessとして上記のCalcProcessパッケージを認識させます。
ログイン
Process機能を登録する場合は、Admin権限でiDempiereにログインします。
https://localhost:8443/webui
にてメインページを開きます。
Select Roleを有効にします。
EMail:superuser@oss-erp.co.jp
Password:System
Tenant:System
Role:System Administrator
Process機能CalcProcessの登録
メニュー左側からReport & Process
をクリックします。
新規アイコンをクリックし、Process登録画面を表示します。
以下の各項目を入力します。
Search Key:CalcProcess
Name:CalcProcess
Description:CalcProcess
Data Access Level:All
Classname:org.idempierefan.plugin.process.CalcProcess
Classnameは、実装したソースコード名に合わせて入力します。
入力したら画面上部の保存ボタンをクリックします。
続いて、CalcProcessのパラメータを登録します。
CalcProcessの引数の登録
画面下にあるParameter
タブから引数を2つ登録します。
こちらは、上記ソースコードで実装した文字列を指定します。
なお、ここで指定する項目名称は、SOAP通信時のリクエストに含めます。項目名称と大文字小文字を区別するので注意します。
型はStringを指定します。
1項目目:argValue1
2項目目:argValue2
追加したら、表の上部にある保存ボタンをクリックします。
以上で、追加したパッケージおよびプロセスがもつ引数について定義が完了しました。
iDempiere画面からのWebサービスセキュリティの設定
つづいて、SOAPリクエストからこのProcessを実行するためWebServiceのセキュリティ設定を行います。
Webサービスセキュリティの設定は、GardenWorld Admin
ロールを使用して設定を行います。
ログイン
EMail:superuser@oss-erp.co.jp
Password:System
Tenant:GardenWorld
Role:GardenWorld Admin
Web Service Securityの設定
- ログイン後、画面上部からWeb Service Security設定を検索します。
色々な機能や画面を検索する場合が多い方は、まずはロケール英語でログインして操作することをお勧めします。
-
新規ボタンを押し、それぞれ設定項目を入力します。
CalcProcessを呼び出す名称はWebServiceCalcProcess
とします。
Web Serviceには、Model Oriented Web Servicesを有効にし、Run Processを選択します。
なお、ここで指定した名称を、後続の動作確認時のSOAPリクエストに指定します。
Search Key:WebServiceCalcProcess
Name:WebServiceCalcProcess
Web Service:Model Oriented Web Services
Web Service Method:Model Oriented Web Services_Run Process
-
つづいて、パラメータ(Web Service Parameters)を指定します。
ここでは、iDempiereの内部で定義されている情報を明示的に登録します。※ CalcProcessの引数とは別の定義です。
Create Default Parameter
ボタンをクリックします。
クリックすると、画面下部のリストに3項目表示されます。
ParameterTypeを全てFree
にします。
登録後、保存ボタンをクリックします。
これらのパラメータは画面上では特に値を指定しませんが、iDempiereの仕様上必ずこの3種類をFreeとして定義します。
定義が無い場合や、Free以外の設定がされている場合、SOAPからのプロセス実行のリクエストが失敗します。
- つづいて、アクセス権限(Web Service Access)にRole情報を設定します。
となりのタブにWeb Service Access
があります。こちらをクリックします。
なお、ここで指定したRole情報をSOAPリクエストに数値として指定します。
ここまで、設定ができたらiDempiereサービスを再起動します。
Eclipseに戻りサービスを停止します。
再度、RunメニューのRun Configurations
から実行します。
SOAP経由でリクエストを受信する設定は以上です。
SOAPリクエストの準備
SoapUIというツールを使用して、SOAPデータをiDempiereサービスにリクエストを送信します。
SOAP通信なので、wslを最初に認識させます。その後、プロセス実行に必要な引数を指定していきます。
-
WSL情報を読み込みます。
Initial WSDLにhttp://localhost:8080/ADInterface/services/ModelADService?wsdl
を指定します。
-
CalcProcessへアクセスする情報を指定します。
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:_0="http://idempiere.org/ADInterface/1_0">
<soapenv:Header/>
<soapenv:Body>
<_0:runProcess>
<_0:ModelRunProcessRequest>
<!-- AD_Process_IDにCalcProcessのProcessコードを指定する -->
<_0:ModelRunProcess AD_Process_ID="1000352">
<!-- WebServiceCalcProcessを指定する-->
<_0:serviceType>WebServiceCalcProcess</_0:serviceType>
<_0:ParamValues>
<!-- argValue1に値を指定する -->
<_0:field column="argValue1" >
<_0:val>123</_0:val>
</_0:field>
<!-- argValu2に値を指定する -->
<_0:field column="argValue2" >
<_0:val>456</_0:val>
</_0:field>
</_0:ParamValues>
</_0:ModelRunProcess>
<_0:ADLoginRequest>
<!-- 以下に接続情報を指定する -->
<_0:user>superuser@oss-erp.co.jp</_0:user>
<_0:pass>System</_0:pass>
<_0:lang>en_US</_0:lang>
<!-- GardenWorld -->
<_0:ClientID>11</_0:ClientID>
<!-- GardenWorld Admin -->
<_0:RoleID>102</_0:RoleID>
<!-- GardenWorld HQ! -->
<_0:OrgID>11</_0:OrgID>
<!-- HQ Warehouse -->
<_0:WarehouseID>103</_0:WarehouseID>
<_0:stage>0</_0:stage>
</_0:ADLoginRequest>
</_0:ModelRunProcessRequest>
</_0:runProcess>
</soapenv:Body>
</soapenv:Envelope>
上記でリクエスト送信の準備は完了です。
動作確認
動作確認は、上記SOAPリクエストをSoapUIから送信します。
左側の三角ボタンをクリックするとリクエストが送信されます。
画面右側にレスポンスが表示されます。
Summary項目に、ソースコードで指定した文字列が返却されることが確認できます。
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns1:runProcessResponse xmlns:ns1="http://idempiere.org/ADInterface/1_0">
<RunProcessResponse IsError="false" xmlns="http://idempiere.org/ADInterface/1_0">
<Error>Post values SUCCESS!</Error>
<Summary>Post values SUCCESS!</Summary>
<LogInfo/>
</RunProcessResponse>
</ns1:runProcessResponse>
</soap:Body>
</soap:Envelope>
また、Eclipseのコンソールウィンドウからもデバッグ情報としてパラメータが受け取れたことが確認できます。
実装と動作確認は以上です。
残課題
- レスポンスの形式検証
今回は、doIt関数から文字列を返却するというシンプルなレスポンス形式です。
実運用では複雑なレスポンスなど想定されますが、こちらは別途検証が必要だと思われます。 - PCalcProcess内からのデータベースや他インスタンスへのアクセス
受っとった文字列をキーにして、データベースと連動できるような機能も有用かなと思われますが、DBアクセスなどは今回は検証しておりません。
次回は
今回はSOAP経由でCalcProcessを呼び出し実行しました。
このProcessは、画面からのボタンと連動することもできます。
次回は、画面のメニューにボタンを配置して実行する内容を紹介したいと思います。