2013-03-01 46 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