2009年5月10日星期日

Maven中依赖强制指定

一般的依赖机制可以参阅这里
今天碰到的一个比较郁闷的问题是这样的:
在一个开源项目中运行mvn eclipse:eclipse,结果返回出错,原因是找不到org.codehaus.plexus.utils.IOUtil这个类,但是后面提示跟着好几个备选的jar包,其中第一个是来自maven2.1.0的maven-2.1.0-uber.jar,里面确实有org.codehaus.plexus.utils包,但是没有IOUtil这个类;第二个是来自org.codehaus.plexus.plexus-utils 1.4.1的jar包,里面包含了IOUtil等类,而Maven缺省使用了第一个,也就是maven-2.1.0-uber.jar包,于是提示说ClassNotFound。

郁闷了一天后,晚上散步回来偶然发现Appfuse的basicspring pom配置中有对插件依赖进行配置,于是尝试了一下,果然,可以强制指定插件依赖包,狂喜~

2009年4月26日星期日

Windows上做开发的利器

  • QTTabBar,windows explorer的多tab插件
  • PowerCMD,多CMD窗口管理器,不过有点慢
虽然不能说两个软件在性能上不能算是尽善尽美,但是还是对开发提供了极大的方便:)


QTTabBar


PowerCMD

2009年4月19日星期日

Windows的NTUSER.DAT

该文件在C:\Documents and Settings\username下,适用于记录用户的个性化配置,今早登录系统时突然出现Windows无法加载配置文件的提示,才发觉该文件的重要性。

所有的环境变量定义、所有的个性化配置,都包含在这个文件中,而且是二进制格式的,这对于迁移、备份工作环境非常不方便,Windows用久了,这个文件也变得非常大,800+MB

根据网上的办法,我先rename了文件夹C:\Documents and Settings\username到C:\Documents and Settings\username_bak,然后重新登陆,这样Windows从DefaultUser那copy了一份新的配置文件作为用户配置文件;从bak中复制所有的配置文件(除了NTUSER*那些文件),虽然恢复了很多配置,比如桌面、开始菜单等,但是很多其他配置比如我的文档位置、环境变量等都不复存在了……

好彩的是,我无意中尝试了把C:\Documents and Settings\username_bak改回C:\Documents and Settings\username,然后使用这个文件夹作为用户目录,竟然可以加载了- -b

一个小时里就这么折腾着,哎,系统管理也是门艺术啊……

2009年4月13日星期一

Flash ActionScript2中加载外部SWF的问题

问题:加载外部SWF后,加载器不能响应鼠标事件,也就是点击加载的SWF没响应。
原因:加载后加载器MovieClip的所有属性方法都被擦出,参考资料
解决方法:在加载器下建一个子MovieClip用于加载SWF文件,用加载器进行控制。

基本步骤如下:
  1. 用createEmptyMovieClip创建一个空的MovieClip
  2. 使用MovieClip的loadMovie或者MovieClipLoader的loadClip加载外部SWF

var my_mcl:MovieClipLoader = new MovieClipLoader();

var mclListener:Object = new Object();
mclListener.onLoadError = function(target_mc:MovieClip, errorCode:String, status:Number) {
trace("Error loading image: "+errorCode+" ["+status+"]");
};

mclListener.onLoadStart = function(target_mc:MovieClip):Void  {
trace("onLoadStart: "+target_mc);
};
mclListener.onLoadProgress = function(target_mc:MovieClip, numBytesLoaded:Number, numBytesTotal:Number):Void  {
var numPercentLoaded:Number = numBytesLoaded/numBytesTotal*100;
trace("onLoadProgress: "+target_mc+" is "+numPercentLoaded+"%loaded");
};
mclListener.onLoadComplete = function(target_mc:MovieClip, status:Number):Void  {
trace("onLoadComplete: "+target_mc);
};
mclListener.onLoadInit = function(target_mc:MovieClip):Void {
// stop playing movie clip after loaded
target_mc.stop();
}
my_mcl.addListener(mclListener);

var loader = createEmptyMovieClip("loader"+i, this.getNextHighestDepth());
loader.target = loader.createEmptyMovieClip("loaderL"+i+"target", _parent.getNextHighestDepth());
my_mcl.loadClip("swf file url",loader.target);

这样加载后就可以对loader添加鼠标响应等行为,比如
loader.onPress = loaderPress;
loader.onRollOver = loaderRollOver;
loader.onRollOut = loaderRollOut;

修水管获得的忠告

宿舍水管漏水,想关总闸,但拧了半天都没反应,于是判定开关坏了,打电话预约维修人员……
第二天一早一个阿伯来了,先看了下开关总闸,拧了一会就把它关了。
我纳闷地问:“为什么我昨晚怎么拧都拧不到底的?”
阿伯慢条斯理地答道:“怎么会拧不到底?要有耐心,急不来~” 接着他慢慢拧下水管,然后换了两个橡皮圈,水管不漏水了。

2009年3月31日星期二

RCP Designing Coding and Packaging Java Applications书中的一个错误

按照书上,一步步实现一个IM系统,虽然没有完好的设计,但是还是体验了一下RCP开发一个完整软件的过程:) 但书上有一处错误,搞到我调了N久……在10.3节的扩展org.eclipse.core.runtime.adapters中,书上只列出了两个对象的adapter配置,即:只配置了RosterEntry和RosterGroup,却没有对Roster对象进行adapter,找出随书附带的源码,发现里面的确配置了Roster。
看书的时候不能光顾着看文字,还得结合附带的代码……

2009年3月30日星期一

Smack

昨晚被Smack的example郁闷了,误以为MessageListener是用来返回对方的回复信息,今天终于搞明白了。
Smack是XMPP的一个Java客户端library,可以用来实现Instance Message Tool(Spark、Sparkweb)。服务器端也有相应的的实现,叫Op
enfire,当然,这里只对这两个XMPP的实现讨论,还有很多其他开源实现。顺便提一下,和Smack对应的有个XIFF的Flash客户端实现。

贴一个例子,假设首先启动了Openfire服务器,用Spark客户端登录了某个账户prc,然后在代码中用另一个用户登录,并进行交谈。

效果图:



package org.prc;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;

/**
* Chat prototype using smack as client library. Server side are supported by
* openfire.
*
* @author promise
* @date 2009-3-30
*
*/
public class FireChat {
public static XMPPConnection con;
public static Chat newChat;
public static ChatManager chatmanager;

public static void main(String[] args) throws InterruptedException {
// XMPPConnection.DEBUG_ENABLED = true;
try {
// Create a connection to server
ConnectionConfiguration config = new ConnectionConfiguration(
"localhost", 5222);
con = new XMPPConnection(config);

// connect and login with the username and pwd on server
con.connect();
con.login("promise", "promise");
System.out.println("Authenticated = " + con.isAuthenticated());

// add a listener to receive all messages
addListener();

chatmanager = con.getChatManager();
newChat = chatmanager.createChat("prc@fantasy-promise/spark",
new MessageListener() {
public void processMessage(Chat chat, Message message) {
System.out.println("I'm sending: "
+ message.getBody());
}
});
newChat.sendMessage("hi");
} catch (XMPPException e) {
e.printStackTrace();
} finally {
Thread.sleep(3600000);
con.disconnect();
}
}

private static void addListener() {
// just need Messages :)
PacketFilter filterMessage = new PacketTypeFilter(Message.class);

PacketListener myListener = new PacketListener() {
public void processPacket(Packet packet) {
System.out.println("From: " + packet.getFrom() + "\n");
System.out.println("Body: " + ((Message) packet).getBody());
// when receiving prc's Message, just say something else again
// and again, robot :)
try {
newChat.sendMessage("hi again :)");
} catch (XMPPException e) {
e.printStackTrace();
}
}
};
// register the listener to the connection
con.addPacketListener(myListener, filterMessage);
}
}