python調用Java代碼,完畢JBPM工作流程application

來源:互聯網
上載者:User

標籤:地址   sig   test   整合   內部類   notify   --   led   this   

1.緣由

有一龐大Python django webproject,要引入工作流程引擎,像OA一樣。方便的流程式控制制與管理。Python或django關於工作流程的開源外掛程式,稀少,並且弱爆了,終於選用java的開源架構JBPM。為了使Pythonproject整合Java架構,嘗試過jbpm-console提供的 REST, 以失敗告終,終於選用Python 直接調用Java代碼。操作JBPM.


1.1pythonprojectREST與JBPM Workbench互動 失敗

REST URL格式

http://host:8080/jbpm-console/rest/runtime/{deploymentId}/process/{processDefId}/start

比如

http://localhost:8080/jbpm-console/rest/runtime/com.fun:test:1.0.0/process/test.TaskData/start
並不是如文檔所言以 /runtime 打頭。REST介面是jbpm-console.war子項目提供的,必須部署此項目。

失敗原因:流程複雜而且須要處理複雜資料,JBPM內部能夠建立資料模型,使用POJO傳遞或儲存複雜資料,可是REST介面無法POST某種格式的資料。使jbpm-console自己主動映射成POJO,假設自己寫java代碼實現REST 資料轉POJO,可行度再說,既然都自己寫Java代碼了。就不是必需走REST,網路慢。不如直接Java代碼完畢JBPM邏輯。

比如:JBPM建立了一個資料模型Person,形如

public class Person{        String name = null;        int age = 0;        boolean isMan= false;}
REST介面沒法POST資料,使JBPM能映射成一個Person類的執行個體,預設jbpm-console會當作三個零散變數(參數)處理,不會當一個對象的三個屬性。所以預設會在資料庫裡variableinstancelog表存入三行記錄,每行代表一個變數。達不到期望結果。僅僅有一條記錄,僅僅存一個對象的序列化資訊。

假設某大神知道怎樣POST資料(或Python簡單處理POST資料後再發請求),jbpm-console能自己主動映射成POJO。請留言。銘謝!


2.Python 直接調用 Java

2.1 jPype 不採用

  • 坑(能夠人為避免)
    • 當Java方法或屬性是Pythonkeyword時,無法訪問
    • 無法訪問不在包以下(default包)的Java代碼
  • 缺點

    • 適合Python26。實測27版本號碼啟動jvm失敗

    • Java特殊方法不支援,如java.lang.Class.forName(String classname),硬傷(由於此方法在架構/容器代碼中十分頻繁)

    • 無法執行個體化匿名內部類。僅能執行個體化靜態內部類

    • 線程同步:明白支援synchronized類同步,notify, notifyAll, wait等未提及怎樣處理

    • 明白表示有較大效能影響:can impose rather large performance bottlenecks

2.2 pyjnius  採用

  • 長處

    • 封裝出色。文檔未提及也未發現有特殊Java文法或進階機制限制(明白支援重載)

    • 大量運用於Python自己主動化測試安卓應用,與Java語言親和度更高

    • 支援Python繼承/實現java的抽象類別/介面(介面中靜態成員不被支援)

    • 提供一個近乎萬能的autoclass。反射出一個Java類的代理(能在Python層面實現Java的代理類)

  • 缺點

    • windows安裝十分困難,無先行編譯版本號碼,預計必須GCC(MinGW, vs08, vs10均失敗)

3.python<-->java se <-->jbpm <-->hibernate<-->mysql原理簡述

  • use pyjnius connect python and java

  • java se code uses CLASSPATH include jbpm jars and hibernate jars(must do before import pyjnius)

  • jbpm uses hibernate in two step

    • jbpm uses jBPM.proporties to setup and register DataSource in specified db(we specify mysql)

    • jbpm calls hibernate to operate db, but hard code to act like use H2 db, we force hibernate act like use mysql by passing custom params when create it‘s entiy manager(more details in code)

  • hibernate operates db, I have find a way to directly control it‘s behavior completely, transparently

  • Codes speak louder. More details in example.



4. 附Python和Java代碼

完整project代碼地址http://download.csdn.net/detail/secretx/7814991


3.1Python代碼

#coding=utf8import osjavapath = "/home/luodh/workspace/jbpm-6.0.0.Final-bin/*:/home/luodh/workspace/jbpm-6.0.0.Final-bin/lib/*"os.environ[‘CLASSPATH‘] = javapath"""call java code directly"""from jnius import autoclassProcessMain = autoclass(‘com.sample.ProcessMain‘)  #.號分隔ProcessMain.pythonCallMeStatic()     #ok,    before ProcessMain(), can call java static method# ProcessMain.pythonCallMeInstance() #error, before ProcessMain(), can not call java instance methodprocess_main = ProcessMain()process_main.pythonCallMeInstance()process_main.pythonCallMeStatic()ProcessMain.pythonCallMeStatic()ProcessMain.pythonCallMeInstance()  # after ProcessMain(), python does not distinguish static/instance methodprint "-----------------------------------------""""use a python proxy class"""from jnius import JavaClass, MetaJavaClass, JavaMethod, JavaField class PythonProxyJavaClass(JavaClass):    __javaclass__ = "com/sample/ProcessMain"  # /分隔.    __metaclass__ = MetaJavaClass  # must be this#     __javaconstructor__ = (  # 建構函式,源於反編譯#         "()V",#     )# 建構函式規則尚未確定,文檔有誤    pythonCallMeStatic = JavaMethod("()V", static=True)    pythonCallMeInstance = JavaMethod("()V")    s1 = JavaField("Ljava/lang/String;", static=True)    s2 = JavaField("Ljava/lang/String;") PythonProxyJavaClass.pythonCallMeStatic()# PythonProxyJavaClass.pythonCallMeInstance() # 執行個體化對象之前,不可調用執行個體方法 PythonProxyJavaClass().pythonCallMeStatic() # 執行個體化對象之後,python不區分靜態(類)方法和非靜態(執行個體)方法PythonProxyJavaClass().pythonCallMeInstance() PythonProxyJavaClass.pythonCallMeStatic()PythonProxyJavaClass.pythonCallMeInstance() """python嚴格區分靜態/非靜態Field"""print PythonProxyJavaClass.s1# print PythonProxyJavaClass.s2  # error, 類不與成員變數綁定print PythonProxyJavaClass().s1  # none,執行個體不與靜態變數綁定print PythonProxyJavaClass().s2

3.2 Java代碼(jbpm相關)

package com.sample;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Properties;import javax.persistence.EntityManagerFactory;import javax.persistence.Persistence;import org.jbpm.test.JBPMHelper;import org.kie.api.KieBase;import org.kie.api.KieServices;import org.kie.api.runtime.KieContainer;import org.kie.api.runtime.KieSession;import org.kie.api.runtime.manager.RuntimeEngine;import org.kie.api.runtime.manager.RuntimeEnvironmentBuilder;import org.kie.api.runtime.manager.RuntimeManager;import org.kie.api.runtime.manager.RuntimeManagerFactory;import org.kie.api.task.TaskService;import org.kie.api.task.model.TaskSummary;public class ProcessMain {public static String s1 = "I‘m static field";public String s2 = "I‘m instance field";public static RuntimeManager manager = null;public static void main(String[] args) {callJBPM(false);System.exit(0);}public void pythonCallMeInstance(){callJBPM(true);}public static void pythonCallMeStatic(){callJBPM(true);}public static void callJBPM(boolean fake){if (fake){System.out.println("I‘m java, python call me to play jbpm. I don‘t know how to include jbpm jars.");return;}KieServices ks = KieServices.Factory.get();KieContainer kContainer = ks.getKieClasspathContainer();//載入kmodule.xmlKieBase kbase = kContainer.getKieBase("kbase");// 依據暴露的名字(kbase標籤的name屬性)擷取知識庫對象if(manager == null) {manager = createRuntimeManager(kbase);// use synchronized static block}RuntimeEngine engine = manager.getRuntimeEngine(null);KieSession ksession = engine.getKieSession();TaskService taskService = engine.getTaskService();// engine一共3介面 getAuditLogServiceksession.startProcess("com.sample.bpmn.hello");// let john execute Task 1List<TaskSummary> list = taskService.getTasksAssignedAsPotentialOwner("john", "en-UK");TaskSummary task = list.get(0);System.out.println("John is executing task " + task.getName());taskService.start(task.getId(), "john");taskService.complete(task.getId(), "john", null);// let mary execute Task 2list = taskService.getTasksAssignedAsPotentialOwner("mary", "en-UK");task = list.get(0);System.out.println("Mary is executing task " + task.getName());taskService.start(task.getId(), "mary");taskService.complete(task.getId(), "mary", null);manager.disposeRuntimeEngine(engine);//System.exit(0);}private static RuntimeManager createRuntimeManager(KieBase kbase) {//因為要擷取task,須要TaskService進行入庫操作,需提前啟動資料庫,準備資料來源//JBPMHelper.startH2Server();//不用h2,則不啟動JBPMHelper.setupDataSource();Map<String, String> map = configHibernate();EntityManagerFactory emf = Persistence.createEntityManagerFactory("org.jbpm.persistence.jpa", map);RuntimeEnvironmentBuilder builder = RuntimeEnvironmentBuilder.Factory.get().newDefaultBuilder().entityManagerFactory(emf).knowledgeBase(kbase);return RuntimeManagerFactory.Factory.get().newSingletonRuntimeManager(builder.get(), "com.sample:example:1.0");//any_non_blank_string}private static Map<String, String> configHibernate(){Map<String, String> map = new HashMap<String, String>();Properties properties = new Properties();        try {            properties.load(JBPMHelper.class.getResourceAsStream("/jBPM.properties"));        } catch (Throwable t) {            // do nothing, use defaults        }        map.put("hibernate.dialect", properties.getProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect"));map.put("hibernate.hbm2ddl.auto", properties.getProperty("hibernate.hbm2ddl.auto", "update"));map.put("hibernate.show_sql", properties.getProperty("hibernate.show_sql", "false"));map.put("hibernate.format_sql", properties.getProperty("hibernate.format_sql", "true"));return map;}}




python調用Java代碼,完畢JBPM工作流程application

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.