2007年12月5日星期三

约定

王菲

还记得当天旅馆的门牌
还留住笑著离开的神态
当天整个城市那样轻快
沿路一起走半哩长街
还记得街灯照出一脸黄
还燃亮那份微温的便档
剪影的你轮廓太好看
凝住眼泪才敢细看
忘掉天地彷佛也想不起自己
仍未忘相约看漫天黄叶远飞
就算会与你分离凄绝的戏
要决心忘记我便记不起
明日天地只恐怕认不出自己
仍未忘跟你约定假如没有死
就算你壮阔胸膛不敌天气
两鬓斑白都可认得你
还记得当天吉他的和弦
还明白每段旋律的伏线
当天街角流过你声线
沿路旅程如歌褪变
就算你壮阔胸膛不敌天气
两鬓斑白都可认得你

2007年9月18日星期二

NetBeans 6.0 beta1 终于出来了!

经过“漫长”的等待,beta1 终于出来了!其实我一直在用它的最近的 daily build, 因为 M10 实在是太不稳定了。
beta1 给人的第一印象是,更换了主题(桌面 icon, welcome 页,向导图案),使用的是接近于 Vista 类似的蓝绿色调,给人以清新的感觉!
加紧试用吧!



2007年8月25日星期六

SUN 将股票代码 SUNW 换为 JAVA

作为SUN公司战略计划的一部分,其将老的股票代码SUNW退修,而取而代之 JAVA,
作为JAVA开发者,我们在高兴之余,你还想详细了解其 "java everywhere" 战略计划吗?
请看SUN总裁的BLOG(对,为数不多的CEO会写博客,Jonathan Schwartz 就是其中的一位,
而且他还留着马尾辫子。个性与成功并不矛盾!)

http://blogs.sun.com/jonathan/entry/java_is_everywhere

2007年8月15日星期三

Hibernate Jpetstore 之五 部署

文档内容
  • 概览
  • 获得工程代码
  • 配置
    • 数据库初始化
      • MySQL 5.x
      • Oracle 9i, 10g, HsqlDB, Postgres 及其它
    • 应用服务器初始化
      • 本地数据源(非JNDI 数据源)
        • Tomcat 5.x,
        • Sun Application Server8.x, 9.x / GlassFish 1.x, 2.x
        • Jetty 6.1.3
      • JNDI 数据源
        • Sun Application Server8.x, 9.x / GlassFish 1.x, 2.x
        • JBoss 4.0.4 +
        • Jetty 6.1.3
  • 部署并运行
  • 总结
PS: 为什么这个系列的最后一篇这么长时间才出来?原因是,我跟大家说过,工程的所有源代码最终将发布。所以我要找一个合适的地方上载。
这个过程还是比较烦的,况且老外们的工作效率普通不如我们,每次交流至少等上一周左右才有回应。试想申请、审批,确认,上载等过程,其实令我这个急性子试 图想把自己家里的电脑搬到主机托管中心,申请一个域名了事!

还好,它终于出来了 (hjpetstore)!但愿没让你失望。

在阅读本篇文章之前,请先仔细阅读前面系列的相关内容。

概览

对于传统的J2EE 项目,当项目开发完后,其工作并未结束,紧接着的部署过程其实是很令开发者头痛的,特别是象重量级的应用服务 WebLogic, WebSphere 等。还好 NetBeans 现在抬简化了这一过程。
我们这个例子是基于无存在数据库的方案,所以在我们演示结果前,我们将要导入一些数据。但首先我们得创建相应的数据库用户和数据库方案(Schema).

获得工程代码

1.从 hjpetstore 得到工程源代码,具体的步骤网站上有说明,在 NetBeans 中就很简单了:

CVS | checkout:
cvs root: :pserver:username@cvs.dev.java.net:/cvs (这个 username 是你必须到 java.net 上注册的用户名称,目前 anonymous 好象不能工作了)
password:

下一页中, module: hjpetstore 下载完后,NetBeans 会问你是否打开该工程,选择是。

2. 你可能需要调整一下lib 的位置,这是 NetBeans 的一个缺陷,保存的路径不是相对路径。
右击工程 | properties
点 Libraries,在Compile 页中将所有 .jar 文件 选中后 'remove',
再加入下载下来的WEB-INF/lib 目录下的所有 jar 文件

3. 确保 Clean And Build project 成功


配置

数据库初始化

我这里只介绍 MySql 的 配置,其它的数据库配置列作 TBD. (待做,其实大部分脚本已经在工程中了,等待你的加入吧!因为我不是一个数据库专家,也没有太多时间去研究这个。)我成功配置过oracle 和 hsqldb.

注 意:因为下面的脚本会删除 'hjpetstore'数据库用户及其所有资源,请确保用户 'hjpetstore' (oracle) 或数据库 hjpetstore (mysql) 目前没被使用,如果使用了,请修改数据库脚本。所以最好的办法是使用你的个人数据库来作演示。

MySQL 5.x


1. 创建用户hjpetstore 和 数据库 hjpetstore

# 在命令行下以 root 身份运行创建脚本
# $hjpetstore 是用真实的工程路径代替
# 其它值根据你的设置作相应的改变,比如你如果连非本机的数据库,那 'localhost' 就是那个机器在 ip 了
> mysql -h localhost -u root -p < $hjpetstore\conf\jpetstore_mysql.sql Enter password: ******** 如果程序的输出显示了 hjpetstore, 则表明成功了: Database information_schema
hjpetstore

mysql
...

或者,如果有mysql query browser 的话,用它直接运行如下命令也可:
-- frist drop database hjpetstore and user hjpetstore
drop database if exists hjpetstore;

create database hjpetstore;

-- create user hjpetstore and give the password hjpetstore
grant all privileges on hjpetstore.* to hjpetstore identified by 'hjpetstore';

show databases;

2. 得用 hibernate.hbm2ddl.auto 自动生成数据库方案
确保 web/WEB-INF/dataAccessContext-hibernate.xml 中 设置了 update

这个属性的具体含义,我在前面的系列中已经讲过了,在产品初始化,你就可以安全地把它注释掉。

3. 在 NetBeans 右击工程 Run project
这一步将所有的数据库表创建出来, 只是没有数据。

4. 加裁数据
使用 NetBeans Sql Editor
4.1 注册mysql 驱动
Runtime | DataBases 右击 -> new Driver
Add ... -> 导航到工程WEB-INF/lib/下的 mysql-connector-java-3.1.12-bin 点 OK

4.2 创建连接
右击刚注册的驱动 MySql (Connector/J driver) -> Connect using ....
Database URL: jdbc:mysql://localhost:3306/hjpetstore?useUnicode=true&characterEncoding=UTF-8
user name: hjpetstore
password: hjpetstore

点 Ok 后,在Databases 下应该会出现一个新的连接。

4.3 执行 SQL 脚本
1. 在 Files 窗口中导航到 db/mhsql/jpetstore-mysql-dataload.sql 并双击打开它
2. 在编辑器的工具条中 Connection: 选择 刚创建的数据库连接:jdbc:mysql://localhost:3306/hjpetstore?useUnicode=true&amp;amp;amp;amp;amp;amp;amp;amp;ampamp;characterEncoding=UTF-8
3. 点击编辑器工具条上,紧挨着下拉框的 run sql

确保没有显示错误信息。


Oracle 9i, 10g, HsqlDB, Postgres 及其它


数据库脚本都已经在工程中了,你所要做的就是利用这些数据库提供的工具创建一个用户 'hjpetstore',
之后的步骤与上述相同。


应用服务器初始化

本地数据源(非JNDI 数据源)


Tomcat 5.x,
事实上,工程默认是使用 Tomcat 服务器的,所以现在你根本不需要改动什么就可以运行工程了。
有关数据源的配置是在 web/META-INF/ context.xml 文件中

Sun Application Server8.x, 9.x / GlassFish 1.x, 2.x
同样的配置,只不过要生成一个 sun-web.xml 文件,
很好,NetBeans 会帮你自动产生,如下:
右击工程 -> Run | Server: 选择注册的Sun App Server (如果你还没注册 Sun App Server 的话,你需要先注册一下,具体步骤见相关文档)

此时,文件已经产生,右击工程 -> Run Project

Jetty 6.1.3
所有的配置文件已经在 WEB-INF 下了: jetty-web.xml, jetty-env.xml, 所以要做的只剩下将dist 上下生成的 hibernateJpetstore.war
放到 Jetty 的部署目录,还好这个目录跟 Tomcat 的目录同名叫 webapps

在 Jetty 目录下运行:
java -jar start.jar
然后在浏览器中请求: http://localhost:8080/hjpetstore/

JNDI 数据源


使用JNDI数据源当然是为了使用其 JTA(包容器管理的事务及其数据库连接池的实现),
只需要按正确的名称 jdbc/hjpetstore 在管理界面配好数据库连接池和相应的数据源,运行起来还是挺方便的,

Sun Application Server8.x, 9.x / GlassFish 1.x, 2.x
1. 首先按照这篇文章介绍的步骤正确配置 mysql 数据源连接池
(中文) http://pprun.blogspot.com/2007/05/glassfishsun-app-server.html
(English) http://enpprun.blogspot.com/2007/05/problem-in-setting-mysql-xa-datasource.html
注意,我文章中介绍的是使用root/root 作为用户名/密码,此时可以设置成hjpetstore/hjpetstore

2. 配置数据源
在应用服务器的 管理 界面 导航Resources | JDBC | JDBC Resources
点击右边主页面中的 new 后进入配置页面,填入:
JNDI Name: jdbc/hjpetstore
Pool Name: 选择前面配置的数据源:连接池:mysql
完成后点击 Ok


JBoss 4.0.4 +

1. 使用 JBoss 也许是冲着所谓的 #1 应用服务器而来的吧,但其配置有一些变化:
第一它实现了自己的一套日志方式,所以需要把 web.xml 中的

org.springframework.web.util.Log4jConfigListener

注释掉。

2. 它的数据源的配法也不相同,只需要将相应的数据库的配置文件(如:mysql-ds.xml ,内容见随后)放到
jboss-4.0.4.GA\server\default\deploy 目录下,
再在 jboss-4.0.4.GA\server\default\conf\login-config.xml 中加入:
    <application-policy name = "MySqlDbRealm">
<authentication>
<login-module code
= "org.jboss.resource.security.ConfiguredIdentityLoginModule" flag =
"required">
<module-option name ="principal">hjpetstore</module-option>
<module-option name ="userName">hjpetstore</module-option>
<module-option name ="password">hjpetstore</module-option>

<module-option name
="managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=hjpetstore-mysql</module-option>
</login-module>
</authentication>
</application-policy>
mysql-ds.xml 相应的内容如下:
    <?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>

<jndi-name>hjpetstore-mysql</jndi-name>
<connection-url>jdbc:mysql://localhost:3306/hjpetstore</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>hjpetstore</user-name>
<password>hjpetstore</password>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>

<!-- should only be used on drivers after 3.22.1 with "ping" support

<valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLValidConnectionChecker</valid-connection-checker-class-name>
-->
<!-- sql to call when
connection is created

<new-connection-sql>some arbitrary sql</new-connection-sql>
-->
<!-- sql to call on an
existing pooled connection when it is obtained from pool -
MySQLValidConnectionChecker is preferred for newer drivers

<check-valid-connection-sql>some arbitrary
sql</check-valid-connection-sql>

-->

<!-- corresponding
type-mapping in the standardjbosscmp-jdbc.xml (optional for ejb) -->
<metadata>

<type-mapping>mySQL</type-mapping>
</metadata>
</local-tx-datasource>
</datasources>


3. 还有,就是JBoss 的 JNDI 的名称有些怪:
    <bean id="dataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">

<!-- JBoss
-->

<property name="jndiName" value="java:/hjpetstore-mysql">

<!-- other standard Java EE server

<property name="jndiName"
value="java:comp/env/jdbc/hjpetstore">
-->
</bean>


看到区别了吗?它只需要java:/hjpetstore-mysql


Jetty 6.1.3
目前,还未测试成功!


部署并运行


在 NetBeans 中,只需要在 工程属性中选定所要运行的 服务器后,点 Run Project 即可运行在本地数据源配置上。
此外,还可以按照服务指定的自动部署目录,将生成的 dist/hibernateJpetstore.war 文件放到该目录,
如果服务器已经运行,一切就 ok 了,如果没有,启动服务器即可。

如果要运行在 JNDI 配置上,则需要改一下 web.xml :

<!--
- Location of the XML file that defines the root
application context.
- Applied by ContextLoaderServlet.
-->
<context-param>

<param-name>contextConfigLocation</param-name>

<!-- local datasource -->
<param-value>
/WEB-INF/dataAccessContext-hibernate.xml
/WEB-INF/applicationContext.xml
</param-value>
<!-- jndi datasource and JTA (for a transactional
JNDI DataSource)

<param-value>

/WEB-INF/dataAccessContext-hibernate-jndi.xml
/WEB-INF/applicationContext.xml
</param-value>
-->
</context-param>

这几行配置说的应该很明白了,上面的是默认情况下的本地数据源,如果使用JNDI数据源,是这样了:

<context-param>


<param-name>contextConfigLocation</param-name>



<!-- jndi datasource and JTA (for a
transactional JNDI DataSource) -->

<param-value>


/WEB-INF/dataAccessContext-hibernate-jndi.xml
/WEB-INF/applicationContext.xml

</param-value>



</context-param>


只要按照上述的步骤配置好了应用服务器的数据源,现在运行的效果应该跟本地数据源是一样的。


总结


NetBeans 对于 Java EE 的开发是全面的,除了几个服务器还未集成进来之外,其它的功能已经走在了所有IDE的最前列,
但这也不防碍开发者使用这些未集成的服务器,因为大部分服务器都支持热部署,当NetBeans 给你的工程生成了 WAR 文件后,
剩下的就是“将它放入热部署目录”了。


看运行在 Jetty6.1.3 上的效果 (注意脚注部分显示,当前运行在什么服务器上):

2007年8月14日星期二

爱因斯坦精神

[转载]
听过一个故事:以前有个小孩,很喜欢拉小提琴,却又拉得不怎么样。连他的父母也觉得这孩子没什么天分,因为琴声真的好难听。于是他求教于一位教授,教授 说:“你为什么要拉小提琴呢?你觉得你快乐吗?”小孩子说:“我想成为一个伟大的小提琴家!我觉得我拉小提琴很快乐。”“那你就不用太刻意去学了”教授 说,你只要觉得快乐就好。小孩于是明白了,他以后都只是把拉小提琴当作是一种生活享受。后来,他在物理领域获得了很大成功,成了改变世界的一个伟人。此人 就是爱因斯坦!!
我觉得我们应该学习他:学会放弃,只要你从中获得快乐,那么你就不要计较是否要获得成功。学会坦然处之。

今年是狭义相对论发表100周年,也是联合国确定的世界物理年,主要纪念伟大的物理学家和社会活动家爱因斯坦对人类所作出的多方面的巨大贡献。爱因斯坦是全身心献身科学和主张科学无国界的理想主义者,是强调科学技术应当以人为本的人道主义者,是具有强烈社会责任感、反对法西斯和主持正义的社会活动家。在人类发展史上,爱因斯坦占有光辉的位置。我们纪念爱因斯坦这位伟人,不仅要了解他在科学上所作出的重要贡献,更要学习他在任何困难条件下都一心为科学而献身的精神,学习他为社会公正和反对法西斯战争而无私无畏的奋斗精神。我们还应当通过爱因斯坦成长的道路,分析产生这样杰出人物的条件,努力为中国青年创造良好的学习和成长的环境,使优秀人才能够脱颖而出,使中国科学能够早日跻身世界先进行列。

一、爱因斯坦对物理学的重要贡献


在20世纪初古典物理学出现危机的关键时刻,爱因斯坦是推动物理学革命思想的一面光辉旗帜。他独自发现了狭义相对论和广义相对论,从根本上改变了传统的绝对时空观念,将时空、物质和作用力通过对称性统一起来。从狭义相对论出发,他提出了质量和能量等价的公式,开辟了原子能的时代。从广义相对论和核能出发,他和一批科学家发展了宇宙构造和起源的模式,他提出的宇宙常数预示了产生排斥力的暗能量的存在。他和普兰克及玻尔一起是量子论的主要奠基人,他提出了集波动性和粒子性于一身的光量子学说,解释了光电效应,促进了量子波动力学的发现。他发展了原子论和统计力学,解释了从布朗运动、固体比热到受激辐射等一系列现象,和玻色合作,建立了玻色—爱因斯坦量子统计理论,预见了玻色凝聚态的存在。他质疑量子力学提出的量子纠缠态,开辟了量子信息学的新领域。他在晚年致力于统一场论,虽然没有取得他预期的结果,但他提出的从高维几何局域对称性出发进行统一相互作用力的思想至今仍指导着基本相互作用大统一理论的发展方向,在他逝世后的半个世纪中,已经在弱电和强相互作用的统一中得到体现。

他的科学思想远远超越当时的时代,具有非凡的前瞻性和深刻性,以至他许多重要的理论发表以后,短期内得不到物理界的普遍认同。他的科学发现不是天才的灵机一动,而是通过自学掌握了当时最前沿的科学成就,经过多年艰苦的思索才完成的。他在高中最后一年,就已经学习了当时大学还未讲授的电动力学理论,并对和光一起运动会产生什么现象进行了思考,10年以后才发现了狭义相对论。他在1909年开始认识到加速度和重力的等价关系,经过6年的努力和多次的失败,才建立了正确的广义相对论引力方程。

相对论和量子力学是20世纪最重要的科学发现,不仅为我们提供了从微观夸克到宏观宇宙的物质和运动的图像和规律,丰富了我们的物质观和宇宙观,而且为20 世纪技术的发展提供了科学的基础。虽然爱因斯坦从事的是基础研究,他并不知道这些研究有什么实用价值,但是,越是基本的规律,覆盖的现象越广泛,潜在应用的面越广,产生的价值也越大。在微电子、激光、原子能、GPS、传感器、加速器、信息保密等等广泛应用的技术中都可以看到爱因斯坦研究成果的影响。

二、爱因斯坦的人生观和社会活动


爱因斯坦对他自己的人生观曾经说道:“要追究一个人自己或是一切生物生存的意义或目的,从客观的观点看来,我总觉得是愚蠢可笑的。可是每个人都有一定的理想,这种理想决定着他的努力和判断的方向。就在这个意义上,我从来不把安逸和享乐看作是生活目的本身——这种伦理基础,我叫它猪栏的理想。照亮我的道路,并且不断地给我新的勇气去愉快地正视生活的理想,是善、美和真。要是没有志同道合者之间的亲切感情,要不是全神贯注于客观世界——那个在艺术和科学工作领域里永远达不到的对象,那么在我看来,生活就会是空虚的。人们所努力追求的庸俗的目标——财产、虚荣、奢侈的生活——我总觉得都是可鄙的。”“当我还是一个相当早熟的少年的时候,我就已经深切地意识到,大多数人终生无休止地追逐的那些希望和努力是毫无价值的。而且,我不久就发现了这种追逐的残酷,这在当年较之今天是更加精心地用伪善和漂亮的字句掩饰着的。每个人只是因为有个胃,就注定要参与这种追逐。而且,由于参与这种追逐,他的胃是有可能得到满足的;但是,一个有思想、有感情的人却不能由此而得到满足。”“我每天上百次地提醒自己,我的精神生活和物质生活都依靠别人(包括活着的人和死去的人)的劳动。我必须尽力以同样的分量来报答我领受了的和至今还在领受的东西,我强烈地向往着简朴的生活,并常常为发现自己占有了同胞过多的劳动而难以忍受。”

他不仅是这样说,也是这样做的。在他创造力最丰富的青年时代,他的生活非常艰苦,经历过歧视和失业,但他从不屈服去追求庸俗的目标,而是全神贯注于科学研究。即使到美国定居以后,他主动要求不要给他很高的薪水,继续过着俭朴的生活。

在他就职柏林科学院不久,第一次世界大战爆发,他从头开始就公开反对这场战争。他说过:“我反对一切形式的战争,除非那个敌人以毁灭人类作为它的唯一目的”。为此,他遭到了当局的迫害和部分报纸的谴责。德国的失败使德国科学家处于孤立的困难境地。爱因斯坦虽有瑞士国籍,被邀请参加国际物理会议和到其它国家就职,但他认为,科学是全人类共同的事业,不应该因政治原因而孤立德国科学家。在德国科学家不被邀请的情况下,他也拒绝出席会议和离开柏林去他地就职。他说:“我曾对普朗克许下诺言,在这里的环境没恶化到普朗克本人承认我的离开是自然而然的和正确的之前,我不离开柏林。如果我不是迫不得已,而是哪怕是部分地出自物质利益便离开我的政治期望正在那里实现的国家,离开用爱和友谊来温暖我的人们,而在开始堕落的时期我的离开对他们来说可能会加倍地难受……那我就是忘恩负义了。”很可惜,他的民主和社会主义的政治期望并未在战后德国实现,法西斯上台后把他视为犹太人的领袖,加大了迫害的手段,迫使他移居美国。此后,他一直以他个人的威望反对法西斯和关心弱小民族的命运。他对中国人民的苦难深表同情,多次支持中国抗日和中国人民争取民主权利的斗争。

爱因斯坦多次告诫科学家要履行自己的社会职责。他说:“任何技术的应用都必须以人为本,关怀人的命运。”“要关心如何安排人的劳动和分配财富,以保证科学的成果用于造福人类,而不是用于破坏的那些尚未解决的大问题。”他还说:“国家是为人而存在,而不是相反,科学也是一样。”

三、爱因斯坦的教育思想和成长历程


爱因斯坦不是一个通常意义下循规蹈矩的好学生,他厌恶那些不尊重学生主动性和独立人格的灌输式教育,他在中学和大学都不为老师所看重。他在自述中写到: “有时,人们把学校简单地看作是一种工具,靠它来把大量的知识传授给成长中的一代。但这种看法是不正确的。知识是死的;而学校却要为活人服务。它应当发展青年人中那些有益于公共福利的品质和才能。但这并不是意味着个性应当消灭,而个人只变成像一只蜜蜂或蚂蚁那样仅仅是社会的一种工具。因为一个由没有个人独创性和个人志愿的规格、统一的个人所组成的社会,将是一个没有发展可能的不幸的社会。相反地,学校的目标应当是培养有独立行动和独立思考的个人,不过他们要把为社会服务看作是自己人生的最高目的。”他还说:“自由行动和自我负责的教育,比起那种依赖训练、外界权威和追求名利的教育来,是多么的优越呀。真正的民主决不是虚幻的空想。”他从小就需要自由的时空和选择来安排自己的学习,他很少听课,利用同学的笔记对付强制的考试,他说:“尽管摆在我们面前的课程本身都是有意义的,可是我仍要花费很大的力气才能基本上学会这些东西。对于像我这样爱好沉思的人来说,大学教育并不总是有益的。无论多好的食物强迫吃下去,总有一天会把胃口和肚子搞坏的。纯真的好奇心的火花会渐渐地熄灭。幸运的是,对我来说,这种智力的低落在我学习年代的幸福结束之后只持续了一年。” “事实上,现代的教学方法还没有把神圣的求知欲完全扼杀掉,这差不多是一个奇迹;因为这株脆弱的幼苗,除了需要鼓励之外,首先需要自由——没有自由它将不可避免地会夭折”。

给一位教授的求情信这样写到:“亲爱的教授:请原谅一个父亲为了他儿子的事情来打搅您。……我的儿子目前失业,这使他深感难过。他越来越觉得,他的事业已经失败,再也无可挽回。而最使他沮丧的是,他感到自己是我们的负担,因为我们的景况不好……”这位教授是否给过帮助,现在已无从了解,但可以肯定大学的教授们从未认为爱因斯坦是个做学问的人才。

1902年,在同学格罗斯曼的父亲的帮助下,爱因斯坦获得了瑞士专利局职员的工作,才得以靠微薄的收入维持一家的生活,而在1905年发表的改变20世纪物理学面貌的5篇重要论文则是他业余时间的创作。爱因斯坦在专利局工作到1909年,才有大学聘请他为副教授。对这7年的生活,他回顾到:“在我最富于创造性活动的1902~1909年这几年中,我就不用为生活而操心了。即使完全不提这一点,明确规定技术专利权的工作,对我来说也是一种真正的幸福。它迫使你从事多方面的思考,它对物理的思索也有重大的激励作用。总之,对于我这样的人,一种实际工作的职业就是一种绝大的幸福。因为学院生活会把一个年轻人置于这样一种被动的地位:不得不去写大量科学论文——结果是趋于浅薄,这只有那些具有坚强意志的人才能顶得住。然而大多数实际工作却完全不是这样……作为一个平民,他的日常生活并不靠特殊的智慧。如果他对科学深感兴趣,他就可以在本职工作之外埋头研究他所爱好的问题。不必担心他的努力会毫无成果。”

四、留给我们的思考


爱因斯坦的一生多姿多彩,光辉伟大。他在艰苦条件下坚持献身科学的理想,他维护正义、反对法西斯和强调以人为本的社会责任感,他不唯上、不唯书、不迷信权威、不惧怕困难、不为世俗名利动心、不受传统制度和观点的束缚,独立自主,自由思考,刨根到底地追求科学真理。敢想敢干,敢于超越!

2007年8月10日星期五

Java 7 语言级的改动

到目前为止,Java7 已经有如下议案:

  • Language-level XML support (语言级的XML支持)

  • Closures (闭包,目前 Java 匿名类担任部分这一角色)

  • Block constructs (块结构)

  • Strings in switch statements (允许 String 作为 switch 语句的开关值)

  • Language support for BigDecimal (语言级支持 BigDecimal, 目的是减小 double 不够用的压力)

  • Java property support (语言级属性支持,目前我们熟悉了 getter/setter)

  • Lightweight method references (轻量级方法引用,目前如果不通过反射是无法完成对方法引用对象的传递)

  • Extensions to the annotation mechanisms (进一步扩充 annotation - 元数据机制)

  • Java Module System (模块系统,解决头疼的 CLASSPATH 问题)


其实我个人关心的是: reified generics (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5098163)
如果这个未实现的话,设计generics (泛型)类(注意,我没说使用泛型)仍然会是一种痛苦。

相信随着时间的推移,各种介绍会陆续出现,这些概念也慢慢会一目了然。

详细信息见 javac 作者的 blog:
Neal Gafter: http://gafter.blogspot.com/
Peter Ahé: http://blogs.sun.com/ahe/
因为 JDK 已经成为了 OpenJDK 了,所以以上两位作者事实上都已经离开了SUN,
开发 javac 的责任留给了 java 社团,也许你就是其中一位了!

2007年7月8日星期日

Open NetBeans 6 module project with NetBeans 5.x

要打开 NetBeans 6 的源代码工程,最方便的当然是使用配套的最新的开发版,但由于开发版或多或少会不稳定(特别是最近的M10)。所以还是要使用稳定的 release 版本来打开或者开发。
但是由于平台的兼容性问题,在尝试 NetBeans 5.5 来打开从 NetBeans CVS checkout 或下载下来的源代码模块工程时,同样也遇到了问题:在打开对话框中 Project Name 中会以红色显示:
java.io.IOException:
Misconfigured project in ... has no defined "code-name-base"


经过一番周折,我打到一个解决办法:

1. 在 NetBeans 5.x 中注册安装的 NetBeans 6.0 平台 Tools | NetBeans Platform Manager -> Add Platform... , 选择NB6 的安装目录
1.1 在 Harness TAB 中要确保选择第二项 "Harness supplied with Platform", 默认好象是第一项"Harness supplied with IDE" (如果工程使用新的平台中的一些API的话,第一项显然是不对的。) 
1.2 记住 "Platform Name" 的值,因为下面要用到,所以最好拷贝一下。


2. 修改要打开的NetBeans 模块工程的 $工程目录\nbproject\project.xml 文件
<data xmlns="http://www.netbeans.org/ns/nb-module-project/
这个值在 NetBeans 6 中为 <data xmlns="http://www.netbeans.org/ns/nb-module-project/

也就是将新版中使用的命名空间定义"3" 回退到 NetBeans 5.x 使用的 "2"

3. 在要打开的NetBeans 模块工程的 $工程目录\nbproject\ 的目录下,增加 platform.properties 文件, 其内容为:
nbplatform.active=NetBeans_IDE_6.0_M10_(build_200706281431)

即让它指向前面记下的 “Platform Name” 的值:


4. 现在打开试试! (你们也许还会遇到其它问题,因为我也记不清是否改了其它配置)

5. 最后,我还遇到一问题,右击工程 | properties
弹出一个对话框说"没找到定义的平台,回退到默认的平台", 我没办法,只有选择是,然后进入到工程属性中后:
Libraries -> NetBeans Platform 把它给改回来

6. build 试试!


好运!

2007年7月6日星期五

小心 Java SE 6 U2

Java SE 6 U2 修复了不少关键的BUG,正因为此,我也迫不急待地更新了。
但是,我发现文件选择对话框(JFilechooser)简直慢如蜗牛了。
请参见这里的讨论:javalobby !

由于个人习惯,在新版本到来后,就会把老版本删除掉。可这次,我简直太无奈了,
java.sun.com 竟然也找不到 U1 的下载链接了,而笔记本又没带回来!
我不得 Google 一番才在国内的下载网站找到了。

我使用的操作系统 WindowsXp.

小心,各位!

2007年7月2日星期一

Hibernate 处理大数据量的方案

问题:OutOfMemoryException


大家知道,Hibernate 有 一级 cache (Session 级) 和二级 cache (需另外配置,如 ehcache),
以下代码,Hibernate 在处理到大约50000条记录时,就会抛出 OutOfMemoryException, 这是因为,Hibernate 把所有新建的 MiniMessage 对象都放在了 Session 级的缓存中了。

Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
tx = session.beginTransaction();
for(int i=0; i<300000; i++ ) {
System.out.println(i + ".................");
MiniMessage message = new MiniMessage("Hello World" + i);
session.save(message);

}

tx.commit();

} catch (HibernateException he) {
tx.rollback();
throw he;
} finally {
session.close();
}

解决办法:


使用"批处理”(Batch process)
Session session = null;

try {
session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = session.beginTransaction();

for(int i=0; i<200000; i++ ) {
log.debug(i + ".................");

MiniMessage message = new MiniMessage("Hello World" + (i+1));
session.save(message);
if ( i % 100 == 0 ) {
//100, same as the JDBC batch size set in xml file:
// <property name="hibernate.jdbc.batch_size">100</property>
//flush a batch of inserts and release memory:
log.debug("fulsh at : " + i + ".................");

session.flush();
session.clear();
}
}


session.getTransaction().commit();
} catch (HibernateException he) {

session.getTransaction().rollback();

throw he;
}


在这种情况下,需要在hibernate.cfg.xml 配置几个参数来达到更好的效果:

1. 配置批处理的大小


 <property name="hibernate.jdbc.batch_size">100</property> 

2. 放弃二级缓存:



<!-- Disable the second-level cache because the
batch process is one-off process. -->

<property
name="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</property>


<property
name="hibernate.cache.use_second_level_cache">false</property>

<property
name="hibernate.cache.use_query_cache">false</property>

<property
name="hibernate.cache.use_minimal_puts">false</property>

这样,Hibernate 会在每 100 个插入后,与数据库同步一次,并将一级缓存中的实体对象清除。

2007年6月15日星期五

Blogsport 又被封了!

最近收到一些邮件说没法访问我的博客,
众所周知的原因,但我们大家还是可以绕个弯吧:

以下是摘自 GG 派的文章

可以同时采用两种方法双管齐下来规避封锁。

第一个方法是修改host文件:
首先把自己的或想访问的博客网址按规则添加进下面这个大家共同编辑的wiki页里:
http://groups.google.com/group/ggpi/web/hostwiki
然后用记事本打开C:\WINDOWS\system32\drivers\etc\hosts文件,然后把上面那个页面的内容全部复制进去即可


第二个方法:
首先打开Notepad(或者其他的编辑器),写入如下内容(是程序员都应该明白这个方法的意思):

function FindProxyForURL(url,host){
if(dnsDomainIs(host, ".blogspot.com")){
return "PROXY 72.14.219.190:80";
}
}

另存为proxy.pac到C盘的根目录下或者其它地方,然后对FireFox或IE7进行设置:
Firefox: 打开Firefox,依次点击工具->选项-> 高级->网络->设置...->选中自动代理配置url,在下面填写:
file:///C:/proxy.pac
再点:重新载入 ,然后一路确定下去就可以了。

IE7:打开IE7,依次点击工具->Internet选项->连接->局域网设置->选中使用自动配置脚本,在下面填写:
file:///C:/proxy.pac
再点确定,就可以了。这个方法的巧妙之处在于保证了所有blogspot的子域名可以没有限制的访问(内含 GFW关键字的除外)。问题在于这种方法似乎对某些IE浏览器支持不是很好,经常有问题。

Cheers!

2007年6月7日星期四

Java 安全拷贝协议 (JSCP: Java Secure Copy Protocol) NetBeans 插件

JSCP NetBeans 插件的作用


大家知道,SCP 广泛使用于SSH出现之前的 Unix 之类的平台上,它允许在 Client <-> Server 间进行双向的文件传输(ScpTo, ScpFrom)

JSCP NetBeans plugin 作为一个 TopComponet 插入到 NetBeans 的 Navigator 方位,通过 Tools | Java SCP 调用。

SCP 可进行文件双向传输的
  • 向支持 SCP 的 Unix/Linux 服务器上传文件(ScpTo)
  • 从支持SCP的 Unix/Linux 服务器获得文件(ScpFrom)

这两种工作模式是分别作为 JTabbedPane 的 两个 Tab 出现在 JScp 这个 TopComponent

JSCP NetBeans 插件的使用方法

从NetBeans PluginPortal 网站上获得一个压缩包,然后解压到一个目录供下面的步骤使用。

安装 .NBM 文件

  1. Tools | Update Center
  2. 选择 Install Manually Downloaded Modules (.nbm Files) 后,点击 Next
  3. 点击 Add... , 在 Select Directory or .nbm Files 对话框中,导航到此插件的两个 .nbm 文件(com-jcraft-jsch.nbm 和 org.pprun-jscp.nbm),同时选中它们后点击 Ok
  4. 点击 Next
  5. 点击 Next
  6. 点击 Next, 在View Certificates and Install Modules 界面点击 Include 列下面的多选框中打上勾。界面将出现版权及插件签名信息。(如果你希望使用计算机的所有用户都使用这个插件,可以将在 Global 列下打勾)
  7. Finish, 不出意外,将显示插件更新界面。
  8. 等到NetBeans 的状态条中显示 Turing on modules... done. 后,点击 Tools 菜单,此时将在菜单最底端看到 Java SCP 菜单项,如下:


使用说明

前提条件:

  • 保证网络可以访问到一台支持 SCP/ SSH1 的 Unix/Linux 服务器
  • 保证具有以上服务器上的一个帐户并且对其中的一个目录具有“写”权限(如果你只使用 ScpFrom 的话,此项可选)

ScpTo (文件上传)


(如果还没打开 JScp Window 的话)通过 Tools | Java SCP 打开,它会出现在左下角并停靠在 Navigator 所在的窗口中,如下图所示:

  1. LocalFile 上传的文件,通过右边的按钮来选择
  2. User@Host 用户名和主机名(或IP地址) 的组合
  3. Password 上述用户的密码
  4. RemoteDir 上传的文件在服务器上放置的目录


请注意在输入的过程中,会动态对输入域的值进行校验,如下,桔色的字显示没有指定服务器主机名(或IP地址):



如果所有的输入都合法的话,按钮 Scp 将可用,点击它将进行网络传输,进度条指示这一过程:



如果一切正常,最终进度条将停止指示。反之,如果后台操作出现错误的话,错误将显示:




ScpFrom (文件下载)


(如果还没打开 JScp Window 的话)通过 Tools | Java SCP 打开,它会出现在左下角并停靠在 Navigator 所在的窗口中,如下图所示:

  1. User@Host 用户名和主机名(或IP地址) 的组合
  2. Password 上述用户的密码
  3. RemoteFile 要下载的服务器上的文件
  4. LocalDir 下载的文件放置的目录,通过右边的按钮来选择




如果所有的输入都合法的话,按钮 Scp 将可用,点击它将进行网络传输。


总结


自从 NetBeans 5.0 开始,编写基于 NetBeans 的插件或平台应用已经变得非常简单。对于新来者,最大的障碍无非是一些NetBeans专用的术语及早期遗留下来的几个不大好理解的概念。不过还好, NetBeans 自己在快速前进的同时并没有忘记为开发者提供便利。
NetBeans wiki 是各种信息的大轮盘
planetnetbeans 则是全世界NetBeans开发者的乐园。大家为了 NetBeans 开怀畅谈。
Geertjan's Weblog 不得不看

2007年6月1日星期五

试用GlassFish V2,赢取 52 吋液晶电视机



只要下载并试用 GlassFishSun Java System Application Server 9.1 Beta 2 ( Java EE 5 SDK Update 3 Preview 2 或 Java Application Platform SDK Update 3 Preview 2) 并将使用效果反馈给SUN(通过BLOG或直接提交表单),就有机会羸取上面的52英吋液晶电视机。 

详细情况见,规则见.

2007年5月25日星期五

软件的脆弱:从二分法查找的BUG说开去

大概是在去年的七月份左右,我首先在 javalobby 上看到这篇。当时也无比震惊,因为JDK (1.5及之前的版本) 中 Arrays.binarySearch(int[] a, int key) 及 Collections.binarySearch(int[] a, int key) (其调用indexedBinarySearch) 存在一个在业界隐藏了几十年的BUG,而这两个方法的作者恰恰是两位高人实现:

* @author Josh Bloch
* @author Neal Gafter

我想在Java 领域呆的比较长的开发者应该会有所耳闻吧,Josh Bloch 被称之为 "Java 之母"(虽然他是一位男性),因为 java collection 框架,java.math, 泛型 及《Effective Java Programming Language Guide》都出自他之手;而 Neal Gafter 则是 我们每天都用的JAVA编译器 Javac 的实现者。


我们先看有问题的代码:

public static int binarySearch(int[] a, int key) {
int low = 0;
int high = a.length-1;

while (low <= high) {
int mid = (low + high) >> 1;
int midVal = a[mid];

if (midVal < low =" mid"> key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}

有问题的代码是这一行:
int mid = (low + high) >> 1; 

大家知道,其等价于:
int mid =(low + high) / 2;

问题是在 low 和 high 都很大时,比如数组的元素达到 2^30 时,low + high 将超过整数的最大值 2^31 -1,此时将造成溢流,溢流后得到的 mid 为负值。

正确的实现应该为:
             int mid = low + ((high - low) / 2);

或者更加清楚地使用Java的无符号右移操作符:
            int mid = (low + high) >>> 1;

虽然这个问题目前得到解决,我们就能断定这十几行程序就准确无误吗?
但连以上两位作者目前也还表示怀疑。
从行内得知,第一个二分法算法是1946年出现的,而当时被认为“无误”的实现到1962年才出现(也就是说以上十几行代码是经过十几年才得到的)。因为当时的数据量不可能逼近 2 ^ 30的数量级,所以直到去年这个BUG被提交到 Java 的 Bug 库中。可想人类的思维是有缺陷的。

目前,对于搜索引擎,基因工程领域,这一数量级应该是少见多怪了,所以如果你工作的领域需要处理大量的数据时,请使用 JDK 6.0

顺便提一句,对于C的实现,可以采用如下实现:
mid = ((unsigned) (low + high)) >> 1;
看到这样的情况,作为程序员,我们应该时刻警惕、保持低调!

2007年5月24日星期四

NetBeans 5.5.1 发布了

在我们大谈特谈 NetBeans 6.0 时,一个中间版本 5.5.1 出来了。
也许是因为6.0 引入了太多的新功能,致使开发周期比以往稍显长些。所以这个中间版本主要是为了跟进最新的产品线:
  • 支持Java EE 5 Application Server 9.1 (GlassFish v2)
  • 支持Windows Vista
  • C/C++ Pack 有很大的提升(这可是我亲自感受到的耶)
  • 还有我们可能不大关心的,但却是目前最完善的,支持J2ME Wireless Toolkit, version 2.5.1 平台

感兴趣的话,到这里下载

不过,过不了多久,它将被 NetBeans 6.0 所取代的,也许就在秋天!

2007年5月23日星期三

NetBeans6 功能介绍: 布置 declaration View 和 Javadoc View

此篇文章介绍一个在 NetBeans 6 中同时查看鼠标指针处的源代码和
Javadoc (不再Go to Source .../ Show JavaDoc)

1. 首先打开它们:Window | Other | Declaration View 和 Window | Other | Javadoc View, 它们都被搁浅在 Output 窗口的位置,但此时只能看到一个窗口的内容,因为无论切换到其中的任何一个,它们都占据整个下端窗口。如下:



2. 我们要将它们分开,点击其中任一窗口的上方(类似标题栏区域),按住不放,将其拖向左侧(或右侧也可),当出现一个红色的方框后释放,如下:



释放后的效果如下:




这些位置会被记录下来,只要你在设置之后正常退出了。在下次启动 NetBeans 后,你可以看到同样的布局。

这个截图中显示的是 Integer.toHexString 方法的 Javadoc 和 实现源码。


(期待下一篇)

SwingWorker for you

想必大家已经知道 SwingWorker 已经加入到了 javax.swing 包中了。它的前身经过好几个阶段改进的,如果你阅读网上的例子就会发现你阅读的例子跟你下载的包不兼容。
SwingWorker 在被正式加入到JDK6中之前叫做:org.jdesktop.swingworker.SwingWorker.java, 除了这个类之外,还包括 org.jdesktop.swingworker.AccumulativeRunnable.java 和 org.jdesktop.swingworker.SwingPropertyChangeSupport.java. 我并不打算深入介绍这几个类的源码,而是利用实际的例子来描述 SwingWorker 给 GUI 程序带来的便利。

如果写过GUI程序的开发者肯定对界面的响应度及界面冻结会有所了解。首先我得说明的是,这个问题并不是SWING特有的,所有的GUI框架如果没有处理 好都会存在这种问题,举例来说,
1. 在网络不好的环境下,在 windows 的文件浏览器中请求一个FTP地址或任何服务器的地址时,我们可以看到“灰块”(所谓灰块,是由于界面元素刷新队列被某个长时间的任务给阻塞,造成本该立 即刷新的界面得不到处理,显示出来的效果就是一块被扯得扭曲了的区域。)
2. 用过 PLSQL Developer 的开发者肯定也体会过屏幕冻结的感受吧。


费话少说,进入我们的 SwingWorker 之旅。

SwingWorker有几个重要的概念:
  1. 初始线程(Initial threads) 一般来讲是应用的主线程 (运行main 方法的那个线程) 
  2. 工作者线程(Worker Thread) 在主线程中生成的,用于执行那些长时间操作的线程
  3. 事件调度线程(Event Dispath Thread) 所有界面相关的行为都应该在这个线程进行,并且一定要保持快速的响应。
如下图是利用 NetBeans Profile 监控到线程:
  • main - 初始线程
  • Our Swingworker #1 - 工作者线程
  • AWT-Envent-Queue-0 事件调度线程
  • 其它的线程不在我们感兴趣之列




我们要记住的是:
  • 所有长时间的操作都不应该放在事件调度线程(EDT-Event Dispatch Thread,专门用来处理与界面响应相关的操作)中,否则界面在这段时间内将变得无法响应。
  • 所有对SWING组件的更新(在其已经被显示出去后)都应当通过EDT来访问,否则有可能造成线程死锁或界面根本没有反映作出的更改。
不要被前面这几段弄晕了,只要弄清楚了 Swing 的线程体系,其实大部分工作JDK 已经为你做好了。我们所要做的就是按照范例实现我们的代码。这样就肯定安全可靠。


我们的例子是一个登录界面,这个界面要求输入用户名与密码,然后点击登录,正常情况下将与中心数据库进行通信。但考虑到文章的长度,我们将使用 Thread.sleep 来演示和长时间的网络操作。

最终的界面将如下所示,我们这里也不介绍怎样制作界面(是的,我的确是使用 NetBeans 的 Gui Builder 来制作的,但使用了一个自定义的 JImagePanel)




如果阅读过别人的代码或自己认真写过SWING方面的代码,在没有使用 SwingWorker 的 GUI 工程中,一定会有如下代码:

java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
// 长时间的操作
}
});


这样做的目的就是为了使长时间的操作在另外的线程中运行。

为了使用面象对象的方式来处理这种行为,我们现在使用 SwingWorker。下面是我们的例子的代码:


import org.jdesktop.swingworker.SwingWorker;
import org.pprun.interviewofprologic.db.domain.UserBusinessDelegate;

/**
* Worker thread for login operation.
* @author pprun
*/
public class LoginSwingWorker extends SwingWorker {
private String username;
private char[] password;

private Exception exception;

/** Creates a new instance of LoginSwingWorker */
public LoginSwingWorker(String aUserName, char[] aPassword) {
this.username = aUserName;
this.password = aPassword;
}

/**
* 所有的后台操作都在这里,如果要动态将处理的数据发出去的话(比如数据库查询的应用),
* 可以在这里调用 publish 方法.
*/
@Override
protected Boolean doInBackground() throws Exception {
try {
// 我们注释掉了这段代码,取而代之以假想的 Thread.sleep
// UserBusinessDelegate cbd = UserBusinessDelegate.getInstance();
// final boolean result = cbd.login(username, password);

//return result;

try {
Thread.sleep(5000);

} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}

return true; // 如果想看看登录失败时的效果,return false;

} catch( Exception anyException ) {
exception = anyException;
throw exception;
}
}


/**
* Returns the exception thrown by the method doInBackground, if any, or
* null if no exception was generated.
* @return The exception generated by the call to doInBackground, or null
* if no exception was generated.
*/
public Exception getDoInBackgroundException() {
return exception;
}
}



在触发端,点击 Ok 按钮时:


private void okJButtonActionPerformed(java.awt.event.ActionEvent evt) {
// ...

loginSwingworker = new LoginSwingWorker(username, password);

loginSwingworker.addPropertyChangeListener(this);
loginSwingworker.execute();

// ...
}



属性改变监听器的实现方法,监听在 SwingWorker 中的改变:


public void propertyChange(PropertyChangeEvent pce) {
if (pce.getSource() == loginSwingworker) {
// property change event coming from the loginSwingworker
if (pce.getPropertyName().equals("state") &&
loginSwingworker.getState() == SwingWorker.StateValue.DONE ) {
// loginSwingWorker 完成,但有可能抛出异常
loginSwingworker.removePropertyChangeListener( this );
if (loginSwingworker.getDoInBackgroundException() != null ) {
// 抛出异常
if (true) {
infoJLabel.setText("Error in login!");
} else {

infoJLabel.setText("Error in login!");
}
}

} else if (loginSwingworker.isCancelled()) {
// loginSwingowrker 被取消时的代码
}
}



关于在 Swing 中使用并发的详细资料,参见 Concurrency in Swing

2007年5月22日星期二

体验更多 NetBeans 的新功能

不喜欢 NetBeans 的开发者往往指出 NetBeans 没有这个功能,没有那个功能。无可厚非,当时他们是对的,但随着时间的推移,现在也许错了:

1. Last Edit (是近更改按钮,带星号的那个),将你带到最近更改的地方




2. Diff SideBar (差异侧条), 根据所在行代码是增加、更改还是删除,在侧条中显示不同的小条,右击可以使用进一步的功能



3. JUnit4 支持(也就是现在可以使用基于 JDK 5 Annotation 的单元测试了)




4. Find/Replace in Project (全工程范围内搜索),是的,这个功能我真的也非常需要:
看到左下方的"Replace" 按钮了吗?
值得注意的是,这个功能在 M9 中被屏蔽了,但在每日构建的版本中可以使用。

[nb-find-replace.png]



另外,大部分初次使用NetBeans 的开发者,不知道更改“自动完成弹出窗口”的键绑定,因为最常用的"Ctrl + 空格" 是不可工作的,因为在中文操作系统中被绑定到输入法的切换了。所以我一般把它改成 'Ctrl + Enter' , 如下进行:
  1. Tools | Options -> Keymap -> Other
  2. 找到 Show Code Completion Popup, 选中它,点击Add...
  3. 按下任何所你希望的键序列,但是如果直接按 Ctrl + Enter 的话,系统提示这个组合键已经被绑定到 Split Line,所以如果我们要使用这个组合键的话,要先把它与 Split Line 解除绑定
  4. 在 Show Code completion Popup 下方第六个即是 Split Line, 选中它,点击移除。你可以为这个功能提供另外的组合键,如果经常使用这一功能的话。
  5. 然后,按照上述把"Ctrl + Enter " 加到 Show Code Completion Popup 中去。

(期待下一篇)

2007年5月18日星期五

GlassFish/Sun App Server 配置 MySqlXADataSource 的问题

如果你打算使用 GlassFish/Sun App Server,并且打算使用 MySql 的 XA 数据源的话。在目前的配置过程中,会遇到如下问题:

重现步骤:
1. (如果之前没做这一步的话)将 Mysql 的 Connector/J 包 (如我的:mysql-connector-java-3.1.12-bin.jar)放入 GlassFish/Sun App Server 安装目录下子目录 \AppServer\lib\ 中

2. 启动 GlassFish/Sun App Server. 可通过 右击 Runtime | Servers | Sun App Server 选择 start

3. 启动后,右击 Sun App Server 选择 View Admin console

4. 登录WEB 管理后台

5. 在左侧导航器中 点击 Resources | JDBC | Connection Pool s,在表格的头部点击 New... 按钮

6. 在右侧中填入:
Name: MySql
Resource Type: javax.sql.XADataSource
Database Vendor: mysql

然后点击 next

7. 注意在 Datasource class name 中自动填入了: com.mysql.jdbc.jdbc2.optional.MysqlXaConnectionPoolDataSource,这个值是不对的。

你如果想试试的话,在最下面的 Properties 窗格中填入 :


点击 Finish

8. 在结果窗口中点击 Mysql

9. 在打开的页面中可以看到一个ping 按钮,点击是用来测试配置成功与否,点击一下,将出现如下错误:


解决的办法:
如果解开mysql-connector-java-3.1.12-bin.jar 文件,在包com.mysql.jdbc.jdbc2.optional 中可 看到:

com/mysql/jdbc/jdbc2/optional/
com/mysql/jdbc/jdbc2/optional/CallableStatementWrapper.class
com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.class
com/mysql/jdbc/jdbc2/optional/MysqlConnectionPoolDataSource.class
com/mysql/jdbc/jdbc2/optional/MysqlDataSource.class
com/mysql/jdbc/jdbc2/optional/MysqlDataSourceFactory.class
com/mysql/jdbc/jdbc2/optional/MysqlPooledConnection.class
com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.class
com/mysql/jdbc/jdbc2/optional/MysqlXADataSource.class
com/mysql/jdbc/jdbc2/optional/MysqlXAException.class
com/mysql/jdbc/jdbc2/optional/MysqlXid.class
com/mysql/jdbc/jdbc2/optional/PreparedStatementWrapper.class
com/mysql/jdbc/jdbc2/optional/StatementWrapper.class
com/mysql/jdbc/jdbc2/optional/SuspendableXAConnection.class

...
其中并没有默认填入的 com.mysql.jdbc.jdbc2.optional.MysqlXaConnectionPoolDataSource, 但是有 com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource

在页面Application Server > Resources > JDBC > Connection Pools > MySql 中:
1.将 Datasource class name 的值改为: com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource

2.点击 Save 按钮

3. 点击 Ping 按钮,成功显示:

2007年5月16日星期三

NetBeans多语言版本,更换默认 Locale 设置时的问题

update: (这个BUG只会在中文操作系统下出现,在英文版的操作系统上一切正常。看来是一些模块在编写时没有正确地加载对应locale 的 properties 文件)

在我看来,在日常的工作平台,JDK/NetBeans 的i18n 字体问题已经成为历史了。但是我前些天又登记了一个 BUG 到 NetBeans 的 IssueZilla 中:

1. 下载多语言版本的安装包,安装
2. 因为我不喜欢那些翻译的不准确的词,所以我打算回退到英文的 locale:
增加一个启动参数到 $NetBeans/etc/netbeans.conf 文件:
netbeans_default_options="$默认的配置 --locale en"
语法为: --locale language[:country[:variant]]

3. 重启后,你将看到“著名的字体问题”重新又出现了,显示为小方框:

当前,只有两种办法可以解决这一问题:

1. 去掉加上的 locale 参数,但必须忍受翻译得不佳的词了。

2. 下载英文版,继续用吧。但这样的话,在 Welcome 中你将看不到中文的 Blog.

2007年5月2日星期三

NetBeans 6.0 抢先试用

NetBeans 6.0 M9 (Preview) 已经出来好些天了,还剩下最后一个里程碑就要进入测试阶段。

对我来说,自从从 Oracle JDeveloper 转向 NetBeans 以来,在工作中我一直坚持用它。也许是的我工作表现迫使远在美国那边的同事放弃了说服我使用 Eclipse 吧。你也许想知道,作为一名NetBeans 的老用户,我期待 6.0 的什么,虽然它已经很好了。

1.不要因为整个 Editor 的体系重组,而使强“稳定性”的口碑打折扣 (基本上大部分模块都重新Retouche了),因为我拒绝使用 Eclipse 的原因之一就是: JVM OutOfMemoryError.

2.Occurrences Highlight 我在之前的文章中写过关于这一功能


3.Javadoc and Declaration View 我已经等了好几年,我甚至曾经自己利用 NetBeans 的API 实现过一个类似的模块,但是因为NetBeans本身的问题(java meta data record),功能不完整。有了这两个窗口,就永远不用 Go to Source, Show JavaDoc 了,所有的信息都在手边,只需将鼠标放在想看的类元素上。



4.Code Generation dialog 我的确很厌倦写类的构造器的实现,特别是类的成员很多的情况下。还有标准的、功能完善的、性能良好的 Common Methods: equals, hashcode 的实现等。
有了它,在右图中的例子中我只需要输入
private long id;
private String name;
private int age;

其它的代码都是由它产生的。

5. Local History

或许有些功能被我忽视了,如是这样的话,请见此处的详细列表。还有整个重写的 Editor 的功能都陆续地出现在


是的,我也保留些目前还未完善的功能,我本人也没有加紧试用。如果我认为有用的话,我会进一步写出来的。

2007年3月15日星期四

Mark Occurrences in NetBeans

Mark Occurrences (元素高亮)指的是当鼠标放在某个类元素上时,在当前文件高亮出该元素的 声明和引用。
如果你使用过 Find Usages 的话,你应该能知道这个功能的好处。但是 Mark Occurrences 比起 Find Usages 来属于轻量级的。因为:
  1. Mark Occurrences 只搜索当前文件
  2. Mark Occurrences 为动态的,不需要菜单来激活只需要将鼠标放在要查看的元素上即可。
  3. Mark Occurrences 懂得语义,比如将鼠标指向当前类的超类,它将显示所有被实现/覆盖的方法;放在方法的返回类型上,将显示方法的所有返回的语句上;...
如果你使用的是 NetBeans 6.0 的开发版的话,这个功能已经内置了,不过它被叫做 Highlights:

  • 成员作用域


  • 方法返回点

  • 特定异常抛出点




如果你使用的是 NetBeans 5.x 系列的话,你需要注册一个更新中心,然后下载插件,具体步骤如下:
  1. 选择 Tools | Options
  2. 单击 Advanced Options 按钮
  3. 选择 Options | IDE Configuration | System | Autoupdate Types
  4. 右击并选择 New | General Update Center
  5. Name 输入域中输入Sandip Chitale's Modules 然后单击 Finish
  6. (此步骤不必,如果你在完成上述步骤后立即进行下面的步骤时) 展开Autoupdate Types node, 选择 Sandip Chitale's Modules
  7. 在右边的窗口中的第一个属性值Server URL,输入: http://blogs.sun.com/roller/resources/scblog/update-center.xml
  8. 确保Enabled 属性勾上。然后关闭当前窗口

现在这个更新中心就可以用了,我们目标是得到 Mark Occurrences 插件,它就在这个更新中心中:
选择Tools | Update Center 菜单. 勾上 Sandip Chitale's Modules 项,如果它还没被勾上的话。依照更新向导在 Select Modules to Install 窗口中选择
Sandip Chitale's Modules 选择Make Occurrences

虽然作者声明:这个模块是个实验性的模块,但是到目前为止在我的工作中我一直在用它,而且没有出现任何问题(比起一些 Eclipse 的插件可强多了!)


注意: 安装完后(不记得要不要重启 NetBeans), 你应该能看到工具条上出现一个黄色的按钮(如下图),或者你可以从 View | Mark Occurrences 激活它: