`
liuInsect
  • 浏览: 132014 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

CXF传输复杂对象问题

    博客分类:
  • CXF
 
阅读更多

 这两天在做使用CXF框架的时候遇到了一个传输复杂对象的问题,问题如下:

 
背景:
 
首先,我定义一个JavaBean WebServiceResult 里面有这么几个属性:
private boolean success =false;
private Map<String,List<Topic>> result = new HashMap<String,List<Topic>>();
private ArrayList<Topic> topics ;
private transient String resultCode;
 
其中,Map我暂且叫做“复杂对象” 因为 一个map里面,装了一个list,而list里面又装了一个自己的JavaBean Topic(活动信息)
接口调用完成后会用WebServiceResult 封装调用结果返回给客户端
 
用客户端调用该接口后发现,result属性值为null,但是,对服务端的debug排除了没有set值的情况,查看后还发现了服务端抛出了
"class XXX nor any of its super class is known to this context" 的异常
 
排查过程:
 
     1. 从异常内容可以看到CXF内部应该有至少一个上下文环境存放当前接口涉及到的Java类的class信息
     2. 通过异常定位到CXF内部,debug后理解上下文环境,可以看到,异常出自这里:

  
     fatal在调用的时候就写死了为true,当bi为null时,就会报出异常,再看getBeanInfon内部:

 
     o对象既是需要将数据绑定到xml文件上的对象,在这里是o是接口调用后返回的对象
     比如:接口方法签名为:
 
      那这里的o可能是WebServiceResult,和WebServiceResult内部的各个实例变量(是"循环遍历"WebServiceResult内的所有对象,调用getBeanInfo方法)
     回到getBeanInfon方法,程序会从beanInfoMap中取出预置好的将Bean映射到xml上的对象JaxBean(这里先卖个弯子,后面会说到它怎么来的)
     如果beanInfoMap里没有这个class对应的JaxBeanInfo对象,就会return一个null,导致了异常的报出。
  
  几个疑问:
        
     1. JaxBeanInfo是做什么的?
          JaxBeanInfo里封装了对大部分Java类映射方式,即,怎么把数据映射到XML上主要方法有:          
          
      主要子类有:
          
  
     2. beanInfoMap是做什么的?
         我的理解是:在服务端初始化的时候,CXF会去看这个接口里,参数和返回值的类型,并根据类型生成相应的JaxBeanInfo对象放在map里面,
     这里好理解,就是等接口被调用时知道 "怎么" 把返回值 映射到XML上,传给客户端。
 
     3. 既然是在服务端初始化的时候去遍历方法签名,将涉及的Bean的相对应的解析对象放到Map中,又怎么会在接口返回的时候找不到解析该Bean的JaxBean呢?
         回到这段代码:

 
再看他的上层调用:

 
   问题就在这里,如WebServiceResult 中的声明:private Map<String,List<Topic>> result = new HashMap<String,List<Topic>>();
     CXF在初始化的时候,“登记”的是List,保存的class信息为java.util.List 而我们在时间使用的时候,通常是这样,
     List<Topic> topics = new ArrayList<Topic>() 这个时候,topics的class信息是:java.util.ArrayList
     当接口调用返回的时候,上图中的 : boolean asExpected = chlid.getCalss() == expected.jaxbType;
     就是那 java.util.List == java.util.ArrayList  导致比较失败,最终进入grammar.getBeanInfo去拿jaxBeanInfo的时候,
     因为”登记“的是java.util.List的JaxBeanInfo而不是java.util.ArrayList,导致拿不到jaxBeanInfo,最后报出异常。
 
解决方法
     解决方法非常简单,当我们在声明接口参数和返回值的时候,别使用到接口或者抽象类 比如java.util.List等
     而是直接写成他们的实现类或者子类 保证实际调用方法的时候的class信息和方法声明的class信息是一致的就可以了,因此,WebServiceResult 改为如下后,可以正常传输
     
     private boolean success =false;
   private Map<String,ArrayList<Topic>> result = new HashMap<String,ArrayList<Topic>>();
   private ArrayList<Topic> topics ;
   private transient String resultCode;
 
ps: 网上有说CXF不支持Map等复杂对象的传输,经过测试,在Jaxb 2.1(CXF 2.2 版本依赖)版本是不存在该问题的。
    
未解决的问题:
     1. Map<String,ArrayList<Topic>> 格式的result传输不会报错,但是map中的list的值会"丢失",即,客户端收到的是空的List(单独一个List传输是不会的)。
 
遗留下来的问题,有空再解决下,大家有知道的也请楼下回复
     
 

 

  • 大小: 12.8 KB
  • 大小: 4.1 KB
  • 大小: 17.1 KB
  • 大小: 13.8 KB
  • 大小: 46.6 KB
  • 大小: 2.2 KB
  • 大小: 14.3 KB
0
1
分享到:
评论
4 楼 liuInsect 2013-02-11  
果是老的项目,当然要考虑兼容。但如果是新项目,我是在想象不出xml对json有什么优势。以前我们的项目一直用Xfire,我相信Xfire是CFX的前身。Xfire其实很好用,但是坏处是客户端太重,json几乎对所有客户端都是中立的。而且json没有scheme,对对象的表现力也比xml好。
elgs 写道
liuInsect 写道
elgs 写道
很难想象现在webservice对json还有什么优势?

使用的场景不同,不能一概而论


楼主文章很好,谢谢。
如果是老的项目,当然要考虑兼容。但如果是新项目,我是在想象不出xml对json有什么优势。以前我们的项目一直用Xfire,我相信Xfire是CFX的前身。Xfire其实很好用,但是坏处是客户端太重,json几乎对所有客户端都是中立的。而且json没有scheme,对对象的表现力也比xml好。


赞成。 但是我更愿意说 最快的应该还是基于二进制的方法调用,因为无论是XML还是JSON都只是能保证调用,但是在调用次数上去以后,什么都是浮云,所以,CXF这类的框架都是二等技术。。。。
3 楼 elgs 2013-02-08  
liuInsect 写道
elgs 写道
很难想象现在webservice对json还有什么优势?

使用的场景不同,不能一概而论


楼主文章很好,谢谢。
如果是老的项目,当然要考虑兼容。但如果是新项目,我是在想象不出xml对json有什么优势。以前我们的项目一直用Xfire,我相信Xfire是CFX的前身。Xfire其实很好用,但是坏处是客户端太重,json几乎对所有客户端都是中立的。而且json没有scheme,对对象的表现力也比xml好。
2 楼 liuInsect 2013-02-07  
elgs 写道
很难想象现在webservice对json还有什么优势?

使用的场景不同,不能一概而论
1 楼 elgs 2013-02-07  
很难想象现在webservice对json还有什么优势?

相关推荐

    Webservice笔记含使用cxf和jaxws两种方式开发webservice【源代码+笔记】

    第一天: 什么是webservice? 从案例(便民查询网站... 测试jaxws传输复杂对象类型 CXF开发webservice: CXF入门程序 Spring+cxf整合(重点) CXF发布rest的webservice。(重点) 综合案例: 实现便民查询网站

    java调用wsdl接口源码-cxf-plus:apachecxf在支持通用数据类型方面的增强

    增强的反射机制,可以对接口和POJO对象中的嵌套泛型、继承泛型等进行完整的解析,从而使得带有各种复杂泛型的接口可以正确发布和传输。 简化集成,针对目前大多数服务使用SpringFramework的特点,自动查找JAX-WS和...

    疯狂XML讲义

    尤其是电子拍卖系统,它是一个包含5个表,表之间具有复杂关联映射的系统,该案例采用目前最流行、最规范的轻量级Java EE架构,将整个应用分为领域对象层、DAO层和业务逻辑层,然后用CXF将业务逻辑组件包装成Web ...

    疯狂XML讲义(Web Service).pdf

    尤其是电子拍卖系统,它是一个包含5个表,表之间具有复杂关联映射的系统,该案例采用目前最流行、最规范的轻量级Java EE架构,将整个应用分为领域对象层、DAO层和业务逻辑层,然后用CXF将业务逻辑组件包装成Web ...

    疯狂xml讲义

    尤其是电子拍卖系统,它是一个包含5个表,表之间具有复杂关联映射的系统,该案例采用目前最流行、最规范的轻量级Java EE架构,将整个应用分为领域对象层、DAO层和业务逻辑层,然后用CXF将业务逻辑组件包装成Web ...

    疯狂XML讲义.part3.rar

    尤其是电子拍卖系统,它是一个包含5个表,表之间具有复杂关联映射的系统,该案例采用目前最流行、最规范的轻量级Java EE架构,将整个应用分为领域对象层、DAO层和业务逻辑层,然后用CXF将业务逻辑组件包装成Web ...

    疯狂XML讲义.part1

    尤其是电子拍卖系统,它是一个包含5个表,表之间具有复杂关联映射的系统,该案例采用目前最流行、最规范的轻量级Java EE架构,将整个应用分为领域对象层、DAO层和业务逻辑层,然后用CXF将业务逻辑组件包装成Web ...

    疯狂XML讲义.part2.rar

    尤其是电子拍卖系统,它是一个包含5个表,表之间具有复杂关联映射的系统,该案例采用目前最流行、最规范的轻量级Java EE架构,将整个应用分为领域对象层、DAO层和业务逻辑层,然后用CXF将业务逻辑组件包装成Web ...

    疯狂XML讲义 源码

    尤其是电子拍卖系统,它是一个包含5个表,表之间具有复杂关联映射的系统,该案例采用目前最流行、最规范的轻量级Java EE架构,将整个应用分为领域对象层、DAO层和业务逻辑层,然后用CXF将业务逻辑组件包装成Web ...

    ASP EXCEL导入SQL

    而以序列化的JavaScript对象为基础的JSON已经获得了广泛认可,它被认为能以远比XML更好的方式来序列化和传输简单数据结构,而且它更简洁。这对REST是一个极大贡献和补充。  当前的网络应用软件还违背了REST的“无...

Global site tag (gtag.js) - Google Analytics