2007-12-18

ejb环境下的org.hibernate.TransientObjectException

网站上用户注册的同时还要给用户加分.

以前ear部署时CallByValue设置的是false(ear-deployer.xml), 后来改成了true, 然后就不能加分了, 注册还是可以的, 就是一直报org.hibernate.TransientObjectException的异常.

代码大概是这样的:
Consumer c = new Consumer();
c.setUsername("uname001");
c.setPassword("pwordddd");
service.save(c);//1
service.addPoints(c, 300);//2

service是对EJB的引用(Stateless)
故事就是由EJB引起的.如果CallByValue=false, 在执行"1"后执行
System.out.println(c.getId());//841
返回值不是空, 如果CallByValue=true, 返回值就是空.

分析一下 : CallByValue时, Hibernate不能同步c的id.

POJO有3种状态, Transient, Persistent, Detached, Transient是用"new" 实例化的, 执行hibernate的save操作, 会存储到数据库的同时更新这个对象, 变成Persistent.而在CallByValue=true 的情况下, hibernate无法更新到这个对象, 也就是说, 在上面1步骤执行的时候, hibernate没有办法更新c这个变量.

废话多了, 好像也没大说明白....

2007-11-20

访问EJB

Local的是不能在EJB外访问的, 否则会报这样的异常:
javax.ejb.EJBException: Invalid invocation of local interface (null container)
如果想独立启动junit测试访问ejb, 需要把ejb声明为Remote.

2007-11-19

jms定时发送

需求说在23:00至10:00这个区间不准向用户发短信, 如果有的话, 时间顺延.
jms标准并未提供定时发送的规范, 所以根据各实现的不同, 有不同处理方法, 在jboss中, 设置如下:

//....
Message msg = session.createObjectMessage();
msg.setLongProperty("JMS_JBOSS_SCHEDULED_DELIVERY", time());
//....
sender.send(msg);
其中time()返回的是msg发送的时间点, long类型. 如果是想立即发送的话, 值应该是
System.currentTimeMillis()

tss讨论帖

2007-11-16

今儿总算是明白了, 为什么那么多人追着学xml

http://www.w3schools.com/xml/xml_xsl.asp

非常清晰直观的sample.

我觉得非常突出的一个优点是, 强制web designer更标准化地去做xsl.

用html的话, 就很随便了, 可以拼凑出页面来.

xml数据是独立出来的, 也方便供其它接口调用(ws?, 采集数据?)

终于发觉它值得学了.....

2007-11-01

函数式编程

适合做DSL.
包括回调(callback)这样的技巧.
感觉象一种"操作注入" , 相对"依赖注入"来说.
实现有Erlang和Haskell等, 高并发, 据说Erlang的http服务器比apache快15倍

复杂的系统倾向于用这种语言, 代码比较优美, 相对较少. ref=>越少的代码越不容易出错

少废话, 来几个链接

http://www.ibm.com/developerworks/cn/web/wa-javascript.html
developerWorks上用js解释的

http://www.ibm.com/developerworks/java/library/j-fp.html
java中的函数式编程

http://code.google.com/p/pure-functional-java/
一个小项目, 大致实现了函数式编程.

http://chn.blogbeta.com/232.html
一个从几千年开始讲起的函数式编程的历史.

2007-09-24

慎用System.exit()

写个程序, 给邮件列表里每个人都发封邮件.

用main启动spring, 然后main就一直等, 一直等...spring就嘿咻嘿咻地启动线程, 发邮件, 启动线程, 发邮件.....

然后就完成任务了~~~ :).

后来, 又给了我一个邮件列表, 这次要带附件发送...

问题来了, 程序还没等邮件发完, 就终止了....

然后发现, 在读邮件列表时, 是一行一行地读的, 每读一个, 就发送给spring, 让spring去嘿咻嘿咻, 如果读到最后一行, 就执行
System.exit(0);
问题就是这段代码了, 把它修改成
return;
OK了, 阳光明媚 :D

虽然读到了最后一行, 但是, 后台的发送程序还没结束.

2007-09-06

发现spring写的代码跟我的一样, 偷乐.....

我写了个StringArrayEditor, 后来发现spring有一个StringArrayPropertyEditor, 名字差不多, 看内容, 完全一样的, 呵呵.

不过, 最后还是把我的代码删除掉了.....

这是一个bug么?Spring.BeanWrapper

spring的BeanWrapper会存放属性值.

class A{
BeanWrapper bw = new BeanWrapper(this);
private String[] sa;
//setter/getter....
}

给sa属性加了个属性编辑器StringArrayPropertyEditor
我觉得, 这么调用, 应该不会出问题:

A a = new A();
a.setSa(new String[]{"a", "b", "c"});
//我期望它的结果应该是 "a,b,c"
a.bw.findCustomEditor(String[].class, "sa").getAsText();

结果, 却是空, 不是找不到属性编辑器, 当你通过属性编辑器去获取属性值时, spring不会真正地去a这个类里面实时查找.只有当执行这句,
上面的代码才能得到预期的结果:
a.bw.setPropertyValue("sa", new String[]{"a", "b", "c"});

令人失望....咋就不去inspect一下'a'这个类捏?

2007-09-05

老婆, 今天我又迟到鸟

车好堵啊, 一动也不动的, 我走到加工区那边, 还等了老半天才座上车的, 其实司机是往石化那边开的, 近一个小时一动也不动, 受不了了, 就掉头去莲花了, 哈哈.

2007-08-31

又一次谈classloading--java.lang.VerifyError

事情是这样的, ear里的war老部署不上去, war里的一个filter(确切的应该是acegi的filter, 托管给spring的)加载不了, 问题出在spring给它的doFilter方法注入属性被检测到verifyError.

后来, 修改jbossweb-tomcat55.sar/META-INF/jboss-service.xml, 把Java2ClassLoadingCompliance属性设置为true, 就OK了.

这个属性是jboss集成tomcat用的, 它的意思是, 是否把java2的"父类优先"加载模型替换为servlet 2.3的"web容器优先"


2007-08-29

jobss类加载

一般来说, 象httpclient, logging等, 不会从ear包内加载, 而是用jboss现有的.如果想加载, 要在meta-inf/下加个jboss-app.xml文件, 内容大概是:
<jboss-app>
<loader-repository>some.dot.com:loader=webtest.ear</loader-repository>
</jboss-app>
原文

然后我就照这个办了, 后来发现还不行, 说是mdb(部署了一个message-driven bean)不合规范:
section:15.7.4
The message driven bean must declare one onMessage method

后来才发现, 不知道哪个傻X把geronimo-j2ee-spec.jar放到ear包里来了, NND, 估计是geronimo与jboss验证方法不一样吧.

去掉就OK了. 还有个关于logging的, 不加jboss-app.xml的话, 会自动把你自己ear内的logging.jar忽略掉(而用jboss服务器的), 加了jboss-app.xml, ear的classLoader也会把ear里面的logging.jar加载上 , 然后Log对象就发现它有两个版本(一个jboss的, 一个ear载的).就会报错(检查的还挺仔细)

再这么下去, 快成jboss专家了....

--
It's Hard to Define, But I Know it When I See it…

2007-08-28

class 版本

Unsupported major.minor version 49.0
部署ejb的时候就出这问题, 也会出classNotFoundException. 原因是jdk5编译出来的class在jdk4上面不能.
这种问题...真让人无奈....

--
It's Hard to Define, But I Know it When I See it…

2007-07-25

因无索引导致的性能问题

测试那边说, 页面打开很慢, 自己跑去试了下, 果然, 一个搜索结果页面, 大概要30s~60s, 查看了下代码, 发现是段hql执行问题, 就抽取出来单独测试, 这个查询类似这样的结构:
select count(*) from a, b where a.bid = b.bid;

其中a表中的bid是b表的id外键. 每个表大概有7k条记录.这个查询每次都耗时30s, 后来把a表中的bid字段建立个属性, 速度就快多了, 大概是300ms~1s.

以前一直没觉得索引有这么神奇的效果.....

--
It's Hard to Define, But I Know it When I See it…

2007-07-24

接口参数类型

之前写过一个接口, 目的是更新FriendLink对象到数据库.形式如下:

update(FriendLink link);

接口的实现是这么写的:
update(FriendLink link){
    dao.update(link);
}

后来, 发现有弊病在: 这个接口依赖这样的事实: link已经存在于数据库中 .这样很容易产生潜在的不安全性, 外部的任何程序都可以随意构造一个FriendLink实例(而不是从数据库中取然后稍加修改而成的), 然后传入到这个接口, 然后产生异常. 还有个问题就是, 它限制了访问媒介为java对象(须先构造出FriendLink对象来, 才能访问到这个接口), 不利于其它形式的访问(如webServices, REST等---虽然可以, 但是须对FriendLink中accessor信息了然于胸). 所以应修改如下:

update(long friendLinkId);

传入基本类型(long), 声明说会对这个(id为friendLinkId的FriendLInk)作更新, 这样, link已经存在于数据库中  这样的谓词是由接口内部来判断处理的. 对于其它形式的访问, 基本类型都是被支持的. 至于update的信息, 可以以参数形式, 或函数名形式展现, 如下:
update(long frindLinkId, Date accessDate); ①

updateAccessDate(long friendLinkId);②

象②这样的只传入id的接口, 依赖于"执行更新所需信息可以从接口上下文得到", 比如当前时间等.所以应用面比较狭窄, 不知道具体应该怎么处理(map参数?) :( (还是动态语言比较好, 象js的arguments参数很灵活)

--
It's Hard to Define, But I Know it When I See it…

date 与 timestamp 类型

用一句话说就是:
timestamp比date精确.
用date只能搞到日期, 时间得不到, 所以在sql里面进行alter时, 只有timestamp=>date的转换, 如果想执行相反的转换会报异常.

如果用hibernate进行映射, 一般来说是 java.util.Date=>timestamp.否则, 标志性的异常信息是batch update exception (不过有个有趣的现象是, 如果你设置hibernate.jdbc.batch_size 为0的话, 就能顺利执行, 应该是hibernate的bug)
P.S. 如果是用xdoclet映射字段, 不要这么写:
@hibernate.property column="createDate" type="date" 
把type写全:java.util.Date. 否则会引来不必要的麻烦: hibernate会把它错当成java.sql.Date :(

--
It's Hard to Define, But I Know it When I See it…

2007-06-28

将unicode转成中文及其它

找不到源文件了, 只好把.properties反转换成中文了
原理就是把.properties中的所有"\uxxxx"形式的转成对应的中文.

String r = FileUtils.readFileToString(new File("d:/aa.TXT"), "utf-8");
Pattern p = Pattern.compile("\\\\u([a-zA-Z0-9]{4})");
String t = "";
Matcher m = p.matcher(r);
while(m.find())
{
    t = m.group(1);
    r = r.replaceFirst("\\\\u([a-zA-Z0-9]{4})", String.valueOf(Character.toChars(Integer.parseInt(t, 16))));
}
System.out.println(r);

那个parseInt中的参数16表示t是16进制的字符串.
感觉还比较简洁的说~~~

P.S. FileUtils是jakarta commons.io里的

--
It's Hard to Define, But I Know it When I See it…

2007-06-14

httpclient提交中文的问题.

提交的时候老出错, 把我的中文全给搞成问号, 后来看服务器上有个encodingfilter, 貌似只接收utf-8的.

本来想的是看看httpclient里面哪里编码不对了, 改成utf-8,如此的思路.

后来, 发现给http head加个meta就成了:
post.addRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");

真的是不能想太复杂鸟...

--
It's Hard to Define, But I Know it When I See it…

2007-06-07

其实, 除了actionForm还有更简便的方式的~

Spring的这个databinder真是好用:

FriendLink bean = new FriendLink();
ServletRequestDataBinder binder = new ServletRequestDataBinder(bean, "link");
CustomDateEditor editor = new CustomDateEditor(new SimpleDateFormat("yyyy-M-d"), true);
binder.registerCustomEditor(Date.class, editor);
binder.bind(request);

这样就自动给bean注入值了, 而且它已经自动拥有了处理multipart的能力, 真是不错. 只是没有处理日期格式的能力, 但是象上面的代码就可以了.

顺便贴几个链接:
link 用spring做项目时的一些设计上的技巧.
link ServletRequestDataBinder的官方文档.
link 处理日期格式的方法就是从他这抄袭来的, 呵呵.

--
It's Hard to Define, But I Know it When I See it…

2007-05-13

补: autoboxing

网上搜NPE,发现了别人碰到同样的问题.这些人还建议不要用autoboxing. 有句倒说的很到位:The root cause of the NPE-related weirdness is that Java doesn't distinguish between pointers and "pointers that can be null". 这也应该是autoboxing问题的根源。

P.S. NPE=NullPointerException(看来这个异常很常见呢)

2007-03-25

java.sql.SQLException: java.lang.NegativeArraySizeException

有段java程序, 通过jdbc调用mysql的
在执行分页查询的时候, 如果是这么写:
select * from orders limit 1, 30;//第一页的30条
没有任何问题.但是把它放到存储过程里(参见前一篇文章), 就会出那个exception,只要是页不满的情况都会报exception.但是有个特别的现象, 如果你把orders表清空, 然后执行java, 不会报错, 只有当行数大于某个值并且页不满才会报Exception.

非常不明白....
相对详细的代码在这:link

2007-03-24

myeclipse差劲

除了它集成的那几个Eclipse Foundation的项目外, 基本上都很差.
特别是UML, 当初看着感觉还不错, 用着问题就出来了: 不能识别泛型, 不能导入类, 删除类/关系删不干净, 生成的代码错误百出.最要命的是它还搞罢工, 本来就是serialize的object, 出点问题就死翘翘了.慎用....非常不稳定

mysql的分页存储过程

一般的分页面可以这样直接写在sql里面:

select * from test limit 3, 20;

表示每页显示20个, 第3页.这种写法不能通过PreparedStatement执行, 因为它是编译过的, 存储过程同理.所以这样写不会成功:

create procedure pager (in pno int, in psize int)
begin
declare pp int default 0;
set pp = (pno - 1) * psize;
select * from pager limit pp, psize;
end

应该算是mysql的bug.

有个折衷的办法:

create procedure pager (in _pno int, in _psize int)
begin
prepare stmt from "select * from test limit ?,?";
set @pno = (_pno - 1) * _psize;
set @psize = _psize;
execute stmt using @pno, @psize;
end

link, link

2007-03-22

autoboxing的bug么?

碰到这么个问题:

Double d = null;
double e = d;
System.out.println(e);

这会出问题, d不能自动autounboxing为double.会报nullPointer异常.
所以在做ibatis映射的时候, bean的属性需要是Double类型的.否则会有不必要的问题.
失望....

2007-03-15

dbdesigner不能连mysql的问题.

dbdesigner连mysql老报错:
cannot connect to mysql : invalid username/password

把password在mysql中更新一下就好了:
mysql> set password for 'root'@'localhost' =OLD_PASSWORD('newpassword');
一个与老版本兼容的问题, link

2007-03-13

目前Ajax主要存在的问题

  • Accessibility问题。
  • 主要开源框架(prototype和dojo)文档不足。
  • 缺乏好的跨域机制。XMLHttpRequest不行,Doug Crockford的JSONRequest不错,但是很难被微软采纳。
  • 跨浏览器编程仍然非常麻烦。
  • 对Comet (HTTP Streaming) 的重要性仍然认识不足。

2007-03-09

全排列算法

题目大致是这样滴:
有1, 2, 2, 3, 4, 5, 这六个字符, 打印出它们的所有排列顺序.
想了老半天, 结果就是这样滴:

public class SnippetTest
{
private void perm(char[] a, boolean[] f, String r)
{
for(int i = 0; i < f.length; i++)
{
if(!f[i])
{
f[i] = true;
if(r.length() == 5)System.out.println(r + a[i]);
perm(a, f, r + a[i]);
f[i] = false;
}
}
}

public static void main(String[] args)
{
char[] a = new char[]{'1', '2', '2', '3', '4', '5'};
boolean[] f = new boolean[6];//default is false
String r = "";
new SnippetTest().perm(a, f, r);
}
}

嗯....相当简洁的说.而且也是可以扩展的, 赞自己一个, 太TNND牛了

2007-02-27

今天这几篇都是转移过来的

因为有段时间blogger并不好用, 然后我就自己搭建了个wordpress, 写了些日志.

现在要离开公司了, 就把这些日志整理出来, 重新发布到blogspot上来了.

其实很长段时间以来都没很好得写过日志了. 感觉总是抽不出时间来.

以后会多多写了 :)

从editplus编译/运行java

天天对着editplus也米好好研究过, 原来它还有这个能力

在给editplus设置参数时发现user tools这个选项, 就想到了java的编译和运行命令.虽然有了eclipse方便了很多, 但是有时还是有命令行的需要.不扯废话, 正题:

在user tools选项里选择add tools>>Program.把javac.exe加进去. Argument设置为$(FilePath), Initial Directory设置为$(FileDir).最好把”capture output”也选上, 这样的话就能看到控制台的输出信息了.

类似的, java命令也这么搞:

Argument : -classpath $(FileDir) $(FileNameNoExt)

Initial Directory : $(FileDir)

保存, 然后新建个java文件, 从tools菜单里选择”编译” 然后再”运行”, 嗯.OK啦, yeah~

在eclipse中搜索中文

一般都是修改别个的代码, 自己会手动加些注释在上面, 但是时间长了就忘记了哪里修改过了, 又米有cvs.

还好, eclipse的search功能还真是强大, p服p服

[\u0100-\uffff]+

这段regexp可以查找出所有的中文来, 如果想只在java文件里搜索, 就加个”*.java”就好了

察看端口冲突

机器上开着好多程序, 几个web服务器, 还有cvs,还有其它的msn, gtalk等, 有时候要想再启动服务会出现错误说端口已经被占用, 一开始的时候不知道是哪个程序占用的, 就一个一个关掉试, 后来找到个好办法:

netstat -b

这个命令可以察看已经打开的端口是由谁打开的.看了觉得MSN开了N多的端口, 真是…

yourkit 连到jvm

jdk1.4:

-Xrunyjpagent:port=10010,dir=d:\dev\yourkit\snapshots

jdk5.0:

-agentlib:yjpagent=port=10010,dir=d:\dev\yourkit\snapshots

我的yourkit版本是5.5, 在jdk6.0上试运行了下, 不行, 查了下, 好像yourkit6.0才支持jdk6的.

不好….

将ant输出日志redirect

ant -logfile ant.log mytarget

这样就OK了, 还有其它的listener&logger等, 可以参看ant的manual, Loggers & Listeners 目录

安装wordpress

问题就在php-mysql.dll没有安装, 但是俺是下载的标准的php安装文件装的吖, 怎么还会这样捏?原来它默认好像是不安装的, 倒….

回顾一下具体的安装步骤吧, 要不又忘记鸟:

  1. 安装apache_2.2.2-win32-x86-no_ssl.msi
  2. 安装mysql,好像是5点几的, 建个db名字为wordpress
  3. 安装php-5.2.0-win32-installer.msi
  4. 修改{php.home}/php.ini文件, 将 ;extension=php_mysql.dll取消注释, 然后设置下对应mysql的host, username, password就成啦