【问题标题】:Calling a WCF service from Java从 Java 调用 WCF 服务
【发布时间】:2010-10-19 14:53:26
【问题描述】:

编辑:问题在于ResponseMessage 类中的[MessageHeader] 属性; Metro/JAX-WS 似乎无法处理这些属性。将它们更改为 [MessageBodyMember] 解决了这个问题。


正如标题所说,我需要获取一些 Java 1.5 代码来调用 WCF Web 服务。我已经下载并使用 Metro 生成 Java 代理类,但它们没有生成我所期望的,我相信这是因为 WCF 服务生成的 WSDL。

我的 WCF 类如下所示(为简洁起见,省略了完整代码):

public class TestService : IService
{
  public TestResponse DoTest(TestRequest request)
  {
    TestResponse response = new TestResponse();

    // actual testing code...

    response.Result = ResponseResult.Success;

    return response;
  }
}

public class TestResponse : ResponseMessage
{
  public bool TestSucceeded { get; set; }
}

public class ResponseMessage
{
  [MessageHeader]
  public ResponseResult Result { get; set; }

  [MessageHeader]
  public string ResponseDesc { get; set; }

  [MessageHeader]
  public Guid ErrorIdentifier { get; set; }
}

public enum ResponseResult
{
  Success,
  Error,
  Empty,
}

生成的 WSDL(当我浏览到 http://localhost/TestService?wsdl=wsdl0 时)如下所示:

<xsd:element name="TestResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" name="TestSucceeded" type="xsd:boolean" /> 
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="ErrorIdentifier" type="q1:guid" xmlns:q1="http://schemas.microsoft.com/2003/10/Serialization/" /> 
<xsd:simpleType name="ResponseResult">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Error" /> 
<xsd:enumeration value="Success" /> 
<xsd:enumeration value="EmptyResult" /> 
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="ResponseResult" nillable="true" type="tns:ResponseResult" /> 
<xsd:element name="Result" type="tns:ResponseResult" /> 
<xsd:element name="ResultDesc" nillable="true" type="xsd:string" />

...

<xs:element name="guid" nillable="true" type="tns:guid" /> 
<xs:simpleType name="guid">
<xs:restriction base="xs:string">
<xs:pattern value="[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}" /> 
</xs:restriction>
</xs:simpleType>

我立即发现此 WSDL 存在问题:TestResponse 不包含从 ResponseMessage 继承的属性。由于此服务一直在 Visual Studio 中有效,我以前从未对此提出过质疑,但也许这会导致我的问题?

无论如何,当我在服务上运行 Metro 的 wsimport.bat 时,会生成以下错误消息:

[WARNING] src-resolve.4.2: Error resolving component 'q1:guid'

并且TestResponse 的输出Java 版本缺少ResponseMessage 的任何属性。

我稍微修改了 WSDL 并将 ErrorIdentifier 更改为 xsd:string,这使得有关解析 GUID 类型的消息消失了,但我仍然没有得到任何 ResponseMessage 的属性。

最后,我更改了 WSDL 以将来自 ResponseMessage 的 3 个属性包含在 TestResponse 中,当然最终结果是生成的 .java 文件包含它们。但是,当我实际从 Java 调用 WCF 服务时,这 3 个属性始终是 null

除了自己编写代理类之外有什么建议吗?

【问题讨论】:

  • 你能帮我找到方法、下载和使用 Metro 吗?

标签: c# wcf


【解决方案1】:

一些#%$^@!将ResponseMessage 的属性上的[MessageBodyMember] 属性更改为[MessageHeader],而不告诉任何人。我将它们改回[MessageBodyMember],重新生成代理类,一切正常。

一旦我完成了集成,我将做 CVS 差异来找到负责人,然后他们将遭受我的愤怒。

【讨论】:

  • 很高兴您发现了问题; +1 用于发布它。请更新您的问题以显示真实属性,否则会混淆未来的读者。你也应该接受你自己的答案。
  • 那是没有办法的。如果已经有一个应用了 MessageBodyMember 属性的成员,你会收到一个编译错误。
【解决方案2】:

这个问题与 Java 无关,只与生成的 WSDL 相关。

为什么不在 TestResponse 和 ResponseMessage 类中使用 [DataContract][DataMember]?试试看它是否有效。

【讨论】:

  • 所有必要的属性都存在,但我省略了它们以使我的帖子更短。正如我的回答所示,这可能是个坏主意。
【解决方案3】:

嗯,我的意思并不是要花言巧语或立即拒绝 Java 原生解决方案,但是当谈到 Wcf 堆栈时,最好的建议通常是使用 Wcf 堆栈。

更重要的是:生成一个 CLR Wcf 客户端 [使用选择的语言,通过 VS 或 svcutil 针对静态 wsdl 或服务端点自动生成客户端],然后通过一些 Java-CLR 互操作调用此 CLR 代理。

这有几个原因,并非最不重要的原因

  • 立即合规 [by Wcf for Wcf]
  • 灵活性 [期望您的远程服务更改或利用复杂的通信协议(例如消息级加密)并非不合理,您希望您的客户端像服务一样轻松更改]

ps:我对手动修改现有服务 wsdls 有很大的疑虑。如果 wsdl 确实是“问题”,那么这表明服务定义 [即服务器端代码] 或服务解释 [即自动生成实用程序的选项] 存在问题。避免手动操作服务合同。这样做就像在构建后修改 IL 字节码一样。

【讨论】:

  • 关于编辑 WSDL 以使事情顺利进行,我完全同意您的看法 - 只是我的时间和选项已经不多了,并且愿意尝试任何事情来使事情正常进行。 :)
  • 我不同意我们让 java 调用 wcf 和 wcf 调用 java web 服务,消息安全性和双向 ssl 安全性都非常成功(无需修改 WSDL)。这是针对真正的数百万美元的商业场景。 Metro 是与 WCF 服务互操作的最佳 Java 堆栈。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-20
  • 2010-09-12
  • 1970-01-01
相关资源
最近更新 更多