2013-03-01 43 views
1

我使用Web服務API,可以通過一般類型的Result來抽取所有提供某些基本信息,最顯着的是唯一的ID。這個唯一的ID往往是 - 但並非必須是 - 由發件人定義的UUID,並不總是同一個人(但ID在整個系統中是唯一的)。Web服務投稿ID消歧

從根本上說,在沿此線的東西API結果(Java編寫的,但語言應該是無關的),其中只有基本接口代表共同細節:

interface Result 
{ 
    String getId(); 
} 

class Result1 implements Result 
{ 
    public String getId() { return uniqueValueForInstance; } 
    public OtherType1 getField1() { /* ... */ } 
    public OtherType2 getField2() { /* ... */ } 
} 

class Result2 implements Result 
{ 
    public String getId() { return uniqueValueForInstance; } 
    public OtherType3 getField3() { /* ... */ } 
} 

重要的是要注意,每個Result類型可能代表一種完全不同的信息。一些它不能與其他Result s內相關,並且它的一些可以,無論它們是否具有相同的類型(例如,Result1可以是能夠與Result2相關,並且因此反之亦然,但一些ResultX可能存在不能相關因爲它代表不同的信息)。

我們目前正在執行接收一些那些Result S和在可能關聯他們的系統中,其產生不同Result對象是什麼相關在一起的容器:

class ContainerResult implements Result 
{ 
    public String getId() { return uniqueValueForInstance; } 
    public Collection<Result> getResults() { return containedResultsList; } 
    public OtherType4 getField4() { /* ... */ } 
} 

class IdContainerResult implements Result 
{ 
    public String getId() { return uniqueValueForInstance; } 
    public Collection<String> getIds() { return containedIdsList; } 
    public OtherType4 getField4() { /* ... */ } 
} 

這些是兩個容器,其中呈現不同的用例。首先,ContainerResult允許某人接收相關詳細信息以及實際完整的相關數據。第二個,IdContainerResult,僅通過發送關聯的ID來犧牲完整的列表,以支持帶寬。在做相關的系統不一定是一樣的客戶端,客戶端可以接收Result s表示這些ID將代表,其目的是讓他們通過簡單地接收的ID,以顯示他們的系統相關性。現在

,我的問題可能是無明顯一些,這可能是顯而易見別人:如果我只發送ID爲IdContainerResult的一部分,那麼客戶機如何知道如何在他們的最終匹配Result如果他們沒有一個單一的ID店?實際上是由每個Result實現所表示的數據的類型借給自己時它們不能被相關,這意味着單個ID店不太可能在大多數情況下,不強制存儲器或存儲負擔被分離。

目前的解決方案,我們已經來到了限嗣繼承創建一個新的ID類型的,我們把它叫做TypedId,它結合了來自各ResultResult的ID XML命名空間和XML名稱。

該解決方案的主要問題是它需要維護一個可變類型的集合,這些類型在發現它們時會進行更新,或者是所有類型的先前知識,以便可以在任何客戶端系統上正確關聯該ID。不幸的是,我不能拿出一個更好的解決方案,但目前的解決方案覺得不妥。

有沒有人遇到類似的情況,他們希望將通用Result與原始類型關聯起來,特別是考慮到WSDL的侷限性,並以更清晰的方式解決它?

回答

1

這裏是我的建議:

  1. 你想擁有「客戶知道如何將結果他們最終匹配」。因此,在您的響應中包含一個名爲「RequestType」的字符串的額外鑑別器字段。

  2. 你想避免「維護一個可變的類型集合,因爲它們被發現或更新所有類型的先前知識,這樣就可以在任何客戶端系統上正確地關聯ID」。顯然,每個客戶端請求調用都知道結果將涉及哪些處理區域。因此,您可以讓客戶端傳遞「RequestType」字符串作爲請求的一部分。只要RequestType是每種不同類型客戶端請求的唯一字符串,您的服務就可以處理並關聯它,而無需對任何知識進行硬編碼。

  3. 這裏的Java類的用於請求和響應消息的一個可能的實施例(即,不是實際的服務端點):

    interface Request { 
        String getId(); 
        String getRequestType(); 
        // anything else ... 
    } 
    
    interface Result { 
        String getId(); 
        String getRequestType(); 
    } 
    
    class Result1 implements Result { 
        public String getId() { return uniqueValueForInstance; } 
        public OtherType1 getField1() { /* ... */ } 
        public OtherType2 getField2() { /* ... */ } 
    } 
    
    class Result2 implements Result { 
        public String getId() { return uniqueValueForInstance; } 
        public OtherType3 getField3() { /* ... */ } 
    } 
    
  4. 這裏的疑難雜症。 (2)和(3)不能給出完全動態的解決方案。您希望您的服務能夠返回與每個不同請求有關的靈活的記錄結構。您有以下選擇:

    4A)在XSD中,將結果聲明爲單一的強類型變體記錄類型,並且在WSDL中返回來自單個服務端點和單個操作的結果。在聲明變體記錄結構時,XSD仍然需要對鑑別器元素的值進行硬編碼。在XSD中,爲每個可能的客戶端請求聲明多個強類型唯一類型Result1,Result2等。在WSDL中,有多個唯一命名的操作來返回其中的每一個。這些操作可以跨越一個或多個服務端點 - 甚至跨越多個WSDL。雖然這避免了將請求類型硬編碼爲特定字段本身,但它實際上並不是通用的客戶端獨立解決方案,因爲您仍然明確地硬編碼以通過爲每個結果類型創建唯一名稱來區分每個請求類型,並且每個操作。所以任何明顯的活力都是海市蜃樓。 4C)在XSD中,定義一個靈活的通用數據結構,它不是變體,但有大量通常命名的字段,能夠處理所有可能的結果。示例字段可以是「字符串字段1」,「字符串字段2」,「整數字段1」,「日期字段1058」等,即使用非常弱的打字並將負擔放在客戶端上以神奇地知道每個字段中的數據。這個選項可能是非常通用的,但通常被認爲是可怕的做法。它不雅,不可讀,容易出錯,並且有無限的限制/假設 - 你怎麼知道你有足夠的通用字段?就你而言,(4A)可能是最好的選擇。

    4D)使用靈活的XSD架構設計策略 - 類型可替換性和使用「any」元素。見http://www.xfront.com/ExtensibleContentModels.html

    4E)針對您自己的工廠類方法使用@Produces @SomeQualifier註釋,該方法創建高級類型。這告訴CDI總是使用這個方法來構造指定bean類型&修飾符。您的工廠方法可以具有花哨的邏輯來決定每次調用時要構建哪個特定的低級類型。 @SomeQualifier可以有其他參數來指導選擇類型。這可能會將限定符的數量減少到一個。

    如果您使用(4D),您將擁有一個靈活的服務端點設計,可以非常有效地處理不斷變化的需求。但是你的服務實現仍然需要實現靈活的行爲來決定爲每個請求返回哪些結果字段。事實是,如果你對變化的數據結構有合理的要求,你的代碼必須知道如何爲每個單獨的請求處理這些數據結構,因此必須依賴某種形式的RequestType /唯一操作名稱來區分。任何完全動態處理的目標(不適應每個客戶對結果數據的需求)都是雄心勃勃的。

+0

我認爲4D代表,我想代替要求每個人對於延長'Result',作爲當前架構劑量的答案,但架構的一部分已經鐵定多年。相關的ID表示一種新的「結果」類型。不幸的是,這聽起來像我無法避免匹配類型和ID的情況,並強迫所有類型的知識傳遞給客戶端。但是,正如您在答案結論中適當指出的那樣,代碼必須知道如何處理數據,無論如何。我認爲這只是野獸的本質。非常完整的答案。 – pickypg 2013-03-15 20:03:06