Skip to content

Commit

Permalink
为nutz集成添加SnakerIocLoader以实现一步配置,并添加合适的测试类及示例配置代码.
Browse files Browse the repository at this point in the history
  • Loading branch information
wendal committed Mar 5, 2015
1 parent 1bba049 commit 33f4d57
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 58 deletions.
2 changes: 1 addition & 1 deletion snaker-nutz/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutz</artifactId>
<version>1.b.50</version>
<version>1.b.52</version>
<scope>provided</scope>
</dependency>
<dependency>
Expand Down
121 changes: 121 additions & 0 deletions snaker-nutz/src/main/java/org/snaker/nutz/SnakerIocLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package org.snaker.nutz;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import javax.sql.DataSource;

import org.nutz.ioc.IocLoader;
import org.nutz.ioc.IocLoading;
import org.nutz.ioc.ObjectLoadException;
import org.nutz.ioc.meta.IocObject;
import org.nutz.ioc.meta.IocValue;
import org.nutz.json.Json;
import org.nutz.lang.Streams;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.resource.NutResource;
import org.nutz.resource.Scans;
import org.snaker.engine.DBAccess;
import org.snaker.engine.SnakerEngine;
import org.snaker.engine.cfg.Configuration;
import org.snaker.engine.entity.Process;
import org.snaker.engine.impl.SimpleContext;
import org.snaker.engine.model.ProcessModel;
import org.snaker.engine.parser.ModelParser;
import org.snaker.nutz.access.NutzAccess;
import org.snaker.nutz.access.NutzTransactionInterceptor;

/**
* 用法: 假设使用ComboIocLoader及流程文件位于flows目录.在@IocBy中声明 "*xxxxxx.xxx.x.x.SnakerIocLoader", "flows"
* @author wendal(wendal1985@gmail.com)
*
*/
public class SnakerIocLoader implements IocLoader {

private static final Log log = Logs.get();
protected IocObject iobj;
protected String name = "snakerEngine";
protected String dataSourceBeanName = "dataSource";
protected String factoryMethodName = "buildSnaker";
protected static String querySql = "select * from wf_process where name=? order by version desc";

public SnakerIocLoader(String...paths) {
// 手工构建一个nutz的ioc bean定义
iobj = new IocObject();
iobj.setFactory(SnakerIocLoader.class.getName() +"#" + factoryMethodName); // 调用本类的buildSnaker方法
iobj.setType(SnakerEngine.class); // 反馈类型
IocValue ds = new IocValue();
ds.setType(IocValue.TYPE_REFER);
ds.setValue(dataSourceBeanName); // 引用数据源
iobj.addArg(ds);
for (String path : paths) {
IocValue p = new IocValue();
p.setValue(path);
iobj.addArg(p);
}
if (log.isDebugEnabled())
log.debug("snakerflow bean will define as\n" + Json.toJson(iobj));
}

public static SnakerEngine buildSnaker(DataSource ds, String path) throws IOException {
return buildSnaker(ds, new Object[]{path});
}

protected static SnakerEngine buildSnaker(DataSource ds, Object...paths) throws IOException {
// 首先,我们构建一个snaker的上下文
SimpleContext ctx = new SimpleContext();
// 将集成nutz所必须的两个类,关联之. 这样使用者仅需要声明本IocLoader即可完成全部配置
ctx.put(NutzAccess.class.getName(), NutzAccess.class);
ctx.put(NutzTransactionInterceptor.class.getName(), NutzTransactionInterceptor.class);
// 开始构建sanker的配置对象
Configuration cnf = new Configuration(ctx);
cnf.initAccessDBObject(ds);
SnakerEngine engine = cnf.buildSnakerEngine();
// 如果用户声明了流程描述文件的路径,加载之
if (paths != null) {
for (Object path : paths) {
for(NutResource re : Scans.me().scan(String.valueOf(path))) {
if (log.isDebugEnabled())
log.debug("Found snakerflow xml > " + re.getName());
//*********************************************************
// 这部分属于hack的部分, 因为snaker并不识别相同的流程配置,而是简单地作为新流程
// 所以,需要自行查询一下是不是数据相同,不一样的时候才deploy
byte[] data = Streams.readBytesAndClose(re.getInputStream());
ProcessModel model = ModelParser.parse(data);
List<Process> list = ctx.find(DBAccess.class).queryList(Process.class, querySql, model.getName());
if (!list.isEmpty()) {
Process p = list.get(0);
byte[] cnt = p.getDBContent();
if (cnt != null && Arrays.equals(cnt, data)) {
log.debug("Same snakerflow xml > " + re.getName() + " skiped");
continue;
}
}
//*********************************************************
// 同名的流程数据有更新或这是全新的流程,部署之
engine.process().deploy(new ByteArrayInputStream(data));
}
}
}
// 工厂方法完成, snaker引擎已经准备好了,可以返回了
return engine;
}

public String[] getName() {
// 这个类仅需要维护一个ioc bean的定义,所以就是单个name的数组咯
return new String[]{name};
}

public boolean has(String name) {
return this.name.equals(name); // 就一个ioc bean定义嘛
}

public IocObject load(IocLoading il, String name) throws ObjectLoadException {
if (this.name.equals(name))
return iobj;
throw new ObjectLoadException("Object '" + name + "' without define!");
}
}
15 changes: 15 additions & 0 deletions snaker-nutz/src/test/java/test/nutz/NutSnakerDemoModule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package test.nutz;

import org.nutz.mvc.annotation.IocBy;
import org.nutz.mvc.ioc.provider.ComboIocProvider;

/**
* 这是个为了演示配置方法的类. 无需在snaker.xml中声明nutz相关的类.
* @author wendal(wendal19885@gmail.com)
*
*/
@IocBy(type=ComboIocProvider.class, args={"*js", "ioc/", // 其他json ioc配置文件
"*anno", "net.wendal.snaker.demo", //需要扫描的package
"*org.snaker.nutz.SnakerIocLoader"})
public class NutSnakerDemoModule {
}
41 changes: 0 additions & 41 deletions snaker-nutz/src/test/java/test/nutz/SnakerFacets.java

This file was deleted.

28 changes: 19 additions & 9 deletions snaker-nutz/src/test/java/test/nutz/TestNutz.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,43 @@

package test.nutz;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.IocLoader;
import org.nutz.ioc.impl.NutIoc;
import org.nutz.ioc.loader.json.JsonLoader;
import org.nutz.ioc.loader.combo.ComboIocLoader;
import org.snaker.engine.SnakerEngine;
import org.snaker.engine.access.QueryFilter;
import org.snaker.engine.entity.Order;
import org.snaker.engine.entity.Task;
import org.snaker.engine.helper.StreamHelper;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.snaker.nutz.SnakerIocLoader;

/**
* 测试nutz整合
* @author yuqs
* @since 2.0
*/
public class TestNutz {

protected Ioc ioc;
private SnakerEngine engine;
@Before
public void before() {
Ioc ioc = new NutIoc(new JsonLoader("ioc.js"));
SnakerFacets facets = ioc.get(SnakerFacets.class, "snaker");
engine = facets.getEngine();
public void before() throws ClassNotFoundException {
IocLoader loader = new ComboIocLoader("*js", "ioc.js", "*"+SnakerIocLoader.class.getName());
ioc = new NutIoc(loader);
engine = ioc.get(SnakerEngine.class);
}
@After
public void after() {
if (ioc != null)
ioc.depose();
}

@Test
Expand Down
4 changes: 0 additions & 4 deletions snaker-nutz/src/test/resources/ioc.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,5 @@ var ioc = {
type : "org.nutz.dao.impl.NutDao",
args : [ { refer : "dataSource" } ],
fields : { sqlManager : { refer : "sql" } }
},
snaker : {
type : "test.nutz.SnakerFacets",
args : [ { refer : "dataSource" } ]
}
}
3 changes: 0 additions & 3 deletions snaker-nutz/src/test/resources/snaker.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>

<config>

<bean class="org.snaker.nutz.access.NutzAccess"/>
<bean class="org.snaker.nutz.access.NutzTransactionInterceptor"/>
<bean class="org.snaker.engine.access.dialect.MySqlDialect" />
<bean class="org.snaker.engine.impl.JuelExpression" />
</config>

0 comments on commit 33f4d57

Please sign in to comment.