Tuesday, January 17, 2006

继续和jetty/maven2浴血奋战

jetty6的最新版本似乎有很多问题。至少在我拿到的jetty-6.0-SNAPSHOT.jar中,任何post的表单都会把现成卡住。这是个很大的问题。jetty的支持对我说这个问题已经被处理,但我没有拿到任何新的版本的包。

不管怎么样,jetty这个古老的项目肯定是有稳定的可用版本的。查了一下5.1.10可能是最稳定的版本,所以我决定在已有的plugin里自己写一个启动jetty的Mojo来测试。 这个mojo不必像jetty自己的那个那么灵活可以设置端口,contextPath等,因为我的web应用里总是会有一个测试用的jetty.xml文件的。所以只要plugin允许用户告诉它这个文件在哪儿就行了。

这个程序非常简单,最终只是简单的调用了org.mortbay.jetty.Server.main, 带一个参数是jetty.xml的路径。它的源码可以在这里找到。

Thursday, January 12, 2006

用jetty6和maven2启动,调试web应用

maven1的日子里对付web应用我一般的做法是用maven-appserver-plugin在项目的target目录里搭建只给当前项目开发用的 tomcat实例,通过配置maven-war-plugin, 可以把程序部署到这个tomcat实例里。调试时因为tomcat实例已经存在了,只要确定tomcat的bootstrap包在classpath里, 就可以在IDE里很容易的启动tomcat的实例。这个流程一旦配置好了很容易用,所以在过去的三年里我启动,调试web应用时都是这样做的。

maven2 里我一直在找类似的做法,可appserver插件没有了,war插件工作起来也不太一样,assembly最终必须产成一个文件,tomcat插件则是 通过tomcat的admin webapp把war热部署到运行的tomcat上,不容易调试。最终我决定试一试maven2的jetty插件。

jetty-maven-plugin是org.codehaus.mojo的子项目,还没有发布过什么稳定的版本,几个maven2 repository里也都没有,所以只能从svn上拿到源码手工安装。mojo项目源码在这里有 介绍。奇怪的是codehaus上各项目svn的位置这几天扑朔迷离, 公布的url经常无效。按照文档配置了maven-war-plugin和maven-jetty-plugin后(主要是设web.xml的位置),在 项目里执行 mvn clean compile war:war jetty:run-war, 报错说log4j找不到。log4j在pom.xml里有年头了,很多别的插件都在用它,这个错误没什么道理。

在maven2 repository里看到了jetty6的插件。这是一个和jetty插件,mojo项目无关的插件,是jetty6项 目里的一个子项目。与其把jetty插件里log4j的问题搞定,还不如试一试这个最新的东西。从codehaus svn上拿下jetty项目的源码,进入modules/maven-plugin, maven package install这个plugin。 在项目的pom.xml中做如下配置(这个修改最终可以放到这些web应用的父pom里去)


<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>${basedir}/src/main/webapp/WEB-INF/web.xml</webXml>
</configuration>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty6-plugin</artifactId>
<version>6.0-SNAPSHOT</version>
<configuration>
<goalPrefix>jetty6</goalPrefix>
<contextPath>/app</contextPath>
</configuration>
</plugin>
</plugins>
</build>


在项目下执行mvn jetty6:run, 居然程序很顺利的跑起来了。

下一个要解决的问题是调试。调试和上面的配置以及maven2没关系。jetty6的启动是用org.mortbay.jetty:start包。在maven2的dependency里加入如下两个包:


<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.0.0beta7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>start</artifactId>
<version>6.0.0beta7</version>
<scope>test</scope>
</dependency>


scope是test因为他们的存在只是为了测试,这两个包最终是不会跑到war里的。main类是org.mortbay.start.Main, 带一个参数,参数是jetty的配置xml文件。此物在这里有详细介绍。我只是从jetty6项目考了一个到自己项目的src/test里,这样就可以在IDE里启动了。程序参数是jetty.xml, 主类是org.mortbay.start.Main。 jetty文件的内容如下

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC
"-//Mort Bay Consulting//DTD Configure//EN"
"http://jetty.mortbay.org/configure_1_2.dtd">
<Configure class="org.mortbay.jetty.Server">
<Set name="ThreadPool">
<New class="org.mortbay.thread.BoundedThreadPool">
<Set name="minThreads">20</Set>
<Set name="maxThreads">100</Set>
</New>
</Set>
<Set name="connectors">
<Array type="org.mortbay.jetty.Connector">
<Item>
<New class="org.mortbay.jetty.bio.SocketConnector">
<Set name="port">8080</Set>
<Set name="maxIdleTime">50000</Set>
</New>
</Item>
</Array>
</Set>
<Set name="handlers">
<Array type="org.mortbay.jetty.Handler">
<Item>
<New class="org.mortbay.jetty.webapp.WebAppContext">
<Set name="contextPath">/app</Set>
<Set name="war">./src/main/webapp</Set>
<Get name="SessionHandler">
<Set name="SessionManager">
<New class="org.mortbay.jetty.servlet.HashSessionManager" />
</Set>
</Get>
</New>
</Item>
</Array>
</Set>
<Set name="stopAtShutdown">true</Set>
<Call name="start" />
</Configure>


参考


Tuesday, January 10, 2006

几个Maven2 repository proxy


dotsrc.org
http://mirrors.dotsrc.org/maven2
central

ggi-project.org
http://ftp.ggi-project.org/pub/packages/maven2
central

sunsite.dk
http://mirrors.sunsite.dk/maven2
central

planetmirror.com
http://public.planetmirror.com/pub/maven2
central

lsu.edu
http://ibiblio.lsu.edu/main/pub/packages/maven2
central

ibiblio.net
http://www.ibiblio.net/pub/packages/maven2
central

Tapestry 4.0 is released

Tapestry一直是我很稀饭的一个Java Web Application Framework。 4.0的发布标志这它的成熟。

What is Tapestry's philosophy?

Tapestry is organized around four key principles:

  • Simplicity - web applications shouldn't be rocket science!
  • Consistency - what works in pages should work in components. What works in small applications should work in large applications. Different developers should find similar solutions to similar problems.
  • Efficiency - applications should be performant and scalable
  • Feedback - when things go wrong, the framework should not get in the way; in fact, it should provide useful diagnostics

These four principles drive the meta-principle: The simplest choice should be the correct choice. The decisions you make early in a project should not come back later to haunt you.

We have found that a component approach to web development is the best way of realizing these principles. Structuring the framework and your application around components makes it possible to move all the boring plumbing code out of your application and into the framework. You write less code, you write simpler code, sometimes you write no code. Tapestry picks up the slack.

Monday, January 09, 2006

又换皮了

简化了页面的结构,把控制皮的css单独拿了出来。新的皮基本上抄袭 deviantart.com上某人的作品

Thursday, January 05, 2006

Maven2的牛刀小试

想把CyclopsGroup.com上所有的项目里的Maven升级到Maven2已经很久了,一直有很多顾虑。比如怎么和现有的AntHill集成, 过去已经发布的包包该怎么办。为了不影响大局,在新的arapaho这个独立,简单项目上,我决定完全抛弃Maven1。 安装maven2很简单,下载maven-2.0.1的包,解压在某处。把bin/mvn在/usr/local/bin下做一个symbolic link就行了。

第一件要做的事儿是吧CyclopsGroup.com网站搬过来。按照其他maven2里项目的模样,我创建了一个名 叫com.cyclopsgroup.arapaho的项目,并在下面创建arapaho-main-site子项目。这个arapaho-main- site是将来存放网站内容的地方。按照maven网站上创建站点的文档, 我只是简单的把xdoc目录考到src/site/目录下,创建site.xml文件,执行mvn site。静态页面很顺利的生成到了target/site下。

现在的问题是我需要把一段googleanalytics的javascript放到每页的头上。文档上没有指出该怎么做但是从代码上看,在site.xml文件里应该可以写<head>标记。


<project>
<bannerLeft>...
<body>...
<head>
<script src="http://www.google-analytics.com/urchin.js"...
...


很遗憾,mvn site后改动没有任何效果。这是因为当前的maven是2.0.1release,很多包都不是最新的。所以需要下载最近的maven。
svn co http://svn.apache.org/repos/asf/maven/components/trunk, 进入trunk执行./bootstrap.sh, 在maven-core/target下产生最新的maven-2.1-SNAPSHOT-bin。解压到另一个目录,在/usr/local/bin里 重建mvn连接。

再次mvn site还没效果,手工安装最新的插件试一试。 svn co http://svn.apache.org/repos/asf/maven/plugins/trunk, 进入拿到的trunk执行mvn package install。 报错说需要的maven-2.0.2-SNAPSHOT不存在。

原来刚刚做的新的maven是 maven-2.1-SNAPSHOT, 这里插件需要的是2.0.2-SNAPSHOT。 在trunk上最新的maven已经抛开了别的插件走的太远了。果然,在maven/components/branchs里有个maven-2.0.x 分支。把这个分支搞下来:svn co http://svn.apache.org/repos/asf/maven/components/branches/maven-2.0.x 再用./bootstrap.sh做一个maven包,这回是maven-2.0.2-SNAPSHOT-bin。

解压新的包,重建/usr/local/bin/mvn, 再在arapaho-main-site里做mvn site, 得到一些velocity错误,大概是说244行的$item.toUnescapedString()不认识。打开site的velocity模板, 这行偏偏就是我要的东西。


#if ( $decoration.body.head )
#foreach( $item in $decoration.body.head.getChildren() )
#if ( $item.name == "script" )
$item.toUnescapedString()
#else
$item.toString()
#end
#end
#end


$decoration 是何许人士?这些代码已经跑到了maven的doxia子项目里面,大概还是包版本的问题。svn拿到doxia项目,mvn package install, 可问题还没有解决。难道maven-site-plugin一定要求用户用它自己的模板,我想要个简单的都不行吗?不会的。打开这段程序, 从execute方法里可以看出,site插件不仅像maven1一样允许你指定一个自己的velocity template, 还可以在site.xml里指定一个site skin包。

在arapaho大项目里建arapaho-skin-default子项目,内容很简单:

src/main/resource
+ images/some iamges
+ css/site.css
+ META-INF/maven/site.vm(modified)

site.vm里加进去了我想要的javascript,并对页面的格式做了很多修改。给arapaho-skin-default做mvn package install, 修改arapaho-main-site的site.xml

<project>
<skin>
<groupId>com.cyclopsgroup.arapaho</groupId>
<artifactId>arapaho-skin-default</artifactId>
<version>1.0-SNAPSHOT</version>
</skin>
<bannerLeft>...
...

原来的head标签就不用了。

再mvn site, 问题解决。这个arapaho-skin-default将来也可以在别的项目上重用。