Docker安装drools workbench和kie-server,使用http调用kie-server rest接口传json参数跑规则
尝试使用docker安装了drools workbench和kie-server,非常方便,记录如下。
安装Drools workbench
workbench从某个版本开始就改名字叫Business Central了,然而,我们在docker hub上看到的名字仍然是workbench。
参考: https://hub.docker.com/r/jboss/drools-workbench-showcase
1 2
| docker pull jboss/drools-workbench-showcase docker run -p 8080:8080 -p 8001:8001 -d --name drools-workbench jboss/drools-workbench-showcase:latest
|
启动成功后,访问http://ip:port/business-central
即可,默认用户名密码见上面的链接
安装Kie-server
参考:https://hub.docker.com/r/jboss/kie-server-showcase
1 2
| docker pull jboss/kie-server-showcase docker run -p 8180:8080 -d --name kie-server --link drools-workbench:kie_wb jboss/kie-server-showcase:latest
|
默认的用户名密码是kieserver/kieserver1!
注意
docker hub 上的启动命令--link drools-wb:kie-wb
实操后发现无法连接上workbench,在workbench页面上找不到启动的kie-server,修改伟--link drools-wb:kie_wb
后链接成功。原因暂时没找到…
使用Workbench定义数据对象和规则
这个没什么好说的。定义好数据对象/规则/规则流之后,记得build然后deploy。deploy成功后,可以在Deploy菜单下看到你发布的containers。也可以通过url:http://ip:port/kie-server/services/rest/server/containers
看到xml格式的描述。
通过Java Api调用规则
需要注意的是,Person
是在Workbench定义的数据对象(DataObject
),要么就在项目里面引入workbench发布的jar包,要么就定义一个实体类,包名/类名/变量都需要跟数据对象一致。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Person person = new Person(); person.setAge(27); person.setBalance(120000.00); person.setName("tangliu");
KieCommands cmdFactory = KieServices.Factory.get().getCommands();
List<Command<?>> commands = new LinkedList<Command<?>>(); commands.add(cmdFactory.newInsert(person, "person")); commands.add(cmdFactory.newFireAllRules());
ServiceResponse<ExecutionResults> response = rules.executeCommandsWithResults("com.riskspace:LtangsTestProject:1.0.0", cmdFactory.newBatchExecution(commands));
System.out.println(JSONObject.toJSON(response.getResult().getValue("person")));
|
正如上面所说,这样做的缺点就是,我的工程必须依赖发布的规则包里面的数据对象,这可太麻烦了。我想着,能否不需要依赖这些jar包,直接用json的方式调用?
终于在官方的用户手册上找到了调用方式,如下。
Rest api调用规则
通过Http请求,直接使用json作为请求参数,触发规则。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| String url = "http://*.*.*.*:8180/kie-server/services/rest/server/containers/instances/testalias"; String req = "{\n" + " \"commands\": [\n" + " {\n" + " \"insert\": {\n" + " \"out-identifier\": \"person\",\n" + " \"object\": {\n" + " \"com.riskspace.ltangstestproject.Person\": {\n" + " \"name\": \"tangliu\",\n" + " \"age\": 27,\n" + " \"balance\": 120000.00\n" + " }\n" + " }\n" + " }\n" + " },\n" + " {\n" + " \"fire-all-rules\": {\n" + " \"out-identifier\": \"firedActivations\",\n" + " \"agenda-filter\": \"TreeTest_0\"\n" + " }\n" + " }\n" + " ]\n" + "}";
String body = HttpRequest.post(url).body(req).basicAuth("kieserver", "kieserver1!").execute().body(); System.out.println(body);
|
调用是成功了,可惜的是agenda-filter
未生效。简单来说就是,fireAll就是真的fire container下所有规则了,不能根据规则名进行过滤。查了下源码,发现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { String max = null; String outIdentifier = null; while ( reader.hasMoreChildren() ) { reader.moveDown(); if ( "max".equals( reader.getNodeName() ) ) { max = reader.getValue(); } else if ( "out-identifier".equals( reader.getNodeName() ) ) { outIdentifier = reader.getValue(); } else { throw new IllegalArgumentException( "fire-all-rules does not support the child element name=''" + reader.getNodeName() + "' value=" + reader.getValue() + "'" ); } reader.moveUp(); }
FireAllRulesCommand cmd;
if ( max != null ) { cmd = new FireAllRulesCommand( Integer.parseInt( max ) ); } else { cmd = new FireAllRulesCommand(); } if ( outIdentifier != null ) { cmd.setOutIdentifier(outIdentifier); } return cmd; }
|
可以看出,fire-all-rules
不像它的java同胞,并不支持规则名过滤。找了很多资料,也没找到解决方案,也不知道为什么drools不支持,邮件问了下他们的开发者,可惜还没收到答复。
在rest api的情况下,想要触发指定规则,目前我能找到的解决方案就是,在workbench里面为你想要触发的规则再封装一个规则流,然后在json参数里面,使用
1 2 3 4 5 6
| { "start-process": { "processId": "example.process", "out-identifier": "firedProcesses" } }
|
的方式去触发指定的规则流。
有没有其他解决方案呢?有的,而且从实现上来说并不困难,自己开发一个工程,承担kie-server的功能,简单来说,就是监听workbench发布的规则包,然后将规则包里面的规则加载,同时对外提供一个http接口,将请求参数反序列化成对应的实体对象再去触发规则即可。后面有时间再弄了。