月蝕傳說

          浮躁讓人失去理智
          posts - 25, comments - 101, trackbacks - 0, articles - 0
            BlogJava :: 首頁 ::  :: 聯(lián)系 :: 聚合  :: 管理

          1.? 遠程服務(wù)概念


          顧名思義,遠程服務(wù)是指可以通過遠程通訊進行調(diào)用的服務(wù)。

          SCA 中,在定義服務(wù)的時候可以將服務(wù)定義為遠程服務(wù),通過 @Remotable 標簽加在服務(wù)接口的類名上,就將該服務(wù)接口定位為了遠程服務(wù)。


          SCA
          規(guī)范中這樣規(guī)定遠程服務(wù)的

          Remotable services are services that can be published through entry points. Published services can be?
          accessed by clients outside of the module that contains the component that provides the service.

          Whether a service is remotable is defined by the interface of the service. In the case of Java this is defined

          by adding the @Remotable annotation to the Java interface. A service whose interface is defined by a Java class is not remotable. "


          上面這段話主要意思是說,一個遠程服務(wù)可以通過
          Entry Points 進行發(fā)布,并且能夠被該服務(wù)所在模塊以外,但包含了該服務(wù)的組件所調(diào)用,并且,遠程服務(wù)只能定義在 Java 接口類上,如果利用 Java 實現(xiàn)類(非 interface java 類)定義的服務(wù)進行 @Remotable 注釋,這種遠程服務(wù)是無效的。


          可能上面的話有點太含糊其詞,我們下面具體講一下
          SCA 遠程服務(wù)的定義,以及 uxsca 容器實現(xiàn)該標準的簡要實現(xiàn)手段。


          2.?
          定義遠程服務(wù)

          根據(jù)上面我們所講的,在一個已經(jīng)被定義為服務(wù)的接口的接口類上加上注釋 @Remotable ,這樣就表示該 sca 服務(wù)將會是一個遠程服務(wù)。就這么簡單!


          3
          UxSCA 容器中遠程服務(wù)的實現(xiàn)概要


          的確,光從
          sca 規(guī)范上來看,一個遠程服務(wù)的定義是如此簡單,但是具體怎么去使用以及使用場合 ,SCA 規(guī)范中沒有給出詳細的示例,所以這里我也只能是根據(jù)遠程服務(wù)定義去做實現(xiàn)了。


          既然是遠程服務(wù),首先想到的實現(xiàn)手段就是
          Web service ,當然,也可以用 Java 遠程調(diào)用。


          既然使用
          Web service ,那在 Java 語言里, Axis 是一個既簡單又使用的 Web service 組件了。這里簡單說一下 Axis 是如何實現(xiàn) web service 的:


          Axis
          其實也是通過 servlet 來實現(xiàn) web service 的,通過一個 HTTP 的訪問, Axis servelet 會去獲得這段 HTTP Request 信息, HTTP 協(xié)議上架著 SOAP , Axis 解析出 SOAP 后定位到具體的一個 Java 實現(xiàn),然后在將該 Java 實現(xiàn)執(zhí)行后的結(jié)果(或者沒有返回結(jié)果)再構(gòu)造成對應(yīng)的 SOAP 返回回去。一般情況下,訪問 Axis 的客戶端是使用的 Axis 生成的客戶端代碼。 Axis web service 實現(xiàn)大致如上所述,如有錯誤請讀者指出。


          Axis
          創(chuàng)建 Web service 的方法一般有 2 種:

          1?. Axis 實現(xiàn) Web service 可以通過 jws 文件來定位服務(wù),也就是將一個寫好的單獨的 Java 類( .java 文件)改后綴名為 .jws ,然后放到 Axis webapp 下。訪問的 URL 如下:


          ??????????????? Http://webserveraddress/axis/services/SomeJws.jws


          當我們通過上面的
          url 去訪問的時候, Axis 會去查找編譯好的 java 類,然后執(zhí)行后返回結(jié)果。

          這種方法很簡單,但是很不實用。

          2.
          Axis 可以通過生成好的 wsdl ,利用 WSDL2Java 工具類產(chǎn)生 Axis 所需要的 wsdd 配置文件,并且生成對應(yīng)客戶端以及一些數(shù)據(jù)對象( DO )代碼。然后通過 Axis 工具類生成一個 server-config.wsdd 文件,將原先生成好的 wsdd 文件中的 service 配置加入到其中,再生成編譯好的 Java 類連同 server-config.wsdd 配置文件一同放到 Axis webapp 目錄下對應(yīng)的位置,這樣可以通過 Axis 生成的客戶端去調(diào)用這個 web service 了。

          ?

          UxSCA 是利用第二種方式去構(gòu)建遠程服務(wù)的。步驟如下:


          UxSCA
          本身是一個 Web 應(yīng)用,它的 web.xml 中加入了 Axis servlet ,這樣就可以不去單獨將 Axis 作為一個 Web 應(yīng)用來獲得 Web service 的請求了。而 UxSCA 在啟動的時候(并不是 Web 服務(wù)容器啟動的時候),會去解析在自己維護下的模塊,從而獲得各個模塊的服務(wù)配置,然后:

          1. 首先解析出遠程服務(wù)接口類,以及其實現(xiàn)類。

          2.?? 然后邊歷接口類中可以發(fā)布的接口方法(可發(fā)布的接口方法,必須是參數(shù)或者返回值都是簡單類型或者是 SDO 類型),生成對應(yīng)的 WSDL 文件。

          3.?? 利用生成好的 WSDL 文件以及服務(wù)接口類再生成 server-config.wsdd 中的 service 元素片段,并加入到該文件中(如果 server-config.wsdd 不存在, UxSCA 會自動生成)

          在作完以上工作后, UxSCA 會去自動啟動 Web 服務(wù)容器,這樣一來,遠程調(diào)用就可以通過 uxsca 容器去訪問遠程服務(wù)了。

          ?

          其中有幾個問題存在:

          1.??? 服務(wù)的查詢是由 SCA 容器去管理的,外部具有遠程服務(wù)的接口的模塊組件怎么去獲得非本地模塊中的服務(wù)定義呢?

          2.??
          Axis 目前只支持 Castor XMLBean 或者 JavaBean 的復雜類型數(shù)據(jù)結(jié)構(gòu),如何讓 Axis 支持 SDO 以及 JAXB 數(shù)據(jù)結(jié)構(gòu)呢?

          3.?? 如果外部模塊獲得了遠程服務(wù)的接口, SCA 容器在返回接口實現(xiàn)的時候卻不會有一個真正的接口類實現(xiàn),就是說,外
          部模塊只有一個
          interface 類,沒有實現(xiàn)類(廢話),如何去返回一個能讓其調(diào)用的類呢?


          對于第一個問題,我本人沒有想好,目前也只有一個不成熟的解決辦法:
          SCA 在部署的時候能夠知道各個節(jié)點的位置,然后再統(tǒng)一啟動,每一個節(jié)點啟動解析完成后再通過網(wǎng)絡(luò)通訊將解析出來的服務(wù)模型反饋給每一個接點,這樣每一個接點上都會有其他接點的服務(wù)描述,于是在使用 ModuleContext 定位服務(wù)時候也就可以作到一致了。當然這只是我個人的想法,行不行得通還需要再去熟悉 SCA 規(guī)范后加上實踐才能證明其合理性。


          第二個問題相對簡單一點,請看我的另一篇文章:
          Axis 支持 EMF 類型


          第三個問題如下:

          假設(shè)我們定義了一個TestInterface接口,并且有一個實現(xiàn)類,TestInterfaceImpl,現(xiàn)在我們的某一個客戶端只擁有TestInterface這個接口類,而TestInterfaceImpl是在服務(wù)端的。所以在客戶端中,是找不到有關(guān) TestInterface 的實現(xiàn)的,所以這里使用了 Java 的動態(tài)接口代理。利用 Proxy ,在用戶調(diào)用的時候,采用 Axis 的客戶端代碼訪問 Web Service

          ?

          4 .遠程服務(wù)使用示例
          先下載UxSCA包。
          新的UxSCA是和Tomcat幫定在了一起,它作為一個Tomcat的webapp存在。在Tomcat啟動的時候會去查詢定義的Module以及定義的服務(wù)。當前UxSCA版本并不是完整的版本,只是為了測試遠程服務(wù)而做的,在以后會完善改進。

          下載地址(壓縮包分成了三份):
          Balto1

          Balto2

          Balto3
          準備環(huán)境:Eclipse-WTP 1.0
          先將下載好的帶有UxSCA的Tomcat釋放到某個目錄下。
          選擇Eclipse的首選項(Preferences...),增加一個Server Runtime,路徑指定到下栽好的Tomcat:

          balto1.JPG?

          然后在webapps中找到一個balto.war,并倒入到Eclipse工程中。

          如果讀者不是在WTP下調(diào)試,則不需要倒入。

          然后新建立一個Java工程,命名為RemoteProject。

          在該工程下建立一個XSD文件:Element.xsd,
          這個Schema比較簡單,只有一個元素:Element,Element有兩個屬性:name,age:

          ?

          <? xml?version="1.0"?encoding="UTF-8" ?>
          < schema? xmlns ="http://www.w3.org/2001/XMLSchema"
          ????targetNamespace
          ="http://www.example.org/Element"
          ????xmlns:tns
          ="http://www.example.org/Element" >
          ????
          < element? name ="Element" >
          ????????
          < complexType >
          ????????????
          < attribute? name ="name" ?type ="string" ></ attribute >
          ????????????
          < attribute? name ="age" ?type ="int" ></ attribute >
          ????????
          </ complexType >
          ????
          </ element >
          </ schema >

          選擇這個Schema點擊右鍵,選擇新建一個EMF Model:

          balto2.JPG

          然后根據(jù)向?qū)梢粋€Element.genmodel文件,打開這個文件后會出現(xiàn)一個編輯界面,選中根元素后點右鍵,選擇:Set SDO Defaults:

          emfmodel.JPG

          然后選擇Generate Model Code,完成后我們發(fā)現(xiàn)在src下多出了一堆代碼,這就是SDO模型代碼:

          modelcode.JPG

          然后修改一下生成的代碼:打開生成的ElementPackageImpl類,找到createExtendedMetaDataAnnotations方法,將

          addAnnotation
          ??????????(elementTypeEClass,?
          ???????????source,?
          ???????????
          new ?String[]?{
          ?????????????
          " name " ,? " Element_._type " ,
          ?????????????
          " kind " ,? " empty "
          ???????????});

          該成:

          addAnnotation
          ??????????(elementTypeEClass,?
          ???????????source,?
          ???????????
          new ?String[]?{
          ?????????????
          " name " ,? " Element " ,
          ?????????????
          " kind " ,? " empty "
          ???????????});

          改這段代碼的目的是為了讓EMF序列化模型的時候生成的XML片段準確一點,也就是Element_._type元素名要改成Element.

          這里需要注意,如果我們生成SDO代碼是由Ecore生成的,就不會有上述的問題,如果是以XSD生成的就會出現(xiàn)這種情況。

          然后我們還需要改一些其他代碼,找到initializePackageContents方法:

          initEClass(documentRootEClass,?DocumentRoot. class ,? " DocumentRoot " ,? ! IS_ABSTRACT,? ! IS_INTERFACE,?IS_GENERATED_INSTANCE_CLASS);
          .....
          initEClass(elementTypeEClass, ElementType.class, "ElementType", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);


          將上面代碼修改為:

          initEClass(documentRootEClass,?DocumentRootImpl. class ,? " DocumentRoot " ,? ! IS_ABSTRACT,? ! IS_INTERFACE,?IS_GENERATED_INSTANCE_CLASS);
          .....
          initEClass(elementTypeEClass, ElementTypeImpl.class, "ElementType", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);


          改這段代碼的目的是為了讓UxSCA能認出我們的復雜類型是一個SDO模型。因為在UxSCA在遇到EMF模型時候,會去查看這個

          EClass的instance類是否是一個SDO模型,但是在EMF生成的代碼中,EClass的instance類是一個接口類,而且該接口類沒有

          實現(xiàn)EObject以及DataObject。當然,這是UxSCA的一個局限性,在以后的版本中我會改進的。


          現(xiàn)在我們已經(jīng)生成了我們的數(shù)據(jù)對象,在該工程下建立一個接口:MyRemotableService,該接口具有兩個方法:getElement和

          getName,getElement返回的是我們剛才生成的ElementTypeImpl對象,getName返回的是一個String。然后我們將這個類

          利用SCA的Annotation定義為一個Remotable:

          package ?org.uxteam.sca.example;

          import
          ?org.example.element.impl.ElementTypeImpl;
          import
          ?org.osoa.sca.annotations.Remotable;

          @Remotable
          public ? interface
          ?MyRemotableService?{
          ????ElementTypeImpl?getElement();
          ????String?getName();
          }



          然后我們創(chuàng)建一個類,讓這個類實現(xiàn)MyRemotableService接口,并且將它定義成一個Service:

          @Service(MyRemotableService. class )
          public ? class ?MyRemotableServiceImpl? implements
          ?MyRemotableService?{

          ????
          /*
          ?(non-Javadoc)
          ?????*?@see?org.uxteam.sca.example.MyRemotableService#getElement()
          ?????
          */

          ????
          public ?ElementTypeImpl?getElement()?{
          ????????ElementTypeImpl?element?
          =
          ?(ElementTypeImpl)?ElementFactory.eINSTANCE.createElementType();
          ????????element.setAge(
          10
          );
          ????????element.setName(
          " Element?Name "
          );
          ????????
          return
          ?element;
          ????}
          ????
          /*
          ?(non-Javadoc)
          ?????*?@see?org.uxteam.sca.example.MyRemotableService#getName()
          ?????
          */

          ????
          public ?String?getName()?{
          ????????
          return ? " This?is?a?remotable?service "
          ;
          ????}
          }



          現(xiàn)在我們完成了遠程服務(wù)的定義了。

          然后我們將RemoteProject中代碼進行打包。先選種src文件夾,然后點右鍵,選擇Export,然后選JarFile,根據(jù)提示即可完成打包。我們將這個命名為Test.jar

          現(xiàn)在打開Tomcat的webapps,會發(fā)現(xiàn)一個名為balto的web項目(UxSCA以后的代號就為balto),

          打開文件夾后會發(fā)現(xiàn)一個名位sca-config.xml文件,打開文件,加入這么一段代碼:

          < property?name? = ? " entries " >
          ????????
          < values >
          ????????????
          < value?type="jar" name = "Test.jar"/?>
          ????????</values>
          </property>


          這段代碼的是讓UxSCA找到我們需要加入到SCA容器管理的包的入口,value的名是包名。

          現(xiàn)在我們通過外部的的應(yīng)用程序去訪問這個服務(wù)。

          首先,我們需要將這個服務(wù)的接口類MyRemotableService以及SDO的數(shù)據(jù)模型打包,也就是說要給訪問端工程數(shù)據(jù)以及服務(wù)的接口(這里我們不要把MyRemotableService的實現(xiàn)類打進去)。當然,可以直接通過訪問web 服務(wù)的方法訪問,這里這么做只是為了測試UxSCA容器定位服務(wù)的功能。

          然后我們再新建一個web項目,TestProject,將剛打好的包放到其中。并在這個項目下創(chuàng)建一個Servlet

          testservlet.JPG


          在doGET中寫如以下代碼:

          ???? protected ? void ?doGet(HttpServletRequest?request,
          ????????????HttpServletResponse?response)?
          throws
          ?ServletException,?IOException?{
          ????????ModuleContext?context?
          =
          ?CurrentModuleContext.getContext();
          ????????MyRemotableService?service?
          =
          ?(MyRemotableService)?context
          ????????????????.locateService(
          " MyRemotableService "
          );

          ????????ElementTypeImpl?obj?
          =
          ?service.getElement();
          ????????String?name?
          =
          ?obj.getName();
          ????????
          ????????System.out.println(name);
          ????????System.out.println(obj.getName());
          ????????System.out.println(obj.getAge());
          ????}


          然后我們在Eclipse的Servers視圖下建立一個server:并把我們剛才新建的TestProject和倒入的balto加入進去:

          servers.JPG



          然后啟動Tomcat,在Console上我們會發(fā)現(xiàn)這么一段話:

          解析Java?Annotation?得到一個Service?-?org.uxteam.sca.example.MyRemotableServiceImpl
          解析Java?Annotation得到一個Service的Java實現(xiàn)?-?Service?:?MyRemotableService?JavaImplemention?:?org.uxteam.sca.example.MyRemotableServiceImpl
          為遠程服務(wù)MyRemotableService創(chuàng)建WSDL文件.
          遠程服務(wù)MyRemotableServiceWSDL文件創(chuàng)建完成
          注冊遠程服務(wù)到Axis?wsdd文件中MyRemotableService


          這就說明我們的服務(wù)已經(jīng)被發(fā)現(xiàn),并且UxSCA已經(jīng)將該服務(wù)發(fā)布成了遠程服務(wù)。

          現(xiàn)在我們在瀏覽器中寫訪問這個服務(wù):

          http://localhost:8080/balto/services/MyRemotableService

          axis.JPG

          如果看到上面的這個界面,就說明MyRemotableService已經(jīng)通過Axis被注冊成為一個Web Service了。

          現(xiàn)在在瀏覽器中輸入:http://localhost:8080/TestProject/TestServlet

          得到以下結(jié)果:

          teset.JPG

          ?

          5??偨Y(jié)

          SCA的遠程服務(wù)是銜接模塊和模塊的重要元素,它使得模塊和模塊之間有了交互。當遠程服務(wù)配合上Scope以及回掉接口(異步時候的接口),將會發(fā)揮巨大的威力。

          在該稿發(fā)布之時,我的UxSCA中遠程服務(wù)部分在處理復雜類型數(shù)據(jù)的時候出現(xiàn)了一些問題,所以目前還只能是定義單個元素的復雜類型(不能使用數(shù)組),并且調(diào)用方法必須是無參數(shù)的。希望不是什么大問題,我會及時改正。


          評論

          # re: SCA程序設(shè)計——遠程服務(wù),以及遠程服務(wù)實現(xiàn)的一些問題和想法  回復  更多評論   

          2006-09-14 18:36 by 冰川
          很好的東西
          謝謝啊。

          # re: SCA程序設(shè)計——遠程服務(wù),以及遠程服務(wù)實現(xiàn)的一些問題和想法  回復  更多評論   

          2007-01-18 19:48 by coolfish
          SCA的遠程服務(wù),類似這樣的服務(wù)應(yīng)該是可以通過ESB這樣的基礎(chǔ)設(shè)施來達到目的的吧
          主站蜘蛛池模板: 定远县| 塔河县| 潞城市| 东方市| 汝阳县| 温泉县| 宜兰市| 洮南市| 沂南县| 桂林市| 阳山县| 蒲城县| 沁水县| 读书| 曲麻莱县| 若羌县| 大方县| 长宁县| 德安县| 苏尼特右旗| 临桂县| 黄山市| 乐都县| 新田县| 景谷| 惠东县| 平乡县| 施秉县| 包头市| 习水县| 长海县| 咸丰县| 屏东县| 寿宁县| 资溪县| 威信县| 左贡县| 台江县| 蒙自县| 射洪县| 石棉县|