【问题标题】:JAX-WS Java client, WCF service interoperability: "400: Bad Request"JAX-WS Java 客户端、WCF 服务互操作性:“400:错误请求”
【发布时间】:2012-03-15 00:41:15
【问题描述】:

我也在Mirth forum上问过这个问题。

我们目前正在尝试使用开源医疗保健集成引擎 Mirth 连接到 WCF 服务。 Mirth 是基于 Java 的,内部使用使用 JAX-WS 的 Mule。 WCF 服务器正在返回 HTTP 状态代码“400:错误请求”。我们无法轻松访问 WCF 服务器。

与客户端的通信在 C# 中运行良好。在 Visual Studio 中,添加服务引用,然后在 main() 中:

PatientRegistryQueryFulfiller.GetDemographicsClient svc = new PatientRegistryQueryFulfiller.GetDemographicsClient();
doc.Load(@"C:\MirthTesting\PRPA_EX201307NO_10_PatientReg_GetDemographics.xml");
PatientRegistryQueryFulfiller.PRPA_IN201307NO patientRegistryRequest = (PatientRegistryQueryFulfiller.PRPA_IN201307NO)ObjectSerializer.DeserializeObject(doc, typeof(PatientRegistryQueryFulfiller.PRPA_IN201307NO));
PatientRegistryQueryFulfiller.PRPA_IN201307NOResponse patientRegistryResponse = svc.GetDemographics(patientRegistryRequest);
doc = ObjectSerializer.SerializeObject(patientRegistryResponse.Item);

自动生成的 WCF 客户端(来自 WSDL)有一个带有端点的 app.config,以及这个绑定:

<bindings>
    <basicHttpBinding>
        <binding name="PatientRegistryQueryFulfiller_Binding" closeTimeout="00:01:00"
         openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
         allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
         maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
         messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
         useDefaultWebProxy="true">
        <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="655360"
           maxBytesPerRead="4096" maxNameTableCharCount="655360" />
        <security mode="None">
        <transport clientCredentialType="None" proxyCredentialType="None"
             realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
    </binding>
  </basicHttpBinding>
</bindings>

WCF 解决方案中唯一不同的做法是在 readerQuotas 标记中为相关绑定扩展 maxNameTableCharCount 和 maxArrayLength,其余部分保留默认值。但是,如果这确实是错误的原因,我还没有找到在 Mirth 中设置这些的方法。

我们正在运行 Mirth v 2.2.1(最近结帐),并且 Mirth 频道设置为读取和发送 HL7v3 文档。只有在尝试与 WCF 服务通信时才会出现问题。目标是一个 Web 服务发送者,服务和端口都从 WSDL 中读取。没有身份验证,并且信封是从唯一可用的操作中生成的。我们没有使用 MTOM。

我们相当肯定这与 JAX-WS 和 WCF 互操作性有关。任何一般性提示?

我们已经尝试在 JAX-WS 连接上设置属性。在欢乐的内心深处,我们尝试设置 http 块大小: dispatch.getRequestContext().put(JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE, 8192)(WebServiceMessageDispatcher.Java 第 140 行)

堆栈跟踪如下:

ERROR-410: Web Service Connector error
ERROR MESSAGE: Error connecting to web service.
com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 400: Bad Request
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.checkStatusCode(Unknown Source)
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.process(Unknown Source)
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.processRequest(Unknown Source)
at com.sun.xml.internal.ws.transport.DeferredTransportPipe.processRequest(Unknown Source)
at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Unknown Source)
at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Unknown Source)
at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Unknown Source)
at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Unknown Source)
at com.sun.xml.internal.ws.client.Stub.process(Unknown Source)
at com.sun.xml.internal.ws.client.dispatch.DispatchImpl.doInvoke(Unknown Source)
at com.sun.xml.internal.ws.client.dispatch.DispatchImpl.invoke(Unknown Source)
at com.mirth.connect.connectors.ws.WebServiceMessageDispatcher.processMessage(WebServiceMessageDispatcher.java:176)
at com.mirth.connect.connectors.ws.WebServiceMessageDispatcher.doDispatch(WebServiceMessageDispatcher.java:106)
at com.mirth.connect.connectors.ws.WebServiceMessageDispatcher.doSend(WebServiceMessageDispatcher.java:204)
at org.mule.providers.AbstractMessageDispatcher.send(AbstractMessageDispatcher.java:164)
at org.mule.impl.MuleSession.sendEvent(MuleSession.java:191)
at org.mule.impl.MuleSession.sendEvent(MuleSession.java:130)
at org.mule.routing.outbound.AbstractOutboundRouter.send(AbstractOutboundRouter.java:85)
at org.mule.routing.outbound.FilteringMulticastingRouter.route(FilteringMulticastingRouter.java:54)
at org.mule.routing.outbound.OutboundMessageRouter$1.doInTransaction(OutboundMessageRouter.java:78)
at org.mule.transaction.TransactionTemplate.execute(TransactionTemplate.java:48)
at org.mule.routing.outbound.OutboundMessageRouter.route(OutboundMessageRouter.java:82)
at org.mule.impl.model.DefaultMuleProxy.onCall(DefaultMuleProxy.java:247)
at org.mule.impl.model.seda.SedaComponent.doSend(SedaComponent.java:209)
at org.mule.impl.model.AbstractComponent.sendEvent(AbstractComponent.java:277)
at org.mule.impl.MuleSession.sendEvent(MuleSession.java:201)
at org.mule.routing.inbound.InboundMessageRouter.send(InboundMessageRouter.java:176)
at org.mule.routing.inbound.InboundMessageRouter.route(InboundMessageRouter.java:143)
at org.mule.providers.AbstractMessageReceiver$DefaultInternalMessageListener.onMessage(AbstractMessageReceiver.java:487)
at org.mule.providers.AbstractMessageReceiver.routeMessage(AbstractMessageReceiver.java:266)
at org.mule.providers.AbstractMessageReceiver.routeMessage(AbstractMessageReceiver.java:225)
at com.mirth.connect.connectors.vm.VMMessageReceiver.getMessages(VMMessageReceiver.java:223)
at org.mule.providers.TransactedPollingMessageReceiver.poll(TransactedPollingMessageReceiver.java:108)
at org.mule.providers.PollingMessageReceiver.run(PollingMessageReceiver.java:97)
at org.mule.impl.work.WorkerContext.run(WorkerContext.java:290)
at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1061)
at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:575)
at java.lang.Thread.run(Unknown Source)

【问题讨论】:

  • 有没有办法获取服务配置的副本?
  • 另一个想法是去掉所有不需要的配置位,只配置你知道你需要的东西。自动生成的配置文件不必要地冗长。可能无法解决问题,但无论如何可能会有所帮助。

标签: wcf jax-ws mule mirth


【解决方案1】:

我们找到了解决方案。 the Mirth forum上的解决方案的详细描述。

问题在于,当我们尝试向它发送一个我们认为有意义的请求时,Web 服务给了我们一个“400:错误请求”。 “400 bad request”是一个非常通用且信息量不大的错误。

测试解决方案

此解决方案创建了一个可调试的基于文件的测试工具,您可以使用它来了解 Mirth 的功能。它不是一个生产质量的解决方案。 YMMV。

  • 安装 Mirth
  • 下载 Web 服务的 WSDL 文件(例如 EncounterManager) 并将它们放在 Mirth 下 Server\public_html\EncounterManager 以便 Mirth 可以托管它们。
  • 在上面的本地 WSDL 文件中,修改它并确保 端点处的 SOAP 操作指向实际的 Web 服务:

肥皂:地址 location="http://your-server/HL7Connector/GetDemographicsService30/"/

  • 如果 Mirth 已经启动,请重新启动它。
  • 在 Mirth Connect 中,创建一个新频道,例如 Sender
  • 只是为了测试,将此频道的Source设为文件阅读器 读取某些内容(例如,来自文本的患者标识符 文件)。例如,让它轮询 C:\MirthTesting\unread。讲笑话 完成后将文件移动到 C:\MirthTesting\read
  • 在新转换器的摘要页面上,单击“设置数据类型”。
  • 将数据类型设置为 Source connector inbound = Delimited text、Source connector outbound=HL7、Destination 1 outbound = Delimited text。这只是为了测试,你以后可以做一些花哨的 HL7 的东西。
  • 在源中,单击编辑转换器
  • 单击“添加新步骤”,输入新变量名称“patientIdWanted”并为映射输入“messageObject.getRawData()”。这使 Mirth 读取您放入“未读”目录的任何文本文件的内容,并将其放入您以后可以使用的变量中(放入频道映射中)
  • 将您的新频道的目的地设置为Web 服务发送者。输入本地 WSDL 的 URL(例如 http://localhost:8080/EncounterManager/EncounterManagerQueryFulfiller.wsdl
  • 点击获取操作,然后点击生成信封。
  • SOAP 信封非常大,充满了 HL7 废话(对我来说)。用一个有效的简单示例替换它,并删除所有不必要的 HL7 垃圾。您的提供商应该为您提供一个可行的示例。
  • 您现在需要将您从文件读取器步骤中读取的变量放入 SOAP 信封中。您的 SOAP 信封应包含“有效负载”,例如某处的患者标识符。对于 GetDemographics 查询,它看起来像这样(部分)。请注意,${patientIdWanted} 是 Mirth 替换模板中的值的地方,来自我们从上面的文本文件中放入通道映射的任何内容。
  • 现在保存此频道。
  • 创建一个新频道以接收上一步中的 Web 服务发送给您的内容。称它为接收者
  • 在新通道中,将数据类型全部设置为“分隔文本”。同样,仅用于测试。
  • 将“Receiver”频道的来源设置为“Channel reader”
  • 将新通道的目标设置为文件写入器。输入目录和文件名,例如C:\MirthTesting\read\webservice-response.txt。在模板中,输入 ${message.rawData} 以查看 Mirth 拥有的所有内容。
  • 回到Sender通道,选择目的地,进入Receiver通道作为响应的目的地。
  • 保存更改、验证连接器、重新部署所有渠道。
  • 现在创建一个包含患者标识符的文本文件,并将其放入 C:\MirthTesting\unread
  • Mirth 将读取此文件(然后将其移至“读取”目录)。您的第一个频道将获取文本文件,将内容移动到频道地图 ${patientIdWanted}。然后,您的 Web 服务将获取包含该患者标识符的 SOAP 信封。响应将被发送到 Receiver 通道,并以纯文本形式转储。

有用的东西

  • 意识到 Mirth 是一艘核潜艇:强大而神秘。没有手册!
  • 一定程度上精通 C# 和 Java
  • 提供有意义的 HL7 消息示例
  • 使用 Visual Studio 生成纯 C# 客户端,以验证我们是否可以使用纯 C# 从 Web 服务读取。 (我们使用 Mirth 来托管 WSDL 文件,但您可以使用 IIS)
  • 使用 Eclipse 生成 Java 客户端,以验证我们是否可以使用 Java 从 Web 服务中读取数据。我们使用 SOAPUI(与 Mirth 使用的相同)和 Eclipse Indigo EE 版本(从命令行使用 wsimport.bat)
  • 从源代码下载 Mirth 并从 Eclipse 运行它。
  • 开启 HTTP 转储(在 Eclipse 中)。在“运行配置”下输入 VM 参数。这让您可以准确地看到 Mirth(或您的 Java 客户端)发送到 Web 服务的内容: -Dcom.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true

  • 将预处理脚本添加到您的发送者通道以查看 Mirth 实际执行的操作:

    FileUtil.write('C:/MirthTesting/read/sender_preprocessmessage_in.txt', false, message);return message;
    
  • 将后处理脚本添加到您的发送者频道以查看 Mirth 的作用:

    FileUtil.write('C:/MirthTesting/read/dipssender_postprocessmessage.txt', false, message);
    return;
    

一次代码更改

要真正完成这项工作,我们必须对 Mirth 源代码进行一次更改。在我们使用的 JDK1.7 中,Mirth 实际上并没有发送 SOAP 操作。在 Server/.../WebServiceMessageDispatcher.Java 第 137 行,我们必须添加:

    dispatch.getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, true);

(取自this blog post

【讨论】:

    猜你喜欢
    • 2011-05-05
    • 1970-01-01
    • 1970-01-01
    • 2015-04-03
    • 2012-04-27
    • 2015-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多