SpringIDE的误导

用springide验证了一下xml文件,得到这个错误

Destroy-method ‘shutdown’ not found in bean class ‘org.enhydra.jdbc.pool.StandardXAPoolDataSource’

bean的配置如下:

也就是说springide认为这个bean没有shutdown的方法.查了一下xapool的source,发现是有的,但是是shutdown(boolean).destroy-method属性的定义:

Attribute : destroy-method
The name of the custom destroy method to invoke on bean factory shutdown. The method must
have no arguments, but may throw any exception. Note: Only invoked on beans whose lifecycle is
under the full control of the factory – which is always the case for singletons, but not guaranteed
for any other scope.

在来看spring的source终于发现玄机所在:

DisposableBeanAdapter的invokeCustomDestroyMethod 方法:

Class[] paramTypes = destroyMethod.getParameterTypes();
if (paramTypes.length > 1) {
logger.error("Method '" + destroyMethodName + "' of bean '" + this.beanName +
"' has more than one parameter - not supported as destroy method");
}
else if (paramTypes.length == 1 && !paramTypes[0].equals(boolean.class)) {
logger.error("Method '" + destroyMethodName + "' of bean '" + this.beanName +
"' has a non-boolean parameter - not supported as destroy method");
}
else {
Object[] args = new Object[paramTypes.length];
if (paramTypes.length == 1) {
args[0] = Boolean.TRUE;
}

if (!Modifier.isPublic(destroyMethod.getModifiers()) ||
!Modifier.isPublic(destroyMethod.getDeclaringClass().getModifiers())) {
destroyMethod.setAccessible(true);
}

红色标记的地方就看到了,这个方法只会接受一个无参数方法或者参数唯一并且是boolean的方法.boolean值得意义就是force

附方法的注释:
This implementation invokes a no-arg method if found, else checking
for a method with a single boolean argument (passing in “true”,
assuming a “force” parameter), else logging an error.

显然SpringIDE没有考虑到这点.

“被和谐掉”应该也被和谐掉

“很黄很暴力”这个应该是最新的2008流行语,我喜欢..背景看这里

网上评论就不贴了,确实很”暴力” –>那帮没事做的网站编辑和cctv一个鸟样子

2007年比较流行的是”和谐” ,大家见面打招呼都是”你被和谐掉了么?””今天你和谐了么?”…鉴于暴民们把这么和谐的词汇用的这么不和谐, GFW决定把”被和谐掉”也和谐掉. 这样人民就不会再看到”xxx被和谐掉”这样的不和谐的东东.中国就会和谐了.

Firefox的一干插件

推荐我常用的Firefox插件

Delicious – 用firefox很大的原因是因为这个插件,del.icio.us实在是很好的应用
Scribefire – 用firefox发blog
Smart Bookmarks – 可以增加一个很方便的收藏夹工具栏,而且是一个个图标,可以容纳很多常用的网站
Gmail Manager – 方便的gmail插件,支持多用户
ForecastFox – 天气预报

Fireftp – 一个ftp客户端,简单易用。但目前不支持FF3
YouPlayer – 用来看youtube,可以容易的收藏下载youtube视频

Web Developer – 超强的页面调试工具,用来方便的调试css,html
JavaScript Debugger – javascript调试工具
Firegestures – 通过鼠标来轨迹来作一些常用的操作(后退,前进,关闭tab,移到下个/上个tab…)
PDF Download – web页面转成PDF

主题:
Littlefox for Firefox – 精简主题


最后更新2008-7-28

jBPM中task的signalling和blocking属性

今天发现在创建一个task实例之后,数据库中会出现两个task记录,不同的只是其中一个的issignaling是r,另一个是null.而且这两个使用的也是同一个token.查看jBPM的手册中的task management发现这样解释的:

A signalling task instance is a task instance that, when completed, can send a signal to its token to continue the process execution. Task instances can be blocking, meaning that the related token (=path of execution) is not allowed to leave the task-node before the task instance is completed. By default task instances are signalling and non-blocking.

信令和阻塞,当执行完成时发送一个signal给token..而blocking意味着token被阻塞在task-node直到task完成.不理解这个要在什么样的情况下使用,是不是分支任务的时候?

但是还是很奇怪,我这里只是 把start-state的task改成blocking=true就解决问题了.难道和state有关系吗?

有可能是我在生成processInstance时候有问题. 代码如下:

// create a new process instance to run
ProcessInstance processInstance = new ProcessInstance(processDefinition);
// create a new taskinstance for the start task
TaskInstance taskInstance = processInstance.getTaskMgmtInstance().createStartTaskInstance();
//signal
taskInstance.getToken().signal();
context.save(processInstance);

这样会生成两个taskinstance,而且一个是signaling一个是blocking??????

jBPM的性能测试

其实也还是hibernate得性能测试.不过为了满足boss的要求,还是写了一个测试.

启动20个线程,每个形成使用JbpmContext生成1000个ProcessInstance,然后遍历每个节点.

测试结果: 每个线程所需时间范围是360 – 420 s

用jconsole看了一下,瓶颈主要在网络读取(jdbc driver的socketread)和连接池等待(waiting available, checkout)上 .

import java.io.FileNotFoundException;
import java.io.IOException;

import org.jbpm.JbpmContext;
import org.jbpm.JbpmException;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.util.Log4jConfigurer;
import org.springmodules.workflow.jbpm31.JbpmCallback;
import org.springmodules.workflow.jbpm31.JbpmTemplate;

import com.jpmchase.zpcclass.common.util.SpringUtils;
import com.jpmchase.zpcclass.workflow.service.WorkFlowService;

public class JbpmScalTest {
static {
SpringUtils.initFromClasspath(new String[]{”com/jpmchase/zpcclass/applicationContext*.xml”});
try {
Log4jConfigurer.initLogging(”classpath:com/jpmchase/zpcclass/log4j.properties”);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
WorkFlowService wfs;
private JbpmTemplate jbpmTemplate;
@Before
public void setUp() throws Exception {
wfs = (WorkFlowService) SpringUtils.getBean(”workFlowService”);
jbpmTemplate = (JbpmTemplate) SpringUtils.getBean(”jbpmTemplate”);
}

@After
public void tearDown() throws Exception {
}

public static void main(String[] args) throws Exception {
int threadcount = Integer.parseInt(args[0]);
int cyclecount = Integer.parseInt(args[1]);
String testtype = args[2];
JbpmScalTest test = new JbpmScalTest();
test.setUp();
//test.testScal2();
test.go(threadcount, cyclecount, testtype);
}
class FlowRunner implements Runnable{
String name,unit=”simple”;
long elapse,cycle;
public FlowRunner(String n,long c,String u){
name=n;cycle=c;unit=u;
}
public long getElapse(){return elapse;}
public void run(){
System.out.println(name+” started”);
long start = System.currentTimeMillis();
jbpmTemplate.execute(new JbpmCallback(){
public Object doInJbpm(JbpmContext context) throws JbpmException {
if(unit.equals(”simple”)){
simpleUnit(context);
}else{
fullUnit(context);
}
return null;
}
});
elapse = System.currentTimeMillis() – start;
System.out.println(name+”,”+elapse/1000+”,”+cycle+”,”+unit);
}
public void simpleUnit(JbpmContext context){
ProcessDefinition pd = (ProcessDefinition)context.getGraphSession().findLatestProcessDefinition(”trademgmt”);
for(int i=0;i<cycle;i++){
ProcessInstance pi = new ProcessInstance(pd);
pi.getTaskMgmtInstance().createStartTaskInstance();
}
}
public void fullUnit(JbpmContext context){
ProcessDefinition pd = (ProcessDefinition)context.getGraphSession().findLatestProcessDefinition(”trademgmt”);
for(int i=0;i<cycle;i++){
ProcessInstance pi = new ProcessInstance(pd);
TaskInstance ti = pi.getTaskMgmtInstance().createStartTaskInstance();

ti.getToken().signal(”saveInput”);
ti.getToken().signal(”acceptInput”);
ti.getToken().signal(”releaseTrade”);
ti.getToken().signal(”generateObligation”);
ti.getToken().signal(”generateAccountEntry”);
}
}

}
@Test
//2 threads
public void testScal1() throws IOException {
go(20,100,”full”);
go(20,100,”simple”);
System.in.read();
}

private void go(int threadcount,int cyclecount,String testtype)throws IOException {
FlowRunner fr;
Thread t;
for(int i = 0;i<threadcount;i++){
fr = new FlowRunner(”runner”+i,cyclecount,testtype);
t = new Thread(fr);
t.start();
}
}

@Test
//20 threads
public void testScal2() throws IOException {
go(20,1000,”full”);
go(20,1000,”simple”);
System.in.read();
}
}

Thinlet 二三事

XUL – xml user interface language, mozilla推出的,firefox就是基于此. flex,zk都是这个意思
http://www.mozilla.org/projects/xul/

Thinlet – 开源XUL引擎,通过XUL分离业务逻辑和界面,基于AWT
ThinG – 用来编写thinklet的XUL的工具,thing.sourceforge.net.通过ThinG配合thinlet使用可以很快速方便的开发awt界面.Theodore – 同上,但是是收费的
genesis – 开发框架,用于企业应用开发的,但是没有体会到有多好,测试sample里的thinlet时AspectWerkz出错,保持关注
swiXML – 类似thinlet但是是用于swing的
jdnc – Sun力推的XUL解决方案,没看出有什么动向,保持关注

配置jvm远程管理控制台

-Dcom.sun.management.jmxremote.port=44444
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

sample:

java YourMainClass -Dcom.sun.management.jmxremote.port=44444 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false

然后在远程jvm上使用 命令jconsole打开 控制台, 输入目标jvm的ip和上面指定的端口(44444). 就可以看到jvm的详细数据了:线程,堆空间,内存使用,cpu使用,mbean…

配置jvm的代理服务器

由于代理的限制,在开发时eclipse运行时没有办法连到外部的服务器.这时就需要设置jvm的代理.

-DproxySet=true
-Dhttp.proxyHost=your.proxy.net
-Dhttp.proxyPort=8080

sample:

java YourMainClass -DproxySet=true -Dhttp.proxyHost=apacproxy.jpmchase.net -Dhttp.proxyPort=8080

eclipse里就是在run->arguments->vm arguments里填上这三个参数 ,如果是tomcat就需要修改catalina.bat/sh了.