2012-02-24 35 views
5

Tôi cũng đã đặt câu hỏi này trên Mirth forum.Máy khách Java JAX-WS, khả năng tương thích dịch vụ WCF: "400: Yêu cầu Xấu"

Chúng tôi hiện đang cố gắng kết nối với dịch vụ WCF bằng công cụ tích hợp chăm sóc sức khỏe nguồn mở Mirth. Mirth là dựa trên Java, sử dụng Mule nội bộ sử dụng JAX-WS. Máy chủ WCF trả lại mã trạng thái HTTP "400: Yêu cầu không hợp lệ". Chúng tôi không có quyền truy cập dễ dàng vào máy chủ WCF.

Giao tiếp với khách hàng hoạt động tốt trong C#. Trong Visual Studio, thêm dịch vụ tham khảo, và sau đó trong 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); 

Các WCF client autogenerated (từ WSDL) có app.config với một thiết bị đầu cuối, và điều này ràng buộc:

<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> 

Điều duy nhất được thực hiện khác nhau trong giải pháp WCF là mở rộng maxNameTableCharCount và maxArrayLength trong thẻ readerQuotas cho ràng buộc trong câu hỏi, phần còn lại được để lại với các giá trị mặc định. Tuy nhiên, tôi đã không tìm thấy một cách để thiết lập chúng trong Mirth, nên đây thực sự là lý do cho lỗi.

Chúng tôi đang chạy Mirth v 2.2.1 (lần thanh toán gần đây nhất) và Kênh Mirth được đặt thành cả đọc và gửi tài liệu HL7v3. Vấn đề phát sinh chỉ khi cố gắng giao tiếp với WCF-dịch vụ. Điểm đến là một Người gửi dịch vụ web, với cả dịch vụ và cổng được đọc từ WSDL. Không có authenthication, và phong bì được tạo ra từ các hoạt động chỉ có sẵn. Chúng tôi không sử dụng MTOM.

Chúng tôi khá chắc chắn rằng điều này liên quan đến khả năng tương tác JAX-WS và WCF. Bất kỳ gợi ý chung nào?

Chúng tôi đã thử đặt thuộc tính trên kết nối JAX-WS. Sâu trong lòng reo vui, chúng tôi đã cố gắng thiết lập kích thước http đoạn:. dispatch.getRequestContext() đặt (JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE, 8192) (WebServiceMessageDispatcher.Java dòng 140)

Các vết đống là như sau:

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) 
+0

Có không có cách nào bạn có thể nhận được một bản sao của cấu hình của dịch vụ? –

+0

Một ý nghĩ khác là loại bỏ tất cả các bit cấu hình không cần thiết và chỉ cần cấu hình những thứ bạn BIẾT mà bạn cần. Các tệp cấu hình được tạo tự động không cần thiết. Có lẽ sẽ không giải quyết vấn đề, nhưng có thể giúp đỡ anyway. –

Trả lời

3

Chúng tôi tìm thấy giải pháp. Mô tả dài về giải pháp trên the Mirth forum.

Vấn đề là các dịch vụ web đã cho chúng tôi một "400: yêu cầu xấu" khi chúng tôi cố gắng gửi yêu cầu mà chúng tôi nghĩ là có ý nghĩa. "400 yêu cầu xấu" là một lỗi rất chung chung và không mang tính thông tin.

Một giải pháp để thử nghiệm

Giải pháp này tạo ra một tập tin dựa trên thử nghiệm khai thác debuggable mà bạn có thể sử dụng để hiểu những gì Mirth làm. Nó không phải là một giải pháp chất lượng sản xuất. YMMV.

  • Install Mirth
  • Tải về các tập tin WSDL của dịch vụ web (ví dụ EncounterManager) và đặt chúng dưới Mirth Server \ public_html \ EncounterManager để Mirth có thể lưu trữ chúng.
  • Trong tập tin WSDL địa phương trên, sửa đổi nó và chắc chắn rằng các hành động SOAP tại các điểm chấm dứt các dịch vụ web thực tế:

xà phòng: Địa chỉ vị trí = "http: // của bạn -server/HL7Connector/GetDemographicsService30/"/

  • Restart Mirth nếu nó đã được bắt đầu.
  • Trong Mirth Connect, tạo ra một kênh mới, ví dụ Sender
  • Chỉ cần để thử nghiệm, làm cho Nguồn của kênh này một trình đọc file mà đọc cái gì đó trong (ví dụ như một định danh bệnh nhân từ một tập tin văn bản ). Ví dụ: đặt cuộc thăm dò ý kiến ​​C: \ MirthTesting \ unread. Yêu cầu Mirth di chuyển tệp sau khi hoàn tất thành C: \ MirthTesting \ read
  • Trên trang tóm tắt của biến mới, nhấp "Đặt loại dữ liệu".
  • loại Set dữ liệu để kết nối Nguồn inbound = Delimited văn bản, đầu nối nguồn ngoài = HL7, Destination 1 outbound = Delimited văn bản. Đây chỉ là để thử nghiệm, bạn có thể làm công cụ HL7 lạ mắt sau này.
  • Trong nguồn, nhấp vào Chỉnh sửa biến áp.
  • Nhấp vào "Thêm bước mới", nhập tên biến mới "patientIdWanted" và nhập cho ánh xạ "messageObject.getRawData()". Điều này làm cho Mirth đọc nội dung của bất kỳ tệp văn bản nào bạn đưa vào thư mục "Chưa đọc" và đưa vào biến mà bạn có thể sử dụng sau này (vào bản đồ kênh)
  • Làm cho Đích của kênh mới của bạn thành Web người gửi dịch vụ. Nhập URL của WSDL cục bộ (ví dụ: http: // localhost: 8080/EncounterManager/EncounterManagerQueryFulfiller.wsdl)
  • Nhấp vào Nhận hoạt động, sau đó Tạo phong bì.
  • Phong bì SOAP là rất lớn và đầy đủ của HL7 không có ý nghĩa (đối với tôi). Thay thế nó bằng một ví dụ đơn giản hoạt động, và loại bỏ tất cả các HL7 cruft không cần thiết. Nhà cung cấp của bạn nên cung cấp cho bạn một ví dụ làm việc.
  • Bây giờ bạn cần phải đặt các biến bạn đã đọc từ bước trình đọc tệp, vào phong bì SOAP. Phong bì SOAP của bạn phải chứa "tải trọng", ví dụ: định danh bệnh nhân ở đâu đó. Đối với truy vấn GetDemographics, nó trông như thế này (một phần của nó). Lưu ý rằng $ {patientIdWanted} là nơi Mirth thay thế giá trị trong mẫu, từ bất kỳ thứ gì chúng tôi đưa vào bản đồ kênh từ tệp văn bản ở trên.
  • Bây giờ hãy lưu kênh này.
  • Tạo kênh mới để nhận dịch vụ web nào trong bước trước đã gửi cho bạn. Gọi điện cho số này là Bộ thu
  • Trong kênh mới, đặt tất cả các loại dữ liệu thành "Văn bản phân tách". Một lần nữa, chỉ để thử nghiệm.
  • Đặt nguồn của kênh "Người nhận" thành "Trình đọc kênh"
  • Đặt đích của kênh mới thành Trình ghi tệp. Nhập một thư mục và tên tệp, ví dụ: C: \ MirthTesting \ read \ webservice-response.txt. Trong mẫu, nhập $ {message.rawData} để xem mọi thứ mà Mirth có.
  • Quay lại kênh Tên người gửi, chọn điểm đến, nhập kênh Bộ thu làm điểm đến của phản hồi.
  • Lưu thay đổi, xác thực trình kết nối, triển khai lại tất cả các kênh.
  • Bây giờ tạo một file văn bản với một nhận dạng bệnh nhân trong nó, và đặt nó vào C: \ MirthTesting \ chưa đọc
  • Mirth sẽ đọc tập tin này (sau đó di chuyển nó đến "đọc" thư mục). Kênh đầu tiên của bạn sẽ nhận tệp văn bản, di chuyển nội dung vào bản đồ kênh $ {patientIdWanted}. Sau đó, dịch vụ web của bạn sẽ nhận được phong bì SOAP với mã nhận dạng bệnh nhân này. Phản hồi sẽ được gửi đến kênh thu và được bán dưới dạng văn bản thuần túy.

Stuff đó là hữu ích

  • Nhận thấy Mirth là một tàu ngầm hạt nhân: mạnh mẽ và bí ẩn. Không có hướng dẫn sử dụng!
  • Là hơi thành thạo trong C# và Java
  • Có ví dụ về thông điệp HL7 có ý nghĩa
  • Sử dụng Visual Studio để tạo ra một tinh khiết C# khách hàng để xác minh rằng chúng ta có thể đọc từ dịch vụ web với đồng bằng C#. (Chúng tôi đã sử dụng Mirth để lưu trữ các tệp WSDL, nhưng bạn có thể sử dụng IIS)
  • Sử dụng Eclipse để tạo một máy khách Java để xác minh rằng chúng ta có thể đọc từ dịch vụ web với Java. Chúng tôi đã sử dụng SOAPUI (giống như Mirth sử dụng) với phiên bản Eclipse Indigo EE (từ dòng lệnh sử dụng wsimport.bat)
  • Tải xuống Mirth từ nguồn và chạy nó từ Eclipse.
  • Bật tính năng bán phá giá HTTP (trong Eclipse). Nhập vào "Chạy cấu hình", đối số VM. Điều này cho phép bạn thấy chính xác những gì Mirth (hoặc máy khách Java của bạn) gửi đến dịch vụ web: -Dcom.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump = true

  • Thêm tiền Xử lý kịch bản kênh gửi của bạn để xem những gì Mirth thực hiện:

    FileUtil.write('C:/MirthTesting/read/sender_preprocessmessage_in.txt', false, message);return message; 
    
  • Thêm một kịch bản sau khi xử lý kênh gửi của bạn để xem những gì Mirth làm:

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

Một thay đổi mã số

Để thực sự thực hiện công việc này, chúng tôi phải thực hiện một thay đổi đối với mã nguồn Mirth. Với JDK1.7 mà chúng ta đã sử dụng, Mirth không thực sự gửi hành động SOAP. Trong Máy chủ/.../ WebServiceMessageDispatcher.Java dòng 137, chúng tôi đã thêm:

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

(lấy từ this blog post)

Các vấn đề liên quan