→ビジネスプロセス管理 →jBPM関連Tips(タスク編) #contents ※以下のTipsは jBPM Ver.6.0.1(コミュニティ版)で調査したものです *永続化 [#m8bc53fc] -[[BPMS 6 を設定して、外部データベースを使用する方法>https://access.redhat.com/ja/solutions/873873]] *ユーザ関連 [#l44c7b8c] **あるユーザの所属するグループを取得して表示 [#y6ec0d71] private void dispUserGroup(String user) { String callBackProp = System.getProperty("jbpm.usergroup.callback.properties"); System.out.println("callbackProperty=" + callBackProp); UserGroupCallback ugrpCallback = new JBossUserGroupCallbackImpl("classpath:/usergroups.properties"); List<String> grps = ugrpCallback.getGroupsForUser(user, null, null); for(String grp : grps) { System.out.println(grp); } /* こういうやり方もある RuntimeEnvironment env = RuntimeEnvironmentBuilder.Factory.get().newDefaultInMemoryBuilder() .addAsset(ResourceFactory.newClassPathResource("sample.bpmn"), ResourceType.BPMN2).get(); UserGroupCallback ugc = env.getUserGroupCallback(); grps = ugrpCallback.getGroupsForUser(user, null, null); for(String grp : grps) { System.out.println(grp); } */ } **EclipseでjBPMのテストクラスを動かすときのユーザ情報はどこにある? [#h9156fce] -もともと用意されているjohnとかmaryとかkrisvとかのユーザは使えるのに、自分で適当なユーザを使いたくてもエラーになってしまう。 -ドキュメントには users.properties を修正するとか adduser.batを実行するとか言う記述があるが、いずれもWebコンソールの話で、Eclipseでテストを実行するときのユーザ情報にはまったく関係がない。 -Eclipseでテスト実行するときのユーザ情報は、JBPMS を C:\jbpmにインストールした場合、C:\jbpm\runtime\jbpm-test-6.0.1-20140120.jar の中に usergroups.properties というファイルがあり、その中にユーザー情報が直に書かれている。 -このjarの中にある usergroups.properties の代わりに自前のユーザ情報の設定を使いたい場合、このファイルをeclipseで開いてローカルにコピーし、自分の好きなように修正を加えた上で、getResourceメソッドで最初に検索される場所に置いておけば、jarを探す前にそちらにある usergroups.propertiesを読み込んでくれます。 -具体的には、Eclipseでビルド・パスの設定で確認すればよいが、<project>/src/main/java のあたりに置けば良い。 -この情報はドキュメントのどこにも書いていないように見える(見つけられなかった)し、ググってもドキュメントなどの情報は出てこない。みんな困っていないのだろうか? -なお roles.properties の読み込みは以下のクラスで行っている jbpm-human-task-core 内の org.jbpm.services.task.identity.JBossUserGroupCallbackImpl *プロセス関連 [#tb6dc3c4] **プロセス内のノードの一覧を取得 [#pcf3370f] @SuppressWarnings("restriction") private void dispProcNodes(ProcessInstance processInstance) { System.out.println("---"); WorkflowProcessInstanceImpl instance = (WorkflowProcessInstanceImpl) processInstance; for (Node node : instance.getNodeContainer().getNodes()) { //NodeContainer nc = node.getNodeContainer(); //Node[] nods = nc.getNodes(); System.out.println(">>id=[" + node.getId() + "], node.Name=[" + node.getName() + "]"); Map<String,Object> map =node.getMetaData(); for (String key : map.keySet()) { System.out.println(key + " = " + map.get(key)); } } System.out.println("---"); } **プロセスインスタンスのステータス [#n0900a1e] private void dispProcState(ProcessInstance processInstance) { int st =processInstance.getState(); switch(st){ case ProcessInstance.STATE_ACTIVE: System.out.println("st=STATE_ACTIVE"); break; case ProcessInstance.STATE_COMPLETED: System.out.println("st=STATE_COMPLETED"); break; case ProcessInstance.STATE_ABORTED: System.out.println("st=STATE_ABORTED"); break; default: System.out.println("st=" + st); break; } } **プロセス変数設定 [#bcf582b7] -【制約】プロセス変数に独自クラスを使う場合、Serializable を実装しておく必要があります WorkflowProcessInstanceImpl wfpi = (WorkflowProcessInstanceImpl) processInstance; wfpi.setVariable(varName, "xxx"); -また、テストクラスの第二引数をfalseにしておかないと processInstance が disconnectedだという例外になってしまう。 (WorkflowProcessInstance#reconnectというメソッドがあるので、これを呼べばよいのかも?→ダメでした) -永続化をありにしているときは、トランザクション内でないとダメだという。このようにすればよい。 TransactionManager tm = TransactionManagerServices.getTransactionManager(); tm.begin(); WorkflowProcessInstance wfpi = (WorkflowProcessInstance) ksession.getProcessInstance(processinstance.getId()); wfpi.setVariable("user", "abc"); System.out.println("after set: " + wfpi.getVariable("user")); tm.commit(); --[[ソース:How to set process variable ?>https://access.redhat.com/solutions/801833]] --TransactionManagerServicesは[[bitronix>http://docs.codehaus.org/display/BTM/Home]] 関連のクラスである。 --Ver.6では、EnvironmentクラスからTransactionManagerを取得できるので、それを使って上記サンプルと同様にしてやるという手もある。トランザクションをbegin()した後にKieSession#getProcessInstance()でプロセスインスタンスを再取得するのがポイント。commit()の引数は true にする。 --ただし、プロセス変数の変更は completeメソッドでタスク変数のアウトプットを使って行うのが本来のやり方であり、上のやり方は必要のない限り割けるべき --ただし、プロセス変数の変更は completeメソッドでタスク変数のアウトプットを使って行うのが本来のやり方であり、上のやり方は必要のない限り避けるべき -JbpmJUnitBaseTestCaseで直接プロセス変数取得 String val = (String) getVariableValue(varName, processInstance.getId(), ksession); System.out.println("val=" + val); **プロセス変数の列挙(通常のやり方) [#gf4d7e2b] Map<String,Object> vmap = wfpi.getVariables(); for(String s : vmap.keySet()){ System.out.println( s + "=" + vmap.get(s) ); } **VariableScopeを使ってプロセス変数の一覧を取得する [#g0a382b6] ContextableInstance ci = (ContextableInstance) processInstance; VariableScopeInstance vsi = (VariableScopeInstance)ci.getContextInstance(VariableScope.VARIABLE_SCOPE); VariableScope vs = vsi.getVariableScope(); List<Variable> vars = vs.getVariables(); for(int i = 0 ; i < vars.size(); i++ ){ System.out.println(vars.get(i).getName() + "=" + vars.get(i).getValue()); } ** Context<?>の取得 [#o4d29acb] -PerProcessInstance のストラテジで RuntimeManager を作った場合、GetRuntimeEngineにはContext<?>を渡す必要がある。Nullだと例外になる。 -このContext<?>の取得方法 RuntimeManager manager = createRuntimeManager( Strategy.PROCESS_INSTANCE, "sample.bpmn","subpro.bpmn"); RuntimeEngine engine = manager.getRuntimeEngine(ProcessInstanceIdContext.get()); -そもそもこのContext<?>というのは何?かというと、どうもPerProcessInstanceストラテジの際にProcessInstanceとKieSessionをヒモづけるための情報らしい。 --上記でいうと、ProcessInstanceIdContext が Context<?> の派生クラスです。 *セッション関連 [#a507df2a] **デフォルト KieSession と 名前つき KieSession についての解説 [#dc686f34] -http://blog.athico.com/2013/10/configuration-and-convention-based.html **KieSessionの実装 [#xf2579de] -org.drools.core.command.impl.CommandBasedStatefulKnowledgeSession である模様 -implementsの階層は CommandBasedStatefulKnowledgeSession > StatefulKnowledgeSession > KieSession, KnowledgeRuntime, KnowledgeRuntimeEventManager -drools-coreの org.drools.core.common.AbstractWorkingMemory がKieSession の実装かと思ったが、そうではない模様 -implementsをたぐると StatefulSession >WorkingMemory >WorkingMemoryEntryPoint なので違う *Eclipseによる開発 [#k053e34a] -ビジネスルールタスクにタスク変数の設定ができない? --BPMNのPreferenceで ioSpecification、dataInputAssociation、dataOutputAssociationを表示するようにしてやればプロパティ設定画面(タブ)が出てくるようになりますが、デフォルトでは表示されていません。 -Eclipse PluginのProcess Instancesビューの使い方 --EclipseがAdvancedで自動生成した ProcessTestクラスのコンストラクタの2つの引数が両方ともtrueになっているが、第二引数をfalseにしないとProcess Instancesビューは有効にならず、何も表示されない。第二引数をfalseにしたうえで、デバッガで実行中に止め、変数ビューでksessionに行を合わせると初めてProcess Instancesビューに表示される。 --Process Instanceビューは Process InstancesビューからProcessInstanceをダブルクリックすると表示される。 -インストール後のEclipse起動 --普通にEclipseを起動するとjBPMのruntimeのjarがビルド・パスに入らないので、コマンドラインから ant start.eclipse で起動するようにするか、runtimeのjarをビルド・パスに組み込んでしまうのが良いかも --antで起動した場合、 eclipse.preferences.ini の下記の記述が引数として渡されている org.jbpm.eclipse/jBPM.Runtimes=jBPM runtime#./runtime#true#