2005年12月15日

grails 有一个 wicket 的插件:

http://graemerocher.blogspot.com/2007/05/grails-wicket-wonders-of-grails-plug-in.html

我试了一下,发现最新版本(0.3)的wicket插件,运行helloworld都有问题,错误是:

wicket.markup.MarkupNotFoundException: Markup not found.

查看了一下原因,按照文档, HelloWorld.html 是放在 grails-app/views 目录下的,但是 wicket 插件 没有修改classpath 和 resource 装载的路径,也就是说,实际上这个 HelloWorld.html 对于 wicket 来说 是不可见的。但是如果把这个 HelloWorld.html 放在 src/java 目录下,则可以正常运行。
想到了一个简单的解决方案,修改 $GRAILS_HOME/scripts/Package.groovy,在 146 行增加:
fileset(dir:"${basedir}/grails-app/views") {
include(name:
"**/**")
exclude(name:
"**/*.groovy")
}

就像 src/java 当中的资源一样,全部拷贝到目标目录下,这样的效果就和放在 src/java 目录下一样了。

主站: http://blogsite.3322.org/

posted @ 2008-01-15 10:38 SimonLei 阅读(1095) | 评论 (1)编辑 收藏

首先看看我前几天的一篇blog

spring 与 osgi的第一个障碍

eclipse3.1, spring2.0.1,将spring.jar放到一个插件中,在另一个插件中去使用。 最简单的例子,在context.getBean的时候就报了一个异常:

Caused by: org.xml.sax.SAXParseException: cvc - elt. 1 : Cannot find the declaration of element  ' beans ' .

先是搜了一遍,没有发现很有帮助的内容。然后跟了一下,发现还是因为xsd的映射找不到。而造成这个问题的原因, 是在 spring.jar当中的META-INF/spring.schemas 这个找不到。

而这个找不到的最根本原因,是因为在eclipse当中,META-INF目录是不能够被其他插件找到的。也就是说,META-INF 目录是拥有spring.jar的那个插件所独占的,而其他插件就算依赖于这个插件,也是无法找到META-INF目录下的文件, 从而抛出这个异常。

解决问题的办法有几个,最简单的莫过于拷贝spring.schemas文件到需要的插件中,另一个办法是把spring的context 装载就放在spring.jar所在的插件中,或者改eclipse的代码。 :(

这个问题解决之后,紧接着第二个问题就是

Unable to locate NamespaceHandler  for  namespace http: // www.springframework.org/schema/aop

造成这个的原因和第一个类似,将spring.handlers拷贝到META-INF目录下就ok了。

上面是我以前的一个经验,今天仔细研究了一下,发现自己掉进了 经验主义的圈套。

这个经验是这样积累起来的:在刚开始尝试使用eclipse的时候,用的是3.0和3.1Mx系列,当时 不知道osgi是个什么东西 :$ 创建的几个插件,都没有创建osgi bundle manifest。也就是说, 只有plugin.xml,而没有META-INF/MANIFEST.MF文件的。但是在运行期,eclipse会自动的 从plugin.xml当中读取信息,生成临时的MANIFEST.MF文件,放在 runtime的 configuration/org.eclipse.osgi/manifests 目录下。而生成这个MANIFEST.MF文件,是 通过 PluginConverterImpl 这个类来实现的,在它的 isValidPackageName 方法中,所有的 META-INF或者以META-INF开头的目录,都不会被自动的export出去,从而在临时生成的MANIFEST.MF 文件中,永远不会有META-INF目录的export。

当时刚开始接触eclipse和osgi,根本不知道自己当时最佳的解决方案就是创建一个 bundle manifest, 然后在其中将META-INF目录export出来。而是通过盲目的修改代码来绕过这个弯。后来这个弯绕过去了, 留给我的经验就是:META-INF这个目录,是插件独享的,别的插件不允许访问的。

于是,在前几天,当spring.jar当中的几个META-INF目录下的文件访问不了时,我也认为这个经验有用, 差点就去改eclipse的代码了。幸好尝试了一下,把spring.jar所在的插件中,将META-INF目录共享出来, 居然就好了。仔细查了一下,发现屏蔽META-INF的代码只出现在PluginConverterImpl这个类当中。 回头想了想,终于明白自己这次是掉在经验主义的坑里面了。

经验主义害死人啊。唉。

主站: http://blogsite.3322.org/

posted @ 2006-12-28 10:37 SimonLei 阅读(3345) | 评论 (2)编辑 收藏
SUN Tech 2006第一天

会场设在最拥堵的北四环中路,赶到会场已经接近9点,匆忙报道之后,
第一感觉是不像去年那么大的场面了,只有两个会场,而且很奇怪的是,
参展的其他厂商,也只有AMD一家,显得有点冷清。

James Gosling又一次出现了,不过做的演讲并没有很多新鲜的东西,值得
注意的倒是Ruby on Rails出现在他的演讲内容当中,这大概也与JDK未来版本
要支持动态语言,以及SUN把jruby的两个人招进去有一系列的关系。随后有
一个SUN的技术展示,其中有意思的一个是 SPOT(Small Programmable Object Tech),
有点象《少数派报告》当中阿汤哥用的手套,用手套来当做鼠标一样的在
空中使用,很是不错。

随后一整天的演讲,给我的感觉,重头戏是Netbeans,其次是Ajax,再其次是
Java EE 5。感觉今天一系列的活动都与Netbeans有关,Ajax和Java EE 5包括
Java ME,都时不时的与Netbeans挂上钩。从今天被Netbeans洗脑的结果来看,
Netbeans现在确实越来越好用,功能也越来越强大。Eclipse如果按照现在的发展
速度,确实有些危险。不过,从另一个角度看,有竞争才能促进发展,也不算是件
坏事。

其他方面的收获,包括对JAVA SE 7 的一些特性了解,Java EE 5的一些介绍,以及
关于Java EE 5的参考实现 GlassFish的介绍,顺便还听了一些Java ME的东西,也
有些意思,可惜暂时用不上。

今天有一些感触:
 
好的技术,如果没有好的工具支持,也是很难生存的。这就联想到我们自己的IMP框架,
过去将重点放在framework和engine上,而对于designer的投入则远远不够。这样造成的现
象就是限制了开发效率,从而没有能够最大的发挥IMP框架的作用。

Netbeans虽然好用,也能够从一定程度上提高生产力。但是我还是那种观点,看上去
很美的代码生成机制,往往只是节省了“创建”的时间成本,而对于“修改”的效
率提高,却不一定有帮助。

JSF感觉还是沿袭了Struts的东西太多,就算通过Ajax的render,感觉还是不能算非常好的
Component Framework。还是不如Echo2 ;)

回家的时候,正赶上北四环的拥堵高峰,回到家已经很晚了,写的很零乱,不知道明天
会不会有什么大的收获。反正今天感觉就是被洗了一天的脑,害得我都想装一个Netbeans
来玩玩了。

SUN Tech 2006第二天

又经历了痛苦的2个小时到达了会场,今天的SUN公司主题居然是“开源的好处”,
重点提出开源最终有利于开源者,号称SUN从OpenSaloris的开源当中获得了很多
好处。不知道前几年大家强烈要求SUN 开源的时候,是不是也是这种论调。也懒得
去查以前的新闻了,不过总算逐渐有将Java开源的打算了,而且SUN号称要将所有的
软件开源,这对于open source社区,也算是件好事。

今天总的来说内容不是很丰富,这一次的Tech Day,总共也就是几个人在讲,一个人
讲好几场,这在以前的Tech Day是很少出现的。

今天的收获如下:

听了一场关于swing和美化swing的讲座,感觉SUN对于java的投入,比以前更大了。
以前,关于swing的微词很多,也有很多不好用的反馈,但是在几个jdk版本的发布过
程当中都没有改进,最典型的莫过于ContentPane,"Lastly, after seven years, we've made
jFrame.add equivalent to jFrame.getContentPane().add()."。在JDK5之后,可以感觉到SUN
对于用户社区的反馈开始逐渐重视。对于swing当中的功能较弱的问题,专门整了一个
swinglab来解决。其中还有个swingx的子项目,也有不少的swing功能增强组件可以用。

Apache Derby,也就是原来IBM收购informix时收购到的Cloudscape,现在又有了一个新
名字叫 Java DB,而且会随着JDK6一起发布。Java DB的功能比较完善,据说性能也不
错,号称支持300G的数据量没有问题。如果这样的话,不仅hsql可以抛掉,而且说不定
mysql也可以不用了。我现在也很喜欢这种既可以embed,又可以做为cs的数据库,现在
做rails的就是用sqlite,感觉也够用了。Java DB还有个很强的功能是,可以将数据打包为
jar文件,做为只读的db,放在光盘或者其他地方,做为备份和还原,以及做demo应用放
在光盘上,应该都有很大的用处。

JDK for script language. 在JDK6当中,已经支持 ruby和javascript两种脚本语言了。
功能上感觉有点象BSF,但是由于随着JDK6一起发布,所以以后影响力会更大。
而且,做演讲的人也提到,jruby的开发者进入SUN公司,恐怕不只是用ScriptEngine
支持script语言这么简单。今天体验了一下印度人说英语,确实是强...

另外还听了一下 MBean,Concurrence方面的东西,收获也有一些。例如在JDK6当中,
MBeanServer缺省就启动了,而不像JDK5里,需要用一个命令行参数才能启动。
两天下来,感觉这一期的SUN Tech Day和以往最大的区别就是,这一期完全是被
SUN自己垄断了,没有别的公司演讲, 不讨论别的公司的内容,没有别的公司参展。
言必称 NetBeans,操作系统必称 Solaris。从一个角度来看,SUN公司确实 积极的
参与到了开源社区当中,并且比以前更加接近用户,也更积极的响应用户的request。
这一点,从Netbeans的进展神速, 到JDK最近几个版本的新特性增加速度,都比JDK5
以前要好很多。这对于Java的进一步发展,可以说是一件好事。从另一个 角度来看,
这一届Tech Day表现出来的情况,不知道是应该说SUN更加有了自主意识,还是应该说
SUN确实没有很好的组织 这次会议。从参加演讲的人员,到展厅的布置来看,
都不如往届。不知道是不是SUN财务紧张造成的,hoho.

又花了两个小时才从首堵北京的北四环中路到了家,感觉今年的Tech Day,
最大的收获是被洗脑了,也体会到了目前最火爆的Ajax是如何的火爆。

主站: http://blogsite.3322.org/jspwiki/
posted @ 2006-09-29 10:09 SimonLei 阅读(1430) | 评论 (4)编辑 收藏
代码的卫生、习惯及其它...

最近忙,发现家里开始脏乱差了。仔细想想,其实之所以会这样,
是因为经常发现有点脏的地方,也懒得动,总是想等到啥时候大扫除
一下子全部清理干净。后来地面越来越脏,就越来越不注意,进入了
一个恶性循环。

不禁联想到“破窗户”理论,有个破窗户的社区,会逐渐变得不适合居住。
又想到一个经常看到的现象,如果一个电线杆下有一包垃圾,只要清理
不及时,过段时间,这个电线杆就会变成一个垃圾堆。

扯这么多,其实想说的是代码的卫生。代码,刚开始都是很干净的,只是
随着时间推移,随手乱扔的果皮纸屑逐渐增多,最后开始发臭,然后这个
代码就没有人愿意去碰了。在项目中,经常碰到这样的情况。同样的功能,
哪怕以前曾经有人写过,很多人还是倾向于自己重头开始写。原因是什么?
程序员只信任自己的代码,这是其中的一个原因。另一个原因是,以前的
代码确实有个需要学习上手的时间。打个比方,一间房子,不适合居住,需要
进行一番打扫才能住进去,这就是已有代码。而新的代码,则是程序员亲手
垒起来,亲手装修的,虽然耗时长,辛苦,但是心理感觉好。但是呢,这个
新房子对于其它程序员来说,已经时一个堆满垃圾不适合居住的旧房子了。
于是,每个程序员都亲手建一个房子,如此重复下去。

那么,要避免这种无意义的重复劳动,一方面是程序员本身意识的纠正。打扫
一个旧房子,虽然脏一点,但是通常比新建一个房子还是要快和省力。另一个
方面,程序员应该有这样的信念,不能让自己的代码变成垃圾堆。也就是说,
不能容忍自己的代码中堆满垃圾。

如何避免代码成为垃圾堆?个人认为,就象“破窗户”理论一样,不能对破了
的窗户听之任之,而要尽快修复。否则的话,其他人看到第一袋垃圾在这里,
觉得扔第二袋垃圾就没有罪恶感,至少罪恶感不那么强。大家可以想象一下,
在一个窗明几亮的环境中,你扔果皮纸屑之前都会三思。但是站在一个垃圾堆
上面,你扔垃圾之前就不会有什么顾虑了。因此,保持卫生的一个好习惯就是,
不放过第一个垃圾。

当然,如果判别某段代码是不是垃圾,或者及时发现第一段垃圾代码,那就是
另一个话题,例如用ut,用code review,等等。《Working Effectively with Legacy Code》
这本书里面,提到了Legacy code 的定义:

Code without tests is bad code. It doesn't matter how well written it is;
it doesn't matter how pretty or object-oriented or well-encapsulated it is.
With tests, we can change the behavior of our code quickly and verifiably.
Without them, we really don't know if our code is getting better or worse.

有人会觉得我管的太细,不揪架构、设计,反而去管代码,只见树木不见森林。我个人
的看法,架构、设计再好,都需要代码来进行实现。如果这个基础没打好,以后这个
代码总是会变成无人想碰的垃圾堆。

当然,我也反对无意义的追求完美。我不是个有洁癖的人,所以,代码到什么程度就算是
干净的了?我个人的看法是,Clean code that works。当然这一点其实不容易达到,但是
做为一个程序员,我还是努力去追求这一点的。

主站: http://blogsite.3322.org/jspwiki/
posted @ 2006-04-03 10:27 SimonLei 阅读(1079) | 评论 (1)编辑 收藏
上次的文章当中,把 eclipse做为web framework的核心,并且使得 servlet 的定义和mapping做为扩展点,确实狠 方便。不过现在又面临一个问题,有个历史遗留系统当中,有jsp 的应用。而jsp与servlet 的一个 很大的区别在于,它需要用 javac 去做编译。这就使得问题复杂化了,特别是使得 class loader 的关系变得更复杂。

我们首先看一下这里面有几种 class loader,首先,启动 eclipse 的是一个system loader,然后 是 eclipse starter 的 loader,启动我们的核心class loader,这个核心负责启动 jetty 和我们 的 web app两个插件,每个插件都有自己的 eclipse bundler loader。而jetty插件启动jetty 应用服务器,应用服务器本身有 context class loader,它还要负责去装载 WEB-INF/lib 下的所有jar文件,以及 WEB-INF/classes 目录下的文件,做为编译期使用。

这里不仅class loader 众多,而且关系复杂。一不小心就容易抛出 class not found 异常,或者是 class cast 异常。相对而言,只支持servlet 就狠简单,因为只要把 servlet 的 context class loader 用 eclipse bundler loader 替换掉就行。而jsp的编译机制,导致了问题的出现。

我对于这种复杂classloader情况的心得,就是把错综复杂的 class loader 关系网拉直,变成一棵 树。这样的好处就是,对于loader 的关系比较清晰,出现ClassNotFoundException和 ClassCastException这两种情况的时候,都狠容易判断怎么回事,不会被绕晕。这种时候,单步跟踪 只是找死,把classloader关系画出来,有利于对问题的分析。

于是画了这样一个图,把复杂的网拉直了,问题就迎刃而解了。


其中的关键就是 LauncherClassLoader。这个就是我们自己的ClassLoader,把它设置为 servlet context classloader 的 parent,并且把 context classloader 的装载顺序改变成为先由parent 装载,再自己装载的模式。这样,jsp的编译还是由 context loader 去处理,我就不管了。其他的 该装载的地方,还是有 eclipse bundler 去装载,这样问题基本解决。

不过这样其实还是有个问题,如果要在 jsp 当中调用某个插件当中的 class,那么在编译期就会出现 问题。不过由于目前只是解决 legacy jsp 应用的问题,所以这个暂时不存在。我能想到的解决方案 其实也狠简单,把这些 jar 文件的url也做为扩展点出现,那么当jsp需要某个class时,只要把它 所需要的 jar 文件的 url 做为一个扩展,在 LauncherClassLoader 当中将这些jar文件添加到 url loader 当中,而这些 url 会出现在 jsp 的编译class path当中。

主站:http://blogsite.3322.org/jspwiki/

posted @ 2005-12-26 10:58 SimonLei 阅读(1276) | 评论 (0)编辑 收藏
一直以来,eclipse 对于 fragment 的概念都是一种补充,而不是覆盖的机制。 也就是说,fragment 里的 class 会在 host plugin 的 class 装载之后而装载。 只有 host plugin 里面没有找到,才会去找 fragment 里面的类。

我们的framework,目前是由一个专门的小组在维护。其他小组是不能随意改它的代码的。 但是,当有些情况下,使用这个framework的开发小组需要修改这部分代码,而这个修改 又只是局部的,只有这个小组需要用的,那么现在就很头痛。后来用一种jar替换的方式 来满足这个需要,但是搞得开发起来很繁琐,需要经常的export。

一直以来也没有去动 eclipse 的代码,这次把应用启动的模式从deploy改成launch 之后, 别的地方都好说,唯有需要处理 fragment 的这个地方很头痛。

如果把eclipse fragment的装载顺序调整一下,先装载 fragment 里的class,再装载 host plugin 里面的 class,这个问题就迎刃而解了。framework开发小组只需要处理 公用的代码,使用 framework 的小组就可以用自己的 fragment 去处理特殊的代码, 这个世界就清净了。大家都可以用 launch 这种模式来启动应用,加快应用开发的效率。

刚才改了一下,其实很简单,只是改 DefaultClassLoader 就行了,看一下代码就知道该 怎么改。后悔怎么没有早点改,呵呵。

主站: http://blogsite.3322.org/jspwiki/
posted @ 2005-12-15 14:01 SimonLei 阅读(1140) | 评论 (0)编辑 收藏

统计