• CXF向后兼容性(backwards compatibility)解决方案


    当在CXF服务端pojo中添加一个新属性后,未经重新generate的客户端会在调用该web service时报UnmarshalException: unexpected element,错误日志如下:

    DefaultValidationEventHandler: [ERROR]: unexpected element (uri:"", local:"areaId"). Expected elements are <{}dmsSiteCode>,<{}provinceId>,<{}countryId>,<{}mail>,<{}phone>,<{}siteType>,<{}cityId>,<{}orgName>,<{}siteCode>,<{}orgId>,<{}staffNo>,<{}address>,<{}staffName>,<{}subType>,<{}role>,<{}customCode>,<{}sitePhone>,<{}countrySideId>,<{}targetType>,<{}storeCode>,<{}siteName> 
         Location: line 1
    2013-1-5 16:43:20 org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging
    警告: Interceptor for {http://webservice.basic.etms.***.com/}BasicForeignWebServiceService#{http://webservice.basic.etms.***.com/}selectSiteBySubtype has thrown exception, unwinding now
    org.apache.cxf.interceptor.Fault: Unmarshalling Error: unexpected element (uri:"", local:"areaId"). Expected elements are <{}dmsSiteCode>,<{}provinceId>,<{}countryId>,<{}mail>,<{}phone>,<{}siteType>,<{}cityId>,<{}orgName>,<{}siteCode>,<{}orgId>,<{}staffNo>,<{}address>,<{}staffName>,<{}subType>,<{}role>,<{}customCode>,<{}sitePhone>,<{}countrySideId>,<{}targetType>,<{}storeCode>,<{}siteName> 
         at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:773)
         at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:624)
         at org.apache.cxf.jaxb.io.DataReaderImpl.read(DataReaderImpl.java:150)
         at org.apache.cxf.interceptor.DocLiteralInInterceptor.handleMessage(DocLiteralInInterceptor.java:99)
         at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:244)
         at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:664)
         at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:2160)
         at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:2040)
         at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1965)
         at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:66)
         at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:627)
         at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
         at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:244)
         at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:478)
         at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:308)
         at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:260)
         at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:73)
         at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:124)
         at $Proxy59.selectSiteBySubtype(Unknown Source)
         at com.jd.syn.wsFacde.WSClient.initBaseCarrierSynDate(WSClient.java:100)
         at com.jd.syn.handler.BaseCarrierSyn.initSyn(BaseCarrierSyn.java:71)
         at com.jd.syn.handler.AbstractSyn.execute(AbstractSyn.java:36)
         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
         at java.lang.reflect.Method.invoke(Method.java:597)
         at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:273)
         at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:264)
         at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:86)
         at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
         at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:525)
    Caused by: javax.xml.bind.UnmarshalException
     
    为了避免反复重新生成客户端代理类,我们必须想一个绕过该Validation的方式。幸运的是,这个问题可以通过提供一个自定义的ValidationEventHandler来解决(仔细看你会发现这个解决方式很取巧)
    import javax.xml.bind.ValidationEvent;
    import javax.xml.bind.ValidationEventHandler;
    
    public class IgnoreUnexpectedElementsHandler implements ValidationEventHandler {
    @Override
    public boolean handleEvent(ValidationEvent event) {
      //true: keep going. In this case we only want to continue for the error we're trying to hide.
      return event.getMessage().startsWith("unexpected element (");
    }
    }
    之后在你的客户端配置中加入<entry key="jaxb-validation-event-handler" value-ref="ignoreUnexpectedElementsHandler">
    具体配置如下:
    <jaxws:client id="basicForeignWebService" serviceClass="com.***.syn.ws.basicforeignwebservice.BasicForeignWebService"
              address="${promise.basicForeignWebService.ws.wsdl.address}">
              <jaxws:outInterceptors>
                   <ref bean="header" />
              </jaxws:outInterceptors>
              <jaxws:properties>
                   <entry key="jaxb-validation-event-handler" value-ref="ignoreUnexpectedElementsHandler">
                   </entry>
              </jaxws:properties>
    </jaxws:client>
  • 相关阅读:
    let与const的区别
    IOS客户端UIwebview下web页面闪屏问题
    移动端click事件延迟300ms问题
    css3+visbibilty解决淡入淡出问题
    git学习之branch分支
    git学习之冲突解决办法
    webpack+vue-cli项目打包技巧
    一个高级PHP工程师所应该具备的
    多站点
    PHP error_reporting() 错误控制函数功能详解
  • 原文地址:https://www.cnblogs.com/qunyang/p/2848158.html
Copyright © 2020-2023  润新知