<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Sky's blog

    我和我追逐的夢

    常用鏈接

    統計

    其他鏈接

    友情鏈接

    最新評論

    glassfish下cxf無法運行的問題

        這是近期工作中遇到的一個問題,cxf在glassfish下timeout設置出現問題,進而引發的關于classloader, JAX-WS的一些小故事,很驚訝的發現cxf在這種情況下根本沒有辦法運行于glassfish平臺。

        關鍵字:glassfish, cxf, classloader, JAX-WS, metro。

        首先看問題的發生,我們有一個webservice的客戶端,使用cxf開發,原來運行于weblogic,目前準備移植到glassfish。異常測試中發現timeout設置不再有效,在glassfish平臺上timeout時間似乎是無限?測試中試過等待10分鐘也沒有timeout,socket一直連著,客戶端一直在等應答。

        于是準備增加timeout的設置到cxf中,下面是cxf的timeout的典型設置:

    Client client = ClientProxy.getClient(this.port);
    HTTPConduit http 
    = (HTTPConduit) client.getConduit();
    HTTPClientPolicy httpClientPolicy 
    = new HTTPClientPolicy();
    httpClientPolicy.setConnectionTimeout(
    30 * 1000);
    httpClientPolicy.setReceiveTimeout(
    60 * 1000);
    http.setClient(httpClientPolicy);

        這段代碼在weblogic中是正常工作的,但是在glassfish上就出現問題,“Client client = ClientProxy.getClient(this.port);” 這行會拋出一個異常ClassCastException:

    javax.xml.ws.soap.SOAPFaultException: com.sun.xml.ws.client.sei.SEIStub cannot be cast to org.apache.cxf.frontend.ClientProxy

        google了一下發現這個問題的出現已經在cxf的issue列表中, CXF-2237:
            https://issues.apache.org/jira/browse/CXF-2237   

        從這個網址得到的信息:
        1. That error would mean that the Sun JAX-WS implementation is being picked up instead of the CXF version.
        2. Classpath issue picking up wrong JAX-WS implementation.

        原因似乎很清晰了,但是沒有給出解決方法,繼續google發現類似的問題在jboss平臺也有發現,cxf有給出解決方法。

        于是郁悶了,找了找資料,發現問題可能和JAX-WS有關:

        1. JAX-WS 是用于web service的java api,定義在JSR 224.
        2. sun提供了JAX-WS的一個實現Metro,包含在glassfish中。
        3. sun的實現后來加入了jdk6(不過package和Metro不同)
        4. apache cxf 是另外一個JAX-WS實現

        從上面的異常看,"com.sun.xml.ws.client.sei.SEIStub cannot be cast to org.apache.cxf.frontend.ClientProxy", 像是從"sun impl" -> "cxf impl"的轉換出問題,也就是說runtime時實際運行的是sun的JAX-WS實現,而不是cxf的實現。這個和CXF-2237的描述是一致的,因此問題基本定位出來了:glassfish中cxf的實現沒有被裝載成功。

        隨即查找了一下關于JAX-WS 實現裝載的資料,application是可以通過Provider SPI來選擇不同的JAX-WS實現的,在JSR 224: JAX-WS 2.x 中的chapter 6.2.1 有選擇Provider implementation的規則:

    1. If a resource with the name of META-INF/services/javax.xml.ws.spi.Provider exists, then its first line, if present, is used as the UTF-8 encoded name of the implementation class.
        意思是說查找名為META-INF/services/javax.xml.ws.spi.Provider的資源,如果存在,那么它的第一行,就是實現類的名字。
        我們試著打開cxf的jar文件,發現的確有上述文件,內容只有一行:org.apache.cxf.jaxws.spi.ProviderImpl。然后查找了一下glassfish的jar文件,在glassfish安裝目錄下的lib\webservice-rt.jar中找到了JAX-WS的實現,同樣有META-INF/services/javax.xml.ws.spi.Provider文件,內容為: com.sun.xml.ws.spi.ProviderImpl.

    2. If the ${java.home}/lib/jaxws.properties file exists and it is readable by the java.util.Properties.load(InputStream) method and it contains an entry whose key

    is javax.xml.ws.spi.Provider, then the value of that entry is used as the name of the implementation class.
        類似的,通過${java.home}/lib/jaxws.properties 文件來設置。

    3. If a system property with the name javax.xml.ws.spi.Provider is defined, then its value is used as the name of the implementation class.
        通過系統屬性javax.xml.ws.spi.Provider來設置。

    4. Finally, a default implementation class name is used.
        最后,默認實現,即使就是jdk中的sun的實現,猜測是Metro的某個版本

        從上述規則來看,明顯當前是遵循了第一個規則,從資源META-INF/services/javax.xml.ws.spi.Provider中讀取實現類。而且雖然application中有cxf.jar的存在并且有名為META-INF/services/javax.xml.ws.spi.Provider的資源,但是因為application的classloader在裝載資源時,按照標準的classloader機制,會首先代理給parent classloader,因此最后實際是system classloader首先嘗試裝載資源,glassfish下lib\webservice-rt.jar是屬于system classpath,glashfish的system classloader會查找到并裝載webservice-rt.jar中的META-INF/services/javax.xml.ws.spi.Provider。這樣application中的classloader就沒有機會裝載cxf的META-INF/services/javax.xml.ws.spi.Provider,而是直接使用glassfish system classloader裝載好的javax.xml.ws.spi.Provider,自然就是Metro的實現。

        現在關鍵的問題在于這個規則是第一順序位,后面的2,3根本沒有機會。因此想裝載cxf的JAX-WS實現,就只有想辦法改變classloader的裝載機制,想辦法讓application中的classloader有機會裝載到cxf的JAX-WS實現。

        類似的class 裝載的問題在cxf上就比較常見了,之前在weblogic上也經常遇到類似的,解決的思路就是改變classloader的默認裝載機制,讓application中的classloader自己去裝載而不是代理給system classloader。

        weblogic中對此有專門的設置prefer-application-packages,在weblogic-ejb-jar.xml或者weblogic-application.xml中加入:

          <prefer-application-packages>
                
    <package-name>javax.jws.*</package-name>
          
    </prefer-application-packages>

        就可以指示weblogic,對于上述的package,優先實現application的classloader而不是使用system classloader,從而解決這個問題。

        因為問題的解決思路就很明顯了: 在glassfish中找到類似于prefer-application-packages的方法。

        首先找到的是glassfish中的delegate設置,看delegate的介紹:

    (optional) If true, the web module follows the standard class loader delegation model and delegates to its parent class loader first before looking in the local class loader. You must set this to true for a web application that accesses EJB components or that acts as a web service client or endpoint.

        粗看正是我們想要的,再一看發現不行,delegate的使用是有限制的:
        1. delegate只在sun-web.xml有,只能用于web app,不能用于普通的application
        2. delegate是有限制的,對于"java.*"和"javax.*"的包不能生效的

        隨后的查找發現,非常遺憾,glassfish沒有提供其他的類似機制,因此試圖改變classloader的想法陷入絕境。

        只好先考慮其他的方法,一個思路就是讓glassfish的system classloader直接load到cxf,方法如下:
        1.將cxf的lib包(或者只是META-INF/services/javax.xml.ws.spi.Provider文件)放到glassfish的system classpath下并在lib\webservice-rt.jar之前
        2.刪除lib\webservice-rt.jar
            這個試過了,glassfish直接起不來

        但這些都不是足夠妥當,最后考慮到既然大家都是JAX-WS實現,而且sun的Metro也算做的不錯,因此將錯就錯,考慮直接使用Metro好了。就當前遇到的timeout設置的問題,在Metro中是非常容易解決的:

        Map<String, Object> requestContext = ((BindingProvider) service).getRequestContext();
        requestContext.put(
    "com.sun.xml.ws.connect.timeout"30 * 1000);
        requestContext.put(
    "com.sun.xml.ws.request.timeout"60 * 1000);

        至此這次timeout的設置問題總算解決了,但是,依然沒有辦法解決glassfish的classloader問題,以后如果遇到類似的需要application優先裝載特定類的情況,還是會遭遇同樣的困境。這里比較奇怪的是,為什么glassfish會沒有類似的設置,按說既然glassfish已經給出了delegate這個設置,說明glassfish已經意思到有這個需要并且也給出了部分解決方法,但是為什么對應于application確不給出任何解決方案呢?百思不得其解。

        而從上面的描述也可以看出,如果不使用特殊的方法,正常情況下,applicatio是沒有辦法裝載到cxf的JAX-WS實現的,實際在runtime時跑的是metor的實現。


    posted on 2010-03-24 14:52 sky ao 閱讀(3146) 評論(0)  編輯  收藏 所屬分類: web service

    主站蜘蛛池模板: 免费的黄网站男人的天堂 | 亚洲天堂2017无码中文| 免费无码肉片在线观看| 一级看片免费视频| 亚洲精品免费在线| avtt亚洲天堂| 曰批视频免费30分钟成人| 国产亚洲视频在线| 77777_亚洲午夜久久多人| 日韩免费视频一区| 99久久人妻精品免费二区| 综合偷自拍亚洲乱中文字幕| 亚洲av永久无码精品国产精品| 免费无码黄网站在线观看| 国产免费一区二区视频| 欧美色欧美亚洲另类二区| 亚洲国产精品热久久| 亚洲国产精品成人一区| 91成人免费观看网站| 男女一进一出抽搐免费视频 | 亚洲w码欧洲s码免费| 污网站在线观看免费| 久久久久亚洲av无码专区导航| 无码欧精品亚洲日韩一区夜夜嗨 | 亚洲综合激情五月色一区| 国产亚洲综合久久系列| 国产精品无码一区二区三区免费 | 中文日本免费高清| 亚洲av最新在线观看网址| 亚洲日韩图片专区第1页| 亚洲国产免费综合| 大学生美女毛片免费视频| 久久久免费的精品| 人妻仑刮八A级毛片免费看| 午夜在线a亚洲v天堂网2019| 亚洲国产精品自在在线观看| 亚洲一区二区视频在线观看| 日本免费高清一本视频| 中文字幕无码免费久久99 | AV无码免费永久在线观看| 男人都懂www深夜免费网站|