• DWR的BUG 【转】


    使用DWR开发项目,好象没有什么BUG。事实上也的确如此,在网上见到的大多是赞美之词,其实把它和hibernate放在一起工作,就会出现很多问题。当然它们中的有些问题不一定就是DWR的事,也有hibernate的问题。

    一、转换一对多值对象出现的问题

    我在《DWR帮助文档-dwr.xml文件的配置》一文中提到,我们应当把在dwr中用到的所有值对象都注册到dwr.xml配置文件中。在配置值对象的时候,有2种方式:使用model.*这种通配符的方式一次性将多个值对象进行注册;使用hibernate3或hibernate2的方式一个一个注册值对象。同时我也提到,使用第一种方式注册虽然简便,但存在不利于编写前端页面和性能差的问题,不推荐使用;使用第二种方式注册有利于程序的编写和性能的提高,但在dwr中存在bug。这样的bug是什么呢?我们不妨举一个实例来说明。假如在项目中存在部门和员工的值对象,并且是一对多的关系(每一个员工都只能在一个部门,但多个员工可以在用一个部门),那么hibernate在查询员工的时候会返回一个员工值对象的集合,集合中的每一个员工值对象都有一个部门属性,对应一个部门值对象,但多个员工值对象对应的可能是一个部门值对象。这个关系很清晰,也应该没有什么疑问,但在dwr将其转换为js中的对象的过程中却会发生错误。错误的提示是这样的:

    1. directwebremoting.extend.MarshallException: Error marshalling com.htxx.demo.model.Employee: Ignoring request to inline on reference for: Object:s0:{departmentId=Simple:"001", departmentName=Simple:"\人\力\资\源\部", employees=Simple:null}. See the logs for more details.   
    2.   
    3.        at org.directwebremoting.convert.BasicObjectConverter.convertOutbound(BasicObjectConverter.java:200)   
    4.   
    5.        at org.directwebremoting.dwrp.DefaultConverterManager.convertOutbound(DefaultConverterManager.java:192)   
    6.   
    7. ...    
    8.   
    9. Caused by: java.lang.IllegalStateException: Ignoring request to inline on reference for: Object:s0:{departmentId=Simple:"001", departmentName=Simple:"\人\力\资\源\部", employees=Simple:null}   
    10.   
    11.        at org.directwebremoting.dwrp.AbstractOutboundVariable.getReferenceVariable(AbstractOutboundVariable.java:148)   
    12.   
    13.        at org.directwebremoting.dwrp.DefaultConverterManager.convertOutbound(DefaultConverterManager.java:181)   
    14.   
    15.        at org.directwebremoting.convert.BasicObjectConverter.convertOutbound(BasicObjectConverter.java:189)   
    16.   
    17.        ... 28 more   

    org.

    仔细查看和跟踪源码,我发现这个问题出在AbstractOutboundVariable类的getReferenceVariable方法中,它的源码是这样写的:

    public OutboundVariable getReferenceVariable()   
    {   
        if (reference == null)   
        {   
            reference = new ReferenceOutboundVariable(getVariableName());   
            if (forcedInlineStatus)   
            {   
                throw new IllegalStateException("Ignoring request to inline on reference for: " + this);   
            }   
            else  
            {   
                setInline(false);   
            }   
        }   
        return reference;   
    }  

    当dwr已经使用了某个对象以后,就会将它的forcedInlineStatue置为true,当dwr再次装载这个对象的时候就会强制抛出IllegalStateException异常。这在通常情况下是没有问题的,但在我们前面提到的例子中就有问题了。当dwr转换员工值对象集合的时候,首先装载和转换了员工甲,他因为是“研发1部”所以dwr也装载了“研发1部”这个部门值对象。然后dwr开始装载和转换员工乙。由于员工乙也是“研发1部”,因此dwr又开始装载“研发1部”这个值对象,但突然发现这个值对象已经装载过了,因而就抛出了以上错误。如果我们希望整合dwr、spring、hibernate到一起进行项目开发,以上这个问题是怎么也不能避免的,问题是如何解决。非常遗憾的是,dwr官方似乎还没有要解决这个问题的意思,我思索再三以后决定,还是“自己动手丰衣足食”吧。解决的办法其实很简单,就是把11行这个强制抛出异常注释掉,然后重新编译。这样修改以后就再也没有出现以上问题,同时至今也没有发现其它问题出现。

    二、转换一对一值对象出现的问题

    这个问题我同样在《DWR帮助文档-dwr.xml文件的配置》一文中提到过,就是dwr在转换一对一值对象关系时出现死循环的问题。假如Employee值对象存在一个且最多一个Address值对象的时候,Employee有一个Address属性指向一个Address值对象,而Address值对象也同样会有一个Employee属性指向这个Employee值对象。我们知道hibernate对于一对一关联是不进行延迟加载的,所以dwr在装载和转换Employee值对象的时候会去加载它的Address值对象,然后在加载这个Address值对象的时候会又去加载那个Employee值对象。如此反复加载就形成了死循环。解决这个问题的办法就是在dwr.xml配置Address的时候,使用exclude禁用它对Employee的加载。详细说明见《DWR帮助文档-dwr.xml文件的配置》,这里就不再罗嗦了。

    三、找不到值对象中set函数的问题

    在使用dwr执行插入和更新操作的时候,有时会出现以下的警告:Missing java bean property to match javascript property:[属性名]. For causes see debug level logs:

    如果将log4j中dwr的级别降低为DEBUG级别,你还可以在控制台中看到一下提示:You may be missing the correct setter: setXXX()The property may be excluded using include or exclude rules.

    其实你并没有在dwr中禁用这个属性,同时也正确地在值对象中编写了一个setXXX()方法的,这个问题到底出在哪里呢?我查看了dwr的源码发现,dwr是如何获得一个值对象的所有属性及其各自的get和set方法呢?是采用Java的反向机制。如果你通过自己去编写或修改某个属性及其它的get和set方法,而不是通过工具生成,那么反向机制就可能找不到这个属性的get和set方法(注意,是可能而并不总是这样)。这个问题解决的办法就是删除该属性的get和set方法,然后使用MyEclipse的get和set方法生成工具自动生成。

    四、找不到值对象的LazyInitializer的问题

    在使用dwr执行插入和更新操作的时候,有时会抛出这样一个离谱的异常:

    java.lang.

    1. NoSuchMethodError: com.htxx.demo.model.Department.getHibernateLazyInitializer()Lorg/hibernate/proxy/LazyInitializer;   
    2.     at com.htxx.demo.model.Department$$EnhancerByCGLIB$$f4b4f445.getHibernateLazyInitializer()   
    3.     at org.directwebremoting.hibernate.H3BeanConverter.getClass(H3BeanConverter.java:139)  

    之所以说这个异常比较离谱,是因为它似乎就没有dwr什么事。事实上它也是没有dwr什么事,而是hibernate出错了。查看hibernate的官方网站你可以发现这个bug的发布,并在hibernate3.2.0.rc4以后的版本这解决这个问题了。将hibernate3换成最新版本后果然就解决这个问题了。

    五、执行查询时找不到hibernate查询工厂类的问题

    这个还是hibernate3的问题。在执行查询的时候在控制台显示这样一个错误:

    CharScanner; panic: ClassNotFoundException: org.hibernate.hql.ast.HqlToken

    遇到这个问题不要怕,其实解决的方法很简单,就是在spring的配置文件ApplicationContext-hibernate.xml中,在sessionFactory的hibernateProperties属性中增加这样一段话:

    xml 代码

    <property name="hibernateProperties">  
        <props>  
           ...   
           <prop key="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactoryprop> </prop> 
           </props>  
    </property>

    六、在JDK1.4中运行和部署DWR2和hibernate3出现的问题

    在DWR2.0中提供了一些JDK5中才能使用的annotations的功能。然而,这个功能在JDK1.4的环境中进行启动或者部署会发生错误。抱歉的是这个错误信息我没有及时记录,日后补上。这个错误在网上可以轻易地搜索到解决方案,即在dwr.jar中删除掉org.directwebremoting.annotations.AnnotationsConfigurator这个类再重新部署就可以了。

    同样的问题出现在hibernate3中,hibernate3对annotations的支持在JDK1.4中也可能出现异常,解决的办法就是在部署文件中删除掉hibernate-annotations.jar就可以了。

    另外值得说明的是,以上2个问题并不是每次都会出现的。它们就如同幽灵一样有时出现有时不出现,因此我们并不需要总是删除这个类和jar包,只是在发生错误时才删除。

  • 相关阅读:
    03人脉搜索:学会这一招,就能轻松找到90%的人的联系方式
    02 资源搜索-全面、快速查找全网你想要的任何信息、情报
    01信息搜索:全面、快速查找全网你想要的任何信息、情报.
    ansible笔记(12):handlers的用法
    ansible笔记(11):初识ansible playbook(二)
    ansible笔记(10):初识ansible playbook
    ansible笔记(9):常用模块之包管理模块
    ansible笔记(8):常用模块之系统类模块(二)
    ansible笔记(7):常用模块之系统类模块
    ansible笔记(6):常用模块之命令类模块
  • 原文地址:https://www.cnblogs.com/macula/p/2881046.html
Copyright © 2020-2023  润新知