Setup a Jython development environment

This article will show you some basic steps to setup a standalone environment for Jython, with the power of some popular and standard tools.

0. Install essential tools

Take Ubuntu Maverick as an example, before starting, you have to make sure these packages installed on your system.

Essential Python tools (Python is shipped with most Linux distribution by default)
sudo apt-get install python-pip python-virtualenv

Java
sudo apt-get install openjdk-6-jdk openjdk-6-jre

Jython
The Jython package in Ubuntu repository is obsolete. Download Jython installer from official website. A full installation is recommended here.
http://jython.org/downloads.html

As an optional step, I often move Jython direcotry to /usr/local/share/ , and use a symbol link to add Jython to PATH:
sudo ln -s /usr/local/share/jython/bin/jython /usr/local/bin/

Install additional Java tools
sudo apt-get install ant ivy

1. Create a standalone environment

Jython 2.5 is fully compatible with virtualenv, so you can create a standalone environment just like what you do with python:
virtualenv -p /usr/local/bin/jython jython-env
cd jython-env

List the directory, you will see these files and directories:

  • bin/
  • cachedir/
  • Lib/
  • jython.jar
  • registry

Source the activate script:
source bin/activate

2. Download and install python packages

Now the python environment is just ready, you can install python packages as you want. Install bottle, for example:
pip install bottle

3. Download and install Java dependencies

This is the different step. As you know, the most important feature of Jython is availability of Java libraries to Python code. So we need some additional tools to manage Java dependencies. Popular Java lifecycle management tool Maven is not suitable here, because Maven is tightly depends on its archetype. Gradle is also known as a powerful build tool with DSL support. However, Gradle uses Groovy as the scripting language to create build file. Bringing Groovy to a Jython project seems terribly strange.

So I prefer the traditional Ant way to manage dependencies. First of all, create a build file with following content:
build.xml

<project xmlns:ivy="antlib:org.apache.ivy.ant" name="jython-env" default="resolve">
    <target name="resolve" description="retrieve dependencies">
        <ivy:retrieve pattern="javalib/[artifact]-[revision].[ext]" type="jar"/>
    </target>
</project>

Then create an ivy xml to configure dependencies:
ivy.xml

<ivy-module version="2.0">
    <info organisation="info.sunng" module="jython-env" />
    <dependencies>
        <dependency org="commons-lang" name="commons-lang" rev="2.5"/>
    </dependencies>
</ivy-module>

Also, as an optional step, you can overwrite default settings to configure ivy to use maven local repository.
ivysettings.xml

<ivy-settings>
    <settings defaultResolver="maven-or-not"/>
    <resolvers>
        <chain name="maven-or-not" returnFirst="true">
            <filesystem name="maven-local" m2compatible="true" />
            <ibiblio name="ibiblio" m2compatible="true" />
        </chain>
    </resolvers>
</ivy-settings>

All done, now you can download everything. In Ubuntu, default ivy installation, you have to specify ivy path in ant command line:
ant -lib /usr/share/java/ivy.jar

You will see jars in javalib.

4. Reconfigure start up script

The default Jython start up script is not friendly to external Java dependencies. To include jars, you have to use such dirty command line parameters:
jython -Dpython.path=javalib/commons-lang-2.5.jar:javalib/…

To get rid of this, first rename bin/jython to bin/startJython. (Follow the Groovy naming convention)

Then create a new bin/jython script wraps the old one:

#! /bin/bash

JYTHON_CMD="startJython"
JAVA_LIBS="javalib/*.jar"
PYTHON_PATH=""

for lib in $JAVA_LIBS
do
    PYTHON_PATH="$PYTHON_PATH:$lib"
done

#echo $PYTHON_PATH
$JYTHON_CMD -Dpython.path=$PYTHON_PATH

5. Run

Finally, it comes to an end. Type jython to execute the interactive shell:
jython

Jython 2.5.1 (Release_2_5_1:6813, Sep 26 2009, 13:47:54)
[OpenJDK Server VM (Sun Microsystems Inc.)] on java1.6.0_20
Type “help”, “copyright”, “credits” or “license” for more information.
>>> from org.apache.commons.lang import BitField
>>> import bottle

Both Python and Java dependency is accessible. Now it’s time to get your new start.

My first http server, soldat-http

2008年的冬天,有一天和一个不认识的网友聊天,他说,以前也对这些框架啦什么的感兴趣,后来就变了,他说他当时的目标是写一个HTTP服务器。我当时能够认同他的观点,不过没什么特别的共鸣。到了今天春天,项目开始了,周末老大休假回杭州,留下大伙大眼瞪小眼要联调。出现了问题发现自己一窍不通,然后开玩笑说一定要把老大的NIO框架看懂才跳槽。结果不幸还没来得及怎么看就闪人了,还好老大开源,现在依然还可以偷偷看看。另外,我还隐约记得09年冬天的时候,似乎也给自己定过个类似一年之内写个HTTP服务器之类的目标。

所以我说,自己写程序是一件情怀驱动的事情:就像有些同学一再强调自己再也不写wordpress插件了,可是还是不断有新版本发布

好吧,其实这个目标最后没有实现。目前这个版本仅仅是能够work,在2010年快要结束的时候赶紧把他搬出来,聊以自慰,嗯,我这一年不是一无所获。
Screenshot - 12282010 - 09:17:59 PM

接下来我还会进一步完善它和底层的事件驱动框架,还有意完成一个Jython的WSGI实现。

LM Tooling, 2010

阿哈,大家都开始总结2010年了,我也想找个角度来总结一下今年。三句不理老本行,还是聊软件开发周边的事情。Lifecycle Management Tooling,软件生命周期管理的工具和我一年的感受。

一月份的时候我还有大把的业余时间,在做一个叫做Yan的验证码服务。这个项目从我刚一到盛大工作就开始了,不过因为没有特别的需求,最后变成了自己的开源项目。这个项目用Maven做dependency management,用hg做版本控制,代码放在bitbucket上。它对Maven的使用还很基本,是一个Single Module的小项目,因为服务本身已经实现了插件机制,本来我准备把它拆成Multimodule的Maven工程来着,不过后来因为比较忙,这件事就放掉了。那时我已经开始尝试用hg进行分支管理、每个release打tag,甚至还有一段时间会有一些两个分支的并行开发。这些基本上是实验性质的尝试,不过和后来相比也算是做的比较规范的了。

三月份我注册了github,顺带就开始用git了。到目前为止,我对hg和git的区别还没有特别的感受,选择的主要依据其实bitbucket和github。相对social一些的项目,github是当仁不让的选择。bitbucket上人少比较清净,一些incubator项目放在上面,烂尾了也不至于太丢脸。扯远了,哈哈。

之后我们开始做一个规模比较大的项目,我们使用Maven,使用Nexus,使用SVN。项目规模比较大,我们有数个Multimodule的Maven项目,遇到的第一个问题就是集成的成本非常大。最初几周,我都是在自己的机器上做集成,Windows,你懂的,又不太方便做自动化,结果整个过程非常痛苦。到了四月份项目还没有全部完成,已经不能忍了,于是我引入了Hudson。我们为每一个项目创建单独的build task,unstable的构建会有邮件通知开发人员。一方面把我从每天反复的手动集成打包中解脱出来,另一方面也促进了大家写高质量的UnitTest,因为一旦有测试不通过就会有一个虚构的200000000@snda.com的邮箱给大家发邮件,以至于最后几乎所有人都把这个地址拉黑了。

写真正能够Automation的单元测试其实很不简单,尤其是DAL层。理想的solution是用内存数据库来做单元测试的数据源,不过在实际开发里,因为一些SQL会依赖特定的数据库,所以这个方案并不太理想。如果有事务的话,Spring的TestCase可以设置自动回滚,可是互联网项目,你也懂的,连一致性都搞成最终一致了,事务这么重的东西我们是不用的。

我们遇到的另一个问题是,多个独立的Maven项目,在做集成时,会存在依赖的冲突。这类问题一旦出现,找原因的代价还是比较大的。这方面,老大有一个Best Practice,定义一个统一的、专门管理版本的pom,通过dependency management的import来使用,你可以看这里来了解。

我们suffer的另一个问题是SVN的分支管理,到了项目的后期,功能越来越多,也出现了两个分支的并行开发,回滚的情况也出现了。我们基本上可以保证每次发布都有tag,但是分支的管理实在是非常痛苦。我现在的认识是,两方面原因。第一,SVN的分支成本还是比较高的,远程整个目录拷贝一下,本地需要指向新的地址。第二,项目的计划不明确,根本没有办法去估计新的分支、新的版本。两个原因结合起来说,其实分支管理不完全是一个版本控制系统层面的问题,和整个项目规划都有一定的联系。

到了后期,我们对Hudson的使用也有了一些最佳实践,结合ssh/scp的插件,task的trigger机制,我们有了自动化的部署,你可以在这里了解。不过我们的自动化最后倒在公司强制的动态密码验证机制上,每次登录需要使用动态密码,这样一切最后又都回归了手动。

除了在公司的项目,在9月份我又做了一个实验性的项目,叫做Bason,他可以在编译时生成JavaBean到Mongodb BSON代码。也是用Maven管理,不过值得一提的是,我申请了Sonatype提供的OSS Repository,这样可以把项目都deploy到公共的服务器上,使用会非常方便。还值得一提的是,OSS Repository的管理者是校友@Juvenxu

不过今年Maven并不是Java生命周期管理的唯一工具,还有一些工具也开始进入视线,当然我说的不是ant+ivy。前段时间发布0.9的Gradle是比较受关注的,它又回归了ant的task oriented ,结合Groovy的DSL和插件机制提供更高的灵活性。另外,断断续续学了一年的clojure,clojure的生态系统里已经有了一个叫做leinigen的生命周期管理工具,在clojure的世界里,它非常好用。

另外Python的世界,我逐渐开始强制自己用virtualenv来创建一个更可控,更具有移植性的python环境。随着年底开始的一个小项目,我应该对python项目的生命周期管理有更深的认识。

年底到了SAP,开始在NetWeaver平台上做Abap开发。NetWeaver是一个复杂的平台,它的Scope也涵盖了生命周期管理。在NetWeaver中,开发一个非local的程序,需要首先创建一个Change Request,之后所有的变更,最后都会保存到这个ChangeRequest上,有些类似传统的分支。当开发完成后,开发人员把change request release掉,这部分代码会自动被transport到Test系统或者其他下游系统上。实际开发里,一个Change Request可能对应一个Ticket,一个特性。这样的平台上,开发人员需要额外操心的事情,非常少。

Exaile doubanfm plugin 0.0.6b

上周豆瓣电台增加了电影原声频道,这次的插件更新支持了这个新频道(OST)。

下载地址

https://github.com/sunng87/exaile-doubanfm-plugin/downloads

安装指南

https://github.com/sunng87/exaile-doubanfm-plugin/wiki/Installation

欢迎使用!

Blackboard Pattern

昨天很虔诚地在图书馆把POSA第四卷里所有的Pattern Languages都抄了一遍。恰好遇到Modeling部分的第9个Pattern, Blackboard,没有感性认识。今天简单地搜索了一下。

POSA上指出Blackboard模式用于解决尚没有绝对解决方案的问题,将几个子系统的知识组合起来提供一个近似的解决方案。在解决这类问题的过程中,几个子系统相互独立,Blackboard作为中央控制对子系统进行控制和反馈。在这个系统中有三个角色:

  • Control Shell: 系统对外的控制接口
  • Blackboard: 中央的知识管理,接受Specialist运算的反馈,对Specialist进行调度
  • Specialist: 具有专业知识的子系统,负责独立的运算

这里有一个描述Blackboard模式的代码例子:
http://www.andypatterns.com/index.php/blog/blackboard_architectural_pattern/

参考:

http://www.vico.org/pages/PatronsDisseny/Pattern%20Blackboard/

http://en.wikipedia.org/wiki/Blackboard_system

http://chat.carleton.ca/~narthorn/project/patterns/BlackboardPattern-display.html