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=utf8

import os
javapath = "/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 autoclass ProcessMain = autoclass('com.sample.ProcessMain') #.号分隔
ProcessMain.pythonCallMeStatic() #ok, before ProcessMain(), can call java static method
# ProcessMain.pythonCallMeInstance() #error, before ProcessMain(), can not call java instance method process_main = ProcessMain()
process_main.pythonCallMeInstance()
process_main.pythonCallMeStatic() ProcessMain.pythonCallMeStatic()
ProcessMain.pythonCallMeInstance() # after ProcessMain(), python does not distinguish static/instance method
print "-----------------------------------------" """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.xml

		KieBase 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接口 getAuditLogService

		ksession.startProcess("com.sample.bpmn.hello");

		// let john execute Task 1

		List<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 2

		list = 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的更多相关文章

  1. Python调用Java代码部署及初步使用

    Python调用Java代码部署: jpype下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#jpype 下载的时候需要使用Chrome浏览器进行下载 ...

  2. python 调用 java代码

    一.JPype简述 1.JPype是什么? JPype是一个能够让 python 代码方便地调用 Java 代码的工具,从而克服了 python 在某些领域(如服务器端编程)中的不足. 2.JPype ...

  3. python调用java代码 java虚拟机(jvm)

    1.新建com文件夹,在里面新建 fibnq.java package com; public class fibnq { public fibnq(){} public int fb(int n){ ...

  4. python调用Java代码

    #coding:utf-8 #!/usr/bin/python from jpype import * import os.path,json from ethereum.utils import e ...

  5. python调用java代码,jpype简单使用

  6. python2.7 (x64) 调用 java 代码实践

    背景:公司实施接口自动化测试,使用的框架python+unittest:因为开发使用的架构师SpringBoot,在测试过程中难免需要使用到python调用JAVA的一些接口,所以需要用到python ...

  7. C#调用java代码(IKVMC)

    参考资料:https://blog.csdn.net/threadroc/article/details/51406587 参考1:http://www.cnblogs.com/Jack-Blog/p ...

  8. 使用 jpype 库实现 Python 调用 java 的 jar 包中的功能

    一.what's the JPype JPype 是一个能够让 python 代码方便地调用 Java 代码的工具.在某些时候 java 的能力更强,我们可以用 java 写一个模块的功能然后用 Py ...

  9. python - jpype模块,python调用java的接口

    转载自: http://www.cnblogs.com/junrong624/p/5278457.html https://www.cnblogs.com/fanghao/p/7745356.html ...

随机推荐

  1. C# Winform 模拟QQ新闻弹出框

    一开始做的时候,觉得这个太简单了.真心做的时候还是遇到了不少的坑啊. 1)循环播放新闻内容,建议使用showdialog(),不要用show(),不太好控制前后之间的停顿. 2)窗口的初始位置为有下角 ...

  2. sass06 mixin

    scss @mixin cont{ //mixin是关键字 color:red; } body{ @include cont; //使用默认值 } @mixin cont($color: red ){ ...

  3. Mysql优化ibdata1大小

    在MySQL数据库中,如果不指定innodb_file_per_table参数来单独存在每个表的数据,MySQL的数据都会存放在ibdata1文件.mysql ibdata1存放数据,索引等,是MYS ...

  4. BZOJ 1336&1337最小圆覆盖

    思路: http://blog.csdn.net/commonc/article/details/52291822 (照着算法步骤写--) 已知三点共圆 求圆心的时候 就设一下圆心坐标(x,y) 解个 ...

  5. 设置和获取Android中各种音量

    通过程序获取android系统手机的铃声和音量.同样,设置铃声和音量的方法也很简单! AudioManager am = (AudioManager) getSystemService(Context ...

  6. Android属性动画-Interpolator和ViewPropertyAnimator的用法

    Interpolator的用法 Interpolator这个东西很难进行翻译,直译过来的话是补间器的意思,它的主要作用是可以控制动画的变化速率,比如去实现一种非线性运动的动画效果.那么什么叫做非线性运 ...

  7. Intellij格式化java和xml

    使用Intellij的这段时间,一直在寻找一些技巧,不断提高对它的熟练度.接下来告诉大家一个小秘密,带大家体验一下Intellij半自动格式化代码的快感.那要使用这个功能还得安装一个插件--Eclip ...

  8. theano import error (win10 python2.7)

    因为项目需要,在win10-64位电脑上配置theano.但是一直有 import error的错误,找不到解决方法.作为一个python新手,实在搞不定,请大家不吝赐教!小女子不胜感激! 按照网上的 ...

  9. 参考《深度学习之PyTorch实战计算机视觉》PDF

    计算机视觉.自然语言处理和语音识别是目前深度学习领域很热门的三大应用方向. 计算机视觉学习,推荐阅读<深度学习之PyTorch实战计算机视觉>.学到人工智能的基础概念及Python 编程技 ...

  10. php如何openssl_encrypt加密解密

    最近在对接客户的CRM系统,获取令牌时,要用DES方式加密解密,由于之前没有搞错这种加密方式,经过请教了"百度"和"谷歌"两个老师后,结合了多篇文档内容后,终于 ...