Send As SMS

2006-10-16

Ideas about Native Query for EJB3

最近,看了一下db4o这个产品的一些信息,其中 Native Query 这个概念感觉很有意义,因此,也在考虑是否可以在EJB3(Java Persistence API)中应用一下 Native Query这个概念。

按照DB4O的说法,Native Query有很多的优势:
  • Modern integrated development environments (IDEs) do not check embedded strings for semantic and syntactic errors. In all the queries above, both the field age and the value 20 are expected to be numeric, but no IDE or compiler will check that this is actually correct. ("age < 20")
  • If the developer mistyped the query code { changing the name or type of the field age, for example { all of the above queries would break at runtime, without a single notice at compile time.
  • Since modern IDEs will not automatically refactor field names that appear in strings, refactorings will cause class model and query strings to get out of sync. Suppose the field name age in the class Student is changed to _age because of a corporate decision on standard coding conventions. Now all existing queries for age would be broken, and would have to be fixed by hand.
  • Modern agile development techniques encourage constant refactoring to maintain a clean and up-to-date class model that accurately represents an evolving domain model. If query code is difficult to maintain, it will delay decisions to refactor and inevitably lead to low-quality source code.
  • All listed queries operate against the private implementation of the Student class student.age instead of using it's public interface student.getAge() / student.Age and thereby they break object-oriented encapsulation rules, disobeying the object-oriented principle that interface and implementation should be decoupled.
  • Developers are constantly required to switch contexts between implementation language and query language. Queries can not use code that already exists in the implementation language. There is no explicit support for creating reusable query components. A complex query can be built by concatenating query strings, but none of the reusability features of the program-ming language (method calls, polymorphism, overriding) are available to make this process manageable. Passing a parameter to a string-based query is also awkward and error-prone.
  •  Embedded strings can be subject to injection attacks.
那么在EJB3中是否可以应用这个技术上呢?理论上,完全是可行的(或者是部分可行的),比如: "from Cat as cat where cat.mate.name like '%s%' "
可以这样来写:
new Query<Cat> {
public match(Cat cat){ return SQL.like(cat.getMate().getName(), "%s%'") }
}



2006-08-08

Discover GWT's host mode

GWT有一个相当神奇的功能就是能够在Host模式下进行调试,那么它是如何进行工作的呢?本文试图解答下述的问题:
1、Module.onModuleLoad() 方法是如何被调用的?实际上onModuleLoad是每一个GWT应用的入口点,能够将执行的控制权转移到onModuleLoad即启动了一个GWT应用程序。
2、在Java代码中如何执行 JSNI 代码。实际上,GWT的一些低层的任务还是通过 JSNI 借口来完成的,比如说:DOM.getElementById实际上是等同于:
  public native Element getElementById(String id) /*-{
    var elem = $doc.getElementById(id);
    return elem ? elem : null;
  }-*/;
3、在JSNI的script代码中,又是如何的访问Java对象的字段、方法呢?

基本上,理解了上述3个问题后,基本上就可以明白GWT的Host工作模式了。

1、GWT使用了 eclipse swt 来构建HOST模式的用户界面,在其中嵌入了一个浏览器(在我的机器上,是IE浏览器),GWT同时使用了SWT提供的访问os native/COM的相关机制。对于浏览器窗口,GWT在其中设置了一个external 变量,window.external, 现在这个window.external 指向的 IDispatch 对象实际上是一个 Java 对象来的,对其的方法调用将变为对java代码的调用。
GWT的启动代码即 gwt.js 中包括了:
function __gwt_initHostedModeModule(moduleFrame, moduleName) {
    if (!window.external.gwtOnLoad(moduleFrame, moduleName)) {
        // Module failed to load.
        //
        if (__gwt_onLoadError) {
            __gwt_onLoadError(moduleName);
        } else {
            window.alert("Failed to load module '" + moduleName + "'.\nPlease see the log in the development shell for details.");
        }
    }
}
在 浏览器装载入 html 后, gwt.js 中的 _gwt_initHostModelModule 方法被调用,这个js方法就调用 window.external.gwtOnLoad 方法,从而执行其 Module.onModuleLoad 的方法,对整个GWT程序进行初始化。


2、在Java中如何调用javascript的方法,实际上,所有的JSNI被GWT编译器编译成为一个 javascript 方法,并且保存在 window 对象中,一般的,demo.DemoClass.method() 被保存成为一个 @ demo.client.Demo::bar(Ljava/lang/String;) 形式的函数。实际native的java代码被替换成为对这个 javascript 的调用。
如何调用呢? 通过COM API: window.call("function_name", arguments)

3、在 JSNI 中如何调用 java 的方法,或者访问 java 的变量呢?实际上,在调用javascript方法前,所有的Java对象被包装成为一个 IDispatch 对象,javascript 中 对这些对象的访问都会动态的调用回 java.

2006-07-12

Javascript 交叉编译

作为WEB的一等公民,Javascript有很多让人又爱又恨的东西,非常的动态、灵活,但是,在作为大型应用开发的语言时,又缺少一些必须的元素,例如:重构的支持、对IDE的支持(如代码自动完成)等、模块化等,这使得要开发javascript需要更多的技能。

GWT尝试提供了从 Java 到 javascript的编译,除了提供编译之外,GWT还尝试提供了模拟的执行环境,这使得这些Java代码可以在JVM中进行调试,从而简化了开发中的调试环节的支持。

HaXe 也进行了另外一种的尝试,通过自定义一种类似Javascript的语言,Haxe提供了从Haxe源程序到javascript、Flash等的交叉编译环境。


2006-06-08

关于JVM

将 JVM 作为操作系统的一个标准组件是一个很不错的想法,但要达成这一个目标,除了一些商务上的事情(例如,能够在Windows中绑定JVM)之外,作为Java本身,也还需要做一些额外的发展:目前的Java应用还是一个庞大的应用,每一个JVM都是一个完全独立的、有较长的加载时间和内存开销的应用,内存动则以数M计,这个自然会大大的限制JVM的使用。我至今还怀念UNIX下的那些小的工作软件,启动又快,基本不占太多的内存,简直就像一个编程语言的函数一样,可以信手粘来,不必考虑效率、性能的问题,设想这样的一个ls、sed、bc等等如果采用Java来开发, 作为一个独立的进程使用,可能性就不大了。

IBM新近的JVM5.0在这方面似乎有一些改进:通过采用一个ShareMemory,将一些class的load过程(仅包括一些相对静态的)缓存起来,(不包括JIT编译),与SUN Hotspot的不同的是:IBM JVM是通过修改URLClassLoader来完成的,不需要太多的JVM参与(这一点其实很有意思),因此,也不局限于对rt.jar的缓存,CLASSPATH下的也是可以缓存的。按照IBM的测试数据,这样处理以后,不仅仅Load时间有显著的降低,而且,在内存开销上也能够非常明显的节约。但从理论上而言,这个不同的JVM在重用上还是很初步的,应该来说,还有非常巨大的空间。

Sun的MVM这个概念也有很久的时间了,但具体而言,技术规范如何,原理如何,我还不得而知。

2006-05-16

easyajax组件的开发

Easyajax 有很长的时间没有增加新的组件了,这一次计划增加的组件是增加 InternalFrame,就是在Document内的子窗口,它的主要的特性是:

1、窗口内的内容可以加载另外的一个HTML页面
2、或者是一个EasyAJAX组件
3、窗口可以支持图标、标题、最小化、最大化(恢复成为最小化之前的大小)、可以通过拖拉改变大小、可以通过拖拉改变在页面中的位置

典型的使用方式如下:

<div jsclass="easy.InternalFrame" style="left: #px, width:#px">
    <content comes here/>
</div>


开发的参考包括:http://gabbly.com www.live.com

2006-04-02

Java字节码反向工程的另外的用途

http://soja.sourceforge.net/blog/2006/04/java.html 《针对Java开发规则引擎的一种优化》 一文中,我谈到了需要基于字节码分析技术来进行规则引擎的优化工作,实际上,字节码分析技术可能适用的范围会更为广泛,完全可以成为一种通用的底层技术, 从而在多个框架领域发挥重要的作用,这里列举一些应用的场景:

1、Profile。基于字节码分析技术,可以比较简单的在现有字节码中插入Profile用的代码,产生用于Profile的数据收集。
2、Code Coverage Tool。
3、Continuation Framework。基于字节码分析,我们可以重构一个方法,把这个方法变成一个等效的类,使用类变量来替代局部变量,从而实现Continuation的开发。下面是一个示例:

public void mailProcess(){
    Mail mail = waitingEmail();
    String txt = mail.getText();
    if(txt == "Hello"){
         Mail mail2 = waitingEmail();
    }
}

==〉
Class mailProcess {
   Mail mail, mail2;
   String txt;
   int status;

   public void execute(){
        switch(status){
           case 1: goto l1;
           case 2: goto l2;
        }
        mail = waitingEmail(); 
        l1:String txt = mail.getText();
        if(txt == "Hello"){
            mail2 = waitingEmail();
            l2:
        }
    }
}

在这里,waitingEmail这个方法会启动一个任务来接受邮件,同时方法抛出异常,自动的结束当前执行。当异步的任务处理接收到邮件时,将邮件的内 容保存到对象中,系统重新的从l1开时继续执行,通过这样一种字节码处理技术,即可简单的实现Continuation的功能。

4、针对log的优化,很多的java代码并没有使用 if(log.isDebugEnabled) log.debug(...) 模式来处理代码,通过字节码分析技术,我们可以对所有的 log.debug 调用自动的添加上上述的检查代码,从而使得代码可以具有更高的执行效率。这种模式可以认为是在字节码层面上的AOP

总之,字节码分析技术可以让字节码本身成为一个可以操作的对象,而且是在更高的语义层面,从而使得开发人员进一步的从这些内容中解脱出来,提高软件的开发效率。

针对Java开发规则引擎的一种优化

最近,有一种想法是在公司内部的项目中使用规则引擎,drools是一个不错的框架,内置的rete引擎,使得规则处理能够高效的进行。在业务系统如何使 用Rule Engine,这个是一个很有挑战性的考量,我会在后续的blog中进一步的思考这个问题。本文则主要思考如何对Java开发规则,提出一些想法。

drools一般的,使用某种规则语言来进行规则的开发工作,在drools2.1中,就有好多种选择:
  1. Domain Specific Languages
  2. Java Semantic Module
  3. Java Annotation Semantic Module
  4. Groovy Semantic Module
  5. Python Semantic Module
  6. CSharp Semantic Module
虽然是每种开发语言都有特定的客户群和适应层面,我个人则对3比较感兴趣,最主要的这种开发方式可以和Java最为紧密的结合,而且对于使用Java作为语言的开发人员而言,学习的曲线最低。

这里是从 http://drools.codehaus.org/Java+Annotation+Semantic+Module 摘取的一个例子:
import org.drools.semantics.annotation.*;

@DroolsRule
public class Hello {

@DroolsCondition
public boolean isTrader(@DroolsParameter("user") User user) {
return user.getType () == UserType.TRADER;
}

@DroolsCondition
public boolean isMarketOpen(@DroolsParameter("order") Order order,
@DroolsApplicationData("calendar") MarketCalendar calendar{
return calendar.isExchangeOpen(order.getExchange(), order.getTradeTime());
}

@DroolsConsequence
public void consequence(...) {
    	...
}
}
这种开发方式最大的一个好处,就是说这些规则的编写可以利用Java的IDE来进行正确性保证,本文提到的优化则是考虑利用字节码分析的手段,对Condition的方法进行智能化的分析,从而自动的分解成为多个&&(and)模式的Condition。
例如:
public boolean checkCondtion(Order order){
return (order.status == 1) && (order.user != null);
}
可以分解成为
public boolean checkCondition1(Order order){
return order.status == 1;
}
public boolean checkCondition2(Order order){
return order.user != null;
}
除了进行这样的分解之外,优化的引擎还可以利用字节码技术来检查两个条件是否是等效的,从而实现Chain的功能,目前的Drools中暂时还不支持这一技术,因此,实际上会大大的限制使用 Java POJO来开发规则。

此外,还有更多的优化是可以进行的,而且,应该可以较大幅度的提高规则引擎的效率,就是对Condition彼此之间进行推理,比如说,会存在这样的集中关系:
  • C1 ==> C2 当C1满足时,C2肯定满足,此时,不再需要重复的执行对C2的求值
  • C1 ==> !C2,当C1满足时,C2肯定不满足,此时,不需要再次对C2求值
  • !C1 ==> C2,当C1不满足时,C2满足
  • !C1 ==> !C2, 当C1不满足时,C2不满足
  • 更为常见的情况,C1,C2,...Cn满足Hash命中,即计算一个表达式Expr,当其值为V1,V2,...Vn时,C1,C2,...Cn满足,在这种情况下,不需要多次的评估Expr,而只需评估一次即可。
当需要进行上述的更加优化时,有必要打破目前drools的rete引擎,在一个更低的层面上进行优化,为此,可以引入ExprCondition类型, 例如:AndExprCondition, OrExprCondition, NotExprCondition, EqualsExprCondition, etc, 在ExprCondition的层面上可以进行更多的优化。

为此:需要的扩展是:
1、编写字节码分析工具,将Java字节码转换为等效的ExprCondition,这个可以开源的jode基础之上进行。
2、扩展drools,在rete引擎的基础上,支持对ExprCondition的优化。

我个人觉得,如果这个任务能够完成,Drools将可以更为简单、更为高效的在业务软件中进行应用,我会在后续的时间内对这一问题进一步的研究。