eWebEditor不支持IE8/IE7的解决方法 十月 12th, 2009
在修改一个项目的老缺陷,使用了eWebEditor,没看出是哪个版本,但是在点击编辑器按钮时就报错:缺少对象,editor.js,行171。
editor.js中171行的代码是
if (element.YUSERONCLICK) {
eval(element.YUSERONCLICK + "anonymous()");
}
在网上搜索了一下,最简单的办法是将上面的代码替换为下面的,暂时没发现不良影响。
if(navigator.appVersion.match(/MSIE (7|8)\./i)!=null){
if (element.YUSERONCLICK) eval(element.YUSERONCLICK + "onclick(event)");
}else{
if (element.YUSERONCLICK) eval(element.YUSERONCLICK + "anonymous()");
}
为XFire生成的WebService客户端设置连接超时参数 九月 9th, 2009
由于要从另一个系统的WebService读取大量的数据,因此要修改连接WebService的超时参数。WebService的客户端代码是通过XFire的Ant任务生成的。Google一下,没找到答案,但最后还是在XFire官方找到了答案。
假设生成的客户端代码中的服务接口和Client的类分别为TestService和TestServiceClient,修改连接超时参数代码如下:
//创建Service对象
TestServiceClient testClient = new TestServiceClient();TestService testService = testClient.getTestServicePort();
//设置连接参数
HttpClientParams params = new HttpClientParams();params.setParameter(HttpClientParams.USE_EXPECT_CONTINUE, Boolean.FALSE);
params.setParameter(HttpClientParams.CONNECTION_MANAGER_TIMEOUT, setting.getTimeout() * 1000);//单位是毫秒
Client client = Client.getInstance(testService);
client.setProperty(CommonsHttpMessageSender.HTTP_CLIENT_PARAMS, params);
XFire是基于Apache的HttpClient,所以实际上连接超时的参数是就是设置在HttpClient上的。
通过ODBC连接MySql 八月 27th, 2009
由于需要共享EA项目,而暂时发现EA仅支持ODBC连接数据库,所以要解决通过ODBC连接MySql的问题了。
Windows默认是没有MySql的ODBC驱动的,首先要下载ODBC驱动。Google到MySql官网上有,但是需要注册,继续Google到一个下载镜像:http://mirror.cogentco.com/pub/mysql/Connector-ODBC/5.1/,选择了Windows x64的MSI版本下载,因为我的系统是Windows7 x64。下载下来才发现,x64的版本里还包含了x32的。
安装驱动后,在ODBC数据源管理里的“用户DNS”或“系统DNS”点击“Add”按钮,就可以看到了:

选中“MySql DOBC 5.1 Driver”,点击“Finish”,就可以添加一个MySql数据源了:

填完各输入框点“OK”,在列表里就可以看到刚才添加的数据源了:

只谈技术,莫谈国是? 八月 24th, 2009
JavaEye发布的信息:http://www.javaeye.com/news/9991-protect-javaeye
今天下午JavaEye网站被和谐了,原因是多次出现“有害”信息!如果再次出现“有害”信息,我们可能会被和谐很长时间。
在这个特殊的时期,为了保护JavaEye网站还能够继续“存在”下去,为了大家还能有一个高质量的交流场所,我们呼吁每个JavaEye会员:
1、只谈技术,莫谈国是!
2、凡是发现涉及社会敏感事件的热点话题,政治话题,军事话题,请立刻在JavaEye站务论坛向我们举报!
3、请自律自己的行为,只要我们发现任何人发布任何政治话题和敏感事件的文章,帖子,博客,评论,甚至闲聊,统统直接删除用户ID和用户所有JavaEye资料,不给任何通知和解释。
能怪JavaEye不?
不能!
该怪JavaEye不?
该!
无语……
把MyEclipse项目转为WTP项目 八月 20th, 2009
马上要进入另一个项目组了,新项目所用的IDE是MyEclipse。我已不习惯了庞大的MyEclipse,而习惯了WTP并且想试验一下新的Eclipse3.5,因此需要把MyEclipse项目转换为WTP项目。(PS:不遵守团队开发规范是不正确的行为!)
1.在Eclipse里导入MyEclipse项目到工作空间。
2.编辑.project文件,在<natures></natures>中加入
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
在<buildSpec></buildSpec>节点加入
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
3.在Eclipse中刷新项目。
4.右击项目-->Properties—>Project Facets,在右边勾选Java与Dynamic Web Module,应用。
5.如果你的项目源代码文件夹不是WTP默认的src,则需要到Java Build Path中去添加相应源代码文件夹。
6.如果你的项目Web文件夹不是WTP默认的WebContent,则需要文件文件 <项目目录>/.settings/org.eclipse.wst.common.component,找到
<wb-resource deploy-path="/" source-path="/WebContent"/>
并修改,如
<wb-resource deploy-path="/" source-path="/webapp"/>
当BeanUtils的拷贝遇上java.util.Date 八月 16th, 2009
BeanUtils是apache基金会下的一个开源项目,主要用于对Java Bean的操作。在一个项目中,经常要用到Bean属性拷贝,使用了org.apache.commons.beanutils.BeanUtils.copyProperties(dest, orgi)。由于此方法声明了抛出异常,在项目中为了方便,便对此作了简单封装,把异常处理了:
public static void copy(Object dest, Object orgi) {
try {
BeanUtils.copyProperties(dest, orgi);
} catch (Exception e) {
log.error("Bean属性拷贝出错。", e);
}
}
后来却发现,当源对象orgi中某个java.util.Date类型的属性为null时,copy会失败(虽然异常被处理了),目标对象dest中部分非Date类型的属性也为空,虽然源对象中这些属性是有值。原因就是上BeanUtils在处理属性值为null的Date类型时出错了,便抛出了异常,后面的属性便不会再复制。
后来在JavaEye搜到了答案:为BeanUtils注册一个日期类型转换器:使用org.apache.commons.beanutils.ConvertUtils,注册org.apache.commons.beanutils.converters.DateConverter。下面的代码是放在copy方法所在的类:
static{
ConvertUtils.register(new DateConverter(), Date.class);
}
基于注解与自动扫描的某些实体没被映射的原因之一 七月 16th, 2009
在尝试修改基于SpringSide 3.1.3的mini-web过程中,又遇到了一个奇怪的问题。一个hql如下:
StringBuilder hql = new StringBuilder();
hql.append("SELECT new ");
hql.append(CommentBean.class.getName());
hql.append(" (o,u.name,u.image) ");
hql.append(" FROM ");
hql.append(Comment.class.getSimpleName()).append(" o, ");
hql.append(User.class.getSimpleName()).append(" u ");
hql.append(" WHERE o.userId=u.id AND o.infoId=? ");
hql.append(" ORDER BY o.commentTime DESC");
Comment这个实体类的全限定名是:org.shoopman.entity.Comment
但在运行时却报错:
Comment is not mapped [SELECT new org.shoopman.service.dto.CommentBean (o,u.name,u.image) FROM Comment o, org.shoopman.entity.user.User u WHERE o.userId=u.id AND o.infoId=? ORDER BY o.commentTime DESC]
org.hibernate.hql.ast.QuerySyntaxException: Comment is not mapped [SELECT new org.shoopman.service.dto.CommentBean (o,u.name,u.image) FROM Comment o, org.shoopman.entity.user.User u WHERE o.userId=u.id AND o.infoId=? ORDER BY o.commentTime DESC]
at org.hibernate.hql.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:181)
at org.hibernate.hql.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:110)
at org.hibernate.hql.ast.tree.FromClause.addFromElement(FromClause.java:93)
at org.hibernate.hql.ast.HqlSqlWalker.createFromElement(HqlSqlWalker.java:277)
而其他实体的查询却没有问题。先看一下spring的applicationContext.xml关于Hibernate的配置:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="namingStrategy">
<bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider
</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">${hibernate.ehcache_config_file}</prop>
</props>
</property>
<property name="packagesToScan" value="org.shoopman.entity.*" />
</bean>
问题就在这个自动描述packagesToScan的配置上。如上的配置,Spring只会扫描到org.shoopman.entity这个包下的子包里的实体类,而直接放在这个包下的实体却没有描述。
无奈,只好在新建一个org.shoopman.entity.common包,把Comment移到此包下。到此,问题解决。
题外话:看上面的hql生成过程,在使用User这个实体类时,我用的是User.class.getSimpleName(),为什么Hibernate在生成hql却是全限定名。当把Comment移到common包下,控制台里打印出来的hql又是SimpleName。这是Hibernate的一个容错处理吗?
GFW又K了一个ghs的IP? 七月 16th, 2009
下午还能通过blog.shoopman.org来访问我的博客,刚才通过Windows Live Write来发表文章,却不成功。现在只能通过shoopmanlog.appspot.com来访问了。看一下友情连接里的GAE伙伴们,徐明的挂了,Keengle的也挂了,Qing的还没有。这样还好,不用费那么多事去找新的ghs IP了。
5月26日左右,ghs挂了一个IP;6月15日左右,又挂了一个;今天,7月16日,再一个。看来,在GFW的驱动下,广大中国的GAE Blogger们都要习惯每月一次的修改域名A记录或者类似的事情了。
已在GoDaddy修改了域名的A记录,看多久后才能生效吧。现在,只有等待并且忍受,等哪天实在忍受不了了,就去给美国增加一点儿GDP吧。
为Micolog添加了Google翻译功能 七月 15th, 2009
今天在Google Analytics里看到,大概30%的IP流量是来自国外,而语言是en-us的流量更多(我的操作系统也是英文版的)。所以,如果能提供一个翻译按钮给那些老外,他们会更明白我在说什么。Google Translate已经提供了这样一个小工具,只需要简单的几个步骤,就可以往自己网站添加上这个翻译功能。下面就为我这个基于Micolog的博客加上这个小功能吧。
1. 获取代码
到http://translate.google.cn/translate_tools?hl=zh-CN去,代码马上就生成了,如下:
<script src="http://www.gmodules.com/ig/ifr?url=http://www.google.com/ig/modules/translatemypage.xml&up_source_language=zh-CN&w=160&h=60&title=&border=&output=js"></script>
其中,w和h这两个参数是控制Google翻译小工具的宽度和高度,可以自行修改。
2. 修改主题文件
找到你要添加小工具的网页,把上面的代码粘贴进去。比如我是在themes\default\templates\sidebar.html里添加了小工具。
3. 上传文件
至此,Google翻译小工具就添加进去了,你可以看一下页面右上方。样子是有点丑,将就一下了。
Google还提供了更多可以往自己网页里放的小工具,可以到http://www.google.com/webmasters/gadgets/找一下。
为Micolog添加Google自定义搜索 七月 14th, 2009
由于Google App Engine数据存储与关系数据库不一样,Micolog也无法像传统应用那样提供基于数据库某些字段的搜索。作为搜索引擎老大,Google对自家的App Engine里的内容收录还是相当及时的,比如我这博客发布的文章,一般两天内就收录了。因此我们可以利用Google搜索引擎收录索引来解决Blog站内搜索这个问题。Micolog默认主题里就提供的站内搜索,即加上site:blog.shoopman.org,比如这个搜索。有个不爽的地方,就是搜索结果页完全跳出了自己的博客。于是,我利用了Google自定义搜索来为Micolog博客加入站内搜索。
先看一下最后的效果:
http://blog.shoopman.org/google-search?q=java&cx=004316150475193113567%3Ah9vz95zkor4&cof=FORID%3A11&ie=UTF-8
还不错吧,页面的顶部、底部以及右边都是Micolog原本的风格和内容,只有页面主体是搜索结果。下面开始动手了。
1. 创建Google自定义搜索引擎
用你的Google帐号登陆到 http://www.google.com/coop/cse/,按照提示创建一个自定义搜索(图)。
2. 获取代码
转到自定义搜索的控制面板--获取代码,选择”使用 iframe 使搜索结果位于我的网站上”,并指定搜索结果页地址,如/google-search(图),这时可得到搜索框和搜索结果页的代码,先保存一下。
3. 修改Micolog主题
转到你正使用的主题,如我是用默认主题,即到themes\default\templates下,编辑base.html,把搜索框处理的代码修改如下:
<form method="get" id="cse-search-box" action="/google-search">
<input type="text" value="Search..." onfocus="if (this.value == 'Search...') {this.value = '';}" onblur="if (this.value == '') {this.value = 'Search...';}" name="q" id="s" />
<input type="image" src="/themes/{{ blog.theme_name }}/images/transparent.gif" id="go" alt="Search" title="Search" />
<input type="hidden" name="cx" value="004316150475193113567:h9vz95zkor4" />
<input type="hidden" name="cof" value="FORID:11" />
<input type="hidden" name="ie" value="UTF-8" />
</form>
注意,form中action处的google-search后面再说,名为cx的隐藏域应该是自己自定义搜索的标识。在第二步里的搜索框代码里,还有一行<script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&lang=zh-Hans"></script>,不要加进去,这会改变原来搜索框的样式。
4. 创建搜索结果Javascript
由于无法在Micolog的编辑器添加有效的Javascript代码,我们将Google自定义搜索结果页的Javascript代码放到一个独立的js文件里,内容如下:
var googleSearchIframeName = "cse-search-results";
var googleSearchFormName = "cse-search-box";
var googleSearchFrameWidth = 600;
var googleSearchDomain = "www.google.com";
var googleSearchPath = "/cse";
把此文件命名为google_search.js,并放在/static/js目录下。(你可以修改js文件名及路径,但建议放在static目录下)
5. 创建搜索结果显示页
登陆到Micolog后台管理,创建页面,内容如下:
<div id="cse-search-results"> </div>
<script src="http://blog.shoopman.org/static/js/google_search.js" type="text/javascript"></script><script src="http://www.google.com/afsonline/show_afs_search.js" type="text/javascript"></script>
其中前面的js就是上一步创建的那个js文件。
在此页面里,还要指定名称(slug)为google-search,即第2步、第3步中搜索框Form中的action;把页面级别设置为1,那么在博客顶部的菜单就不会出现此页面的连接(图)。
6. 上传文件
把修改过的base.html和新建的google_search.js上传到Google App Engine中,就大功告成了!
Update1:这文章在发布后几分钟就被Google收录了,很快!
Update2:这里有个更方便的办法:http://www.houkai.com/2009/07/7/google-search.html