2008年7月4日星期五

【原创】Hibernate的Antlr在Weblogic中产生Jar冲突的历史缘故以及解决办法

Hibernate使用的文法分析器是antlr,WebLogic同样也是。
不少用户碰到ClassNotFoundException: org.hibernate.hql.ast.HqlToken的典型问题,这个典型问题已经通过
配置weblogic.xml,要求Web应用优先加载WEB-INF的Jar(即应用Classloader)而非WebLogic的System Classloader得以勉强解决:
<weblogic-web-app>
  <container-descriptor>
    <prefer-web-inf-classes>true</prefer-web-inf-classes>
  </container-descriptor>
</weblogic-web-app>
 
 
Hibernate 3.0的用户发现上述的方法依然不能解决问题,因为Hibernate使用了Class.forName去Load一个类,而JVM加载类的方式是先System Classloader(WebLogic),后Application Classloader(Web应用),于是,应用即使采用prefer-web-inf-classes策略,但Class.forName还是Load了WebLogic的Antlr!!
 
Hibernate 3.1迅速解决了这个问题,Hibernate会使用context classloader,Class.forName这种罪恶的代码已经被消除掉。
 
无独有偶,2005年,澳大利亚的Suncorp-Metway公司使用Hibernate3.0.3 + WebLogic8.1SP4开发他们的应用 , 当时的WebLogic 8.1SP4内置了antlr 2.7.1,跟Hibernate  3.0.3捆绑的antlr-2.7.5H3.jar冲突,Suncorp-Metway公司希望改变WebLogic的SystemClassPath(加入antlr-2.7.5H3.jar),效果等于替换了WebLogic的Antlr,这当然能够解决Hibernate的问题,但天知道会带来什么问题,因为WebLogic自身会使用Antlr去分析EJBQL(如果不适用CMP,用户完全可以不管3721,置换WebLogic的Antlr版本了之),Suncorp-Metway公司担心这种替换对系统带来其他影响,希望BEA仍然能够提供技术支持。
当时,作为BEA在澳大利亚昆士兰州最大的BEA客户,他们的建议当然受到足够的尊重。为此,BEA 8.1 SP4/SP5都提供了一个补丁,等同于升级了WebLogic 8.1自带的Antlr的版本,WebLogic 8.1SP6以及WebLogic 9.1开始都沿用这个变更。
 
很明显,这种办法不可能再次沿用到以后的SP,因为Antlr以及Hibernate的版本的更新速度远远高于WebLogic Service pack的更新速度,BEA不可能不断地重构Antlr来适应开源日新月异的API变化。
 
WebLogic 8.1 SP6之后,当使用Hibernate 3(策略是<prefer-web-inf-classes>true</prefer-web-inf-classes>)的Antlr 2.7.6时候,轮到WebLogic自身的Servlet容器出问题(Hibernate好了,WebLogic出事了)抛出如下的Antlr异常:
java.lang.ClassCastException: antlr.CommonToken
at antlr.CharScanner.makeToken(CharScanner.java:175)
at weblogic.servlet.jsp.JspLexer.mWORD(JspLexer.java:4723)
at weblogic.servlet.jsp.JspLexer.mXML_ATTRIBUTES(JspLexer.java:4309)
at weblogic.servlet.jsp.JspLexer.mTAGLIB_DIRECTIVE_BODY(JspLexer.java:5034)
at weblogic.servlet.jsp.JspLexer.mTAGLIB_DIRECTIVE(JspLexer.java:4905)
at weblogic.servlet.jsp.JspLexer.mDIRECTIVE(JspLexer.java:4751)
at weblogic.servlet.jsp.JspLexer.mSTANDARD_THING(JspLexer.java:2161)
at weblogic.servlet.jsp.JspLexer.mTOKEN(JspLexer.java:1947)
at weblogic.servlet.jsp.JspLexer.nextToken(JspLexer.java:1820)
at weblogic.servlet.jsp.JspLexer.nextToken(JspLexer.java:1820)
at weblogic.servlet.jsp.JspLexer.parse(JspLexer.java:963)
at weblogic.servlet.jsp.JspParser.doit(JspParser.java:106)
at weblogic.servlet.jsp.JspParser.parse(JspParser.java:234)
at weblogic.servlet.jsp.Jsp2Java.outputs(Jsp2Java.java:125)

这个问题是WebLogic Servlet容器没有意识到Hibernate用户对ANTLR的版本需求:
1) 在老的Antlr 2.7.1中,WebLogic的Servlet容器使用antlr.CharScanner通过下面的方法 Class.forName(String className)加载token,因为jsp编译的classes本身是基于WebLogic系统Classloader,于是,Classloader当然使用WebLogic的Antlr版本(2.7.1),WebLogic没有被Hibernate的Antlr(2.7.6)所影响,Class.forName转型成System CL所规约的 antlr.CommonToken不会有问题。
2) 而当WebLogic Antlr 2.7.1+Hibernate Antlr2.7.6一起使用的时候,Servlet容器在CharScanner使用 Class.forName(String, boolean, ClassLoader)去加载token,而第三个参数是注入了当前的应用的Classloader,即WebLogic被迫使用了Hibernate的Antlr 2.7.6,而最终会导致容器在将Antlr 2.7.6的 CommonToken转型成Antlr 2.7.1的CommonToken出现java.lang.ClassCastException。
 
这种情况,只能做两件事情:
1)向BEA索取此Case的补丁
2)前置System ClassPath,让新版本的Antlr永远放在前面。
 
 
讲述了这么多东西,其实,最终想揭示的问题是,无论是Hibernate和WebLogic,在一开始的时候都没有意识到开源代码重构的重要性。早期的WebLogic确实已经XML Parser付出版本冲突的代价,所以后期,很多XML包都被WebLogic重新Rename Package(重构代码的一种方式)。如果一开始,WebLogic就使用com.bea.opensource.antlr来让自己的容器使用Antlr,ANTLR冲突的这些问题肯定不会出现。
 
WebLogic 10确实开始大规模重构Jar包,不幸的是,这个世界上有一种潜规则叫做向后兼容,所以,<prefer-web-inf-classes>true</prefer-web-inf-classes>是我们J2EE初级阶段仍然需要接受的现实,当然
,你可以期待另外一种技术解决此问题――OSGI,事实上,这个版本可能比我们想象的要快,或者就在WebLogic 12g。
 
 
 

2008年6月29日星期日

[原创]Oracle收购BEA后的中间件以及SOA产品线战略分析

Oracle应用服务器战略
WebLogic+Tuxedo+JRockit将成为Oracle的J2EE服务器的基础设施,Oracle原来的J2EE容器将边缘化。
WebLogic将很快采用Oracle的命名法,下一个版本可能是WebLogic 11gR1,它将融汇Oracle现有的产品特性:

1 Oracle Toplink: EJB 3.0/JPA Provider & O- R Mapping
2 Oracle Coherence: In-Memory Data Grid for
XTP Applications
3 Oracle Web Services: SCA Runtime infrastructure for
SOA
4 Oracle EDA Infrastructure: Services for CEP &
BAM on WLS
5 Oracle JPS/
Security: For Authentication, Authorization, PKI
6 Oracle AQ/
JMS: Additional alternative to BEA WebLogic JMS
7 Oracle JPS: Advanced features for JSF & UI Customization

其中,KODO被TopLink替换是意料中事,另外,Oracle认为它Web Service协议栈可能也比BEA的要好,基于这个观点,可以预见,在WS*上面的产品线,尤其是SOA产品线(基于WS*),基本上会以Oracle SOA产品线为主流。

Oracle Portal产品战略:
Oracle的WebCenter无疑是Portal产品战略的核心,WebLogic Portal可能不再依旧风光了,它可能仅仅作为一个轻量级Portal继续存在,对BEA来说,Portal的基本要素,比如内容管理,WebClipping(临时收购回来的Kapow),搜索引擎(WLP自带的Autonomy也不是BEA自己的,比Lucene还难用,而且还有让人恼火的License限制),可能在Oracle的产品重组之下变得更加悲观了。
未来的Oracle Portal很明确,它应该会在BEA的WebLogic中间件上运行。

Oracle SOA战略:
Oracle放弃BEA的SOA产品线,并且在中间件的层面上增强它现有的SOA产品体系:

Oracle BPEL Manager
Oracle Service Bus (即BEA的ALSB)
Oracle Enterprise Service Bus
Oracle Human Workflow
Oracle Rules
Oracle Data Integrator
Oracle Adapters
Oracle B2B
Oracle Web Services Policy Manager
Oracle Complex Event Server
Oracle BAM

除了BEA的Aqualogic Service Bus(ALSB)能够进入SOA大名单,其他的产品比如ALDSP对做数据业务出身的Oracle来说是太小儿科了,可能被放弃。

Oracle BPM产品战略:
之前业界的猜测是正确的,Oracle还是基本上保留了它自己的BPM的产品线,BEA的Aqualogic BPM对Oracle BPM产品线贡献仅仅是Designer工具:

Oracle BPA Designer
Oracle BPM Designer (即BEA的ALBPM工具)
Oracle BPEL PM
Oracle Rules
Oracle BAM
Oracle Process Portal

Oracle的BPEL Process Manager依旧是BPM产品线的战略核心,当然,在收购BEA之前,Oracle已经是BPM领域的领导者(From Gartner)。


Oracle开发工具战略
Oracle的JDeveloper依然是主角,BEA收购回来M7虽然优秀,但始终没有得到广泛的认同,因此,Workshop Studio最终将作为一个面向现有客户的产品,依旧提供补丁但可能不会再支持新的JavaEE标准,而Oracle JDeveloper将成为Oracle的Sell给新客户,与竞争对手PK的主要产品,所有BEA现有的Eclipse Plugin(包括M7)将会融入此工具,结合Oracle原有的领先的ADF、TopLink以及元数据解决方案,可以预见,JDeveloper会是一个多么强大的工具。
至于BEA以前曾经提交给Apache的Beehive,将会逐渐退出舞台,但近期依然会提供有限度的支持。
原先Workshop Studio绑定销售Adobe Flex Builder策略,可能Oracle不会再继续,未来的用户需要自己安装FlexBuilder。
老的BEA用户应该能够区分WebLogic Workshop和BEA Workshop studio两个产品,这两个产品都会被边缘化。


总结:
这次产品重组的结果,基本符合了之前很多业内IT人士分析预测,在收购案开始的时候,我已经一针见血指出,
Oracle不是冲BEA的SOA而来,而是冲BEA的中间件而来。
这个混沌的JavaEE世界,不管宝马有多少炫耀的功能,车的发动机不能差。
Oracle收购BEA――如何看待J2EE中间件的价值


[原创]从中间件厂商的角度看EJB3标准

在我Support过的许多BEA客户里面,80%依然使用EJB2,20%已经开始使用Spring,但几乎没有看到有真实的大客户在关键系统中使用EJB3,EJB3的技术其实已经很成熟,在分布式能力上,WebLogic EJB2.0容器经过10年的改进,在分布式性能以及稳定性方面,已经相当成熟,强大的JMX支持亦为WebLogic赢得更多的商业用户。尽管EJB2的复杂性,但BEA毕竟将这些复杂性降至最低,比如通过WebLogic的Ant Task扩展,weblogic.ejb.GenericSessionBean等等,但这一切依然没有解决无接口不OO的尴尬局面(EJB3做到了真正的POJO化,即ReviewManagerBean是implements ReviewService,POJOer舒了一口气),且IDE工具的重构也更加容易直观。
EJB3的Annotation改善了POJOer的Coding状况,却没有增加EJB容器厂家很多的工作量。各个中间件厂商依然使用他们原有的EJB CodeBase作为EJB3的基础,因此,我们完全信任EJB3的稳定性和可靠性。
在中间件厂家的角度,EJB3其实可以分为两个部分:
A1,Session Bean、MDB领域【具有分布式容器依赖性】
A2,持久层实现(JPA)【对分布式容器无依赖性】

在A1领域,中间件厂家更关注于属于容器的范畴,即比如为笨重的EJB2容器添加DI能力,无论是Annotation还是XML描述符,都额外简单;你可能有疑问,这些DI是否会增加容器设计的复杂性吗? 显然不会。据我所知,为了支持EJB3后,WebLogic容器的重构了大量的EJB2代码,从weblogic.ejb20抽出了大量的EJB内部接口到weblogic.ejb Package去,且仅仅改写了部分的内部类,于是,我们会看到内核中包含了一些beaninfo.isEjb3的条件分支的判断。
至于MDB,WebLogic 11g之后会融合更强的Oracle JMS Provider实现,性能和可靠性绝对会让人耳目一新。

A2,很久以前,WebLogic明显花了很大的力气去实现Entity Bean,它太难用了,几乎毫无学习的必要,KODO随后被BEA收购,并派生一个OpenJPA的开源项目(输给了Oracle的TopLink Essential开源项目),Oracle收购BEA之后,可能会将TopLink重新融入到WebLogic默认实现中,之前使用KODO结合Spring的被发现很多运行时问题(困扰了我很久,后来索性换成TopLink Essential),可以让开发者大为放心。有着10多年历史、业界领先的TopLink作为WebLogic EJB容器的一部分(JPA Provider方式),它的稳定性也是有目共睹的;另外,要提到的是,TopLink包含了Runtime监控的特性,Oracle移植TopLink到Weblogic11g的时候亦会包含它为OC4J提供的TopLink Runtime Monitor特性,这些特性是容器依赖的,但并不是必须。

对EJB3的客户而言,Codebase的稳定性是非常重要的,从EJB2->EJB3,WebLogic并没有改变太多的EJB核心设计,从而保证了EJB2客户迁移到EJB3所带来的可靠性;另外,持久层方面,从KODO过渡到TopLink,ORM的稳定性和性能亦会有一个不少的飞跃。总之,WebLogic 11g是值得期待的一个强大的EJB3版本。

标签:


订阅 博文 [Atom]