No announcement yet.

Mirth and WCF: "400: Bad Request"

  • Filter
  • Time
  • Show
Clear All
new posts

  • Mirth and WCF: "400: Bad Request"

    I have also asked this question on StackOverflow.

    We are currently trying to connect to a WCF service using the open source health care integration engine Mirth . Mirth is Java-based, uses Mule internally which uses JAX-WS. The WCF server is returning HTTP status code "400: Bad Request". We don’t have easy access to the WCF server.

    Communication with the client works well in C#. In Visual Studio, add Service Reference, and then in main():
    PatientRegistryQueryFulfiller.GetDemographicsClient svc = new PatientRegistryQueryFulfiller.GetDemographicsClient();
    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);
    The autogenerated WCF client (from the WSDL) has an app.config with an endpoint, and this binding:
            <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"
                 <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" />
    The only thing done differently in the WCF-solution is extending the maxNameTableCharCount and maxArrayLength in the readerQuotas tag for the binding in question, the rest is left with default values. However, I have not found a way to set these in Mirth, should this indeed be the reason for the error.

    We’re running Mirth v 2.2.1 (most recent checkout), and the Mirth Channel is set to both read and send a HL7v3 document. The problem arises only when trying to communicate with the WCF-service. The destination is a Web Service Sender, with both service and port read from the WSDL. There is no authenthication, and the envelope is generated from the only available operation. We’re not using MTOM.

    We’re fairly certain that this is related to JAX-WS and WCF interoperability. Any general hints?

    We’ve tried setting properties on JAX-WS connection. Deep in the bowels of mirth, We’ve tried setting the http chunk size:
    dispatch.getRequestContext().put(JAXWSProperties.H TTP_CLIENT_STREAMING_CHUNK_SIZE, 8192) (WebServiceMessageDispatcher.Java line 140)

    The stack trace is as follows:
    ERROR-410: Web Service Connector error
    ERROR MESSAGE: Error connecting to web service.
    Code: The server sent HTTP status code 400: Bad Request
    at Source)
    at Source)
    at Source)
    at Source)
    at Source)
    at Source)
    at Source)
    at Source)
    at Source)
    at Source)
    at Source)
    at org.mule.providers.AbstractMessageDispatcher.send(
    at org.mule.impl.MuleSession.sendEvent(
    at org.mule.impl.MuleSession.sendEvent(
    at org.mule.routing.outbound.AbstractOutboundRouter.send(
    at org.mule.routing.outbound.FilteringMulticastingRouter.route(
    at org.mule.routing.outbound.OutboundMessageRouter$1.doInTransaction(
    at org.mule.transaction.TransactionTemplate.execute(
    at org.mule.routing.outbound.OutboundMessageRouter.route(
    at org.mule.impl.model.DefaultMuleProxy.onCall(
    at org.mule.impl.model.seda.SedaComponent.doSend(
    at org.mule.impl.model.AbstractComponent.sendEvent(
    at org.mule.impl.MuleSession.sendEvent(
    at org.mule.routing.inbound.InboundMessageRouter.send(
    at org.mule.routing.inbound.InboundMessageRouter.route(
    at org.mule.providers.AbstractMessageReceiver$DefaultInternalMessageListener.onMessage(
    at org.mule.providers.AbstractMessageReceiver.routeMessage(
    at org.mule.providers.AbstractMessageReceiver.routeMessage(
    at com.mirth.connect.connectors.vm.VMMessageReceiver.getMessages(
    at org.mule.providers.TransactedPollingMessageReceiver.poll(
    at Source)
    Last edited by haasj; 02-24-2012, 06:02 AM.

  • #2
    Stand-alone Java client works

    I'm from the same team, and I've done some digging that sheds a little light.

    Generating a stand-alone Java client (with SoapUI) that communicates with the Norwegian HL7 server works well. It is identical to a WCF client, and the responses are identical. This tells me that the problem is not Java per se, but something in the way Mirth reads the WSDL file and sets up the web service. I'm hoping the working Java client described below can be helpful to someone. Mirth uses an embedded SoapUI to read WSDL, so a solution is getting closer but we need more input from Mirth regulars. Mirth calls SoapUI in Server/src/, here:

    private WsdlInterface getWsdlInterface(URI wsdlUrl, String username, String password) throws Exception {
            /* add the username:password to the URL if using authentication */
            if (StringUtils.isNotEmpty(username) && StringUtils.isNotEmpty(password)) {
                String hostWithCredentials = username + ":" + password + "@" + wsdlUrl.getHost();
                wsdlUrl = new URI(wsdlUrl.getScheme(), hostWithCredentials, wsdlUrl.getPath(), wsdlUrl.getQuery(), wsdlUrl.getFragment());
            SoapUI.setSoapUICore(new EmbeddedSoapUICore());
            WsdlProject wsdlProject = new WsdlProjectFactory().createNew();
            WsdlLoader wsdlLoader = new UrlWsdlLoader(wsdlUrl.toURL().toString());
            try {
                Future<WsdlInterface> future = importWsdlInterface(wsdlProject, wsdlUrl, wsdlLoader);
                return future.get(30, TimeUnit.SECONDS);
            } catch (Exception e) {
                throw e;
        private Future<WsdlInterface> importWsdlInterface(final WsdlProject wsdlProject, final URI newWsdlUrl, final WsdlLoader wsdlLoader) {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            return executor.submit(new Callable<WsdlInterface>() {
                public WsdlInterface call() throws Exception {
                    WsdlInterface[] wsdlInterfaces = WsdlInterfaceFactory.importWsdl(wsdlProject, newWsdlUrl.toURL().toString(), true, wsdlLoader);
                    return wsdlInterfaces[0];
    The Java client was generated from the online WSDL, using Eclipse (Indigo), Java EE Edition, with the SoapUI plugin and Glassfish. It's quite simple:
    1. Create new project, regular Java application
    2. Right-click on project root, select Soap-UI, "Add SoapUI nature"
    3. Right-click on "SoapUI Web services", select Soap-UI, "Add WSDL"
    4. Enter the URL of the WSDL and let it work
    5. You can now generate the code from the WSDL. However, the JAX-WS tool that does this removes underscores by default and this messes up serialization and deserialization. Therefore, create a bindings.xml file somewhere with this content:
      <?xml version='1.0' encoding='UTF-8'?>
          <jaxb:globalBindings underscoreBinding="asCharInWord"/>
    6. In the project root, expand "SoapUI Web Services" and right-click the generated binding - in our case, "BasicHttpBinding_ITwoWayAsync" and select "Generate code"/"JAX-WS artifacts".
    7. In the ensuing dialog, specify a package (wcftester), a source directory (src).
    8. Then click on tools and enter the path to the wsimport binary
      . Then click on generate.
    9. In my case, Eclipse hung on this GUI-driven generate so I just ran wsimport from the command line:
      wsimport.bat -d C:\HL7\JavaClientToWcfService\WcfTester\bin -p wcftester -s C:\HL7\JavaClientToWcfService\WcfTester\src -keep -verbose http://serverurl:81/GetDemographics/GetDemographics.svc?wsdl -b C:\HL7\JavaClientToWcfService\bindingFile.xml

    In Visual Studio, things are a lot simpler:
    1. Create a new project of type console application
    2. Right-click on project, "Add Service Reference"
    3. Enter the URL of the WSDL and click OK.

    Using these two approaches, I've coded line-by-line identical Java and WCF clients that send an example HL7 message from disk to the GetDemographics WCF-based service. The example file is taken from the Norwegian HL7 consortium help site at and is known to work.

    The clients load the example XML file, deserialize them to the correct Java/C# request class, calls the web service and retrieves the response. The response is then serialized to XML and stored to disk. With a diff tool, I've confirmed that the responses are identical.

    Stand-alone Java web service client that reads from Norwegian HL7 WCF web service using JAX-WS-generated code:
    package wcfTesterMain;
    import javax.xml.bind.*;
    import wcftester.*;
    public class WcfTester {
    	public static void main(String[] args) throws JAXBException {
    	File inputFile = new File("C:/HL7/MirthTesting/read/PRPA_EX201307NO_10_PatientReg_GetDemographics.xml");			
    	JAXBContext context = JAXBContext.newInstance(PRPA_IN201307NO.class);             
    	Unmarshaller unmarshaller = context.createUnmarshaller();             
    	PRPA_IN201307NO  patientRegistryRequest = (PRPA_IN201307NO) unmarshaller.unmarshal(inputFile);									
    	System.out.println("SUCCESS: XML payload read from: " + inputFile.getAbsolutePath());
    	BizTalkServiceInstance svc  = svc = new BizTalkServiceInstance();							
    	System.out.println("SUCCESS: Created web service client instance.");
    	AddGetDemographics proxy = proxy = svc.getBasicHttpBindingITwoWayAsync();		
    	System.out.println("SUCCESS: Got http binding proxy.");
    	PRPA_IN201307NOResponse response = response = proxy.getDemographics(patientRegistryRequest);		
    	System.out.println("SUCCESS: Called getDemographics on service.");
    	File outputFile = new File("C:/HL7/MirthTesting/response/response_GetDemographics_using_JavaClient.xml");
    	JAXBContext context2 = JAXBContext.newInstance(PRPA_IN201307NOResponse.class);             
    	Marshaller marshaller = context2.createMarshaller();
    	marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, new Boolean(true));
    	marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-16");
    	marshaller.marshal(response, outputFile);            
    	System.out.println("SUCCESS: Deserialized response to file");		
    	System.out.println("Web service response is in: " + outputFile.getAbsolutePath());
    Stand-alone WCF web service client that reads from Norwegian HL7 WCF web service using Visual Studio generated code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Serialization;
    using System.IO;
    namespace WcfClientToWcfService
        class Program
            static void Main(string[] args)
                String inputFile = @"C:\HL7\MirthTesting\read\PRPA_EX201307NO_10_PatientReg_GetDemographics.xml";
                String outputFile = @"C:\HL7\MirthTesting\response\response_GetDemographics_using_WcfClient.xml";
                XmlDocument doc = new XmlDocument();            
                XmlReader reader = new XmlNodeReader(doc);
                XmlSerializer serializer = new XmlSerializer(typeof(PatientRegistryQueryFulfiller.PRPA_IN201307NO), "urn:hl7-org:v3");            
                PatientRegistryQueryFulfiller.PRPA_IN201307NO patientRegistryRequest = (PatientRegistryQueryFulfiller.PRPA_IN201307NO)serializer.Deserialize(reader);
                System.Console.WriteLine("SUCCESS: XML payload read from " + inputFile);
                PatientRegistryQueryFulfiller.AddGetDemographicsClient svc = new PatientRegistryQueryFulfiller.AddGetDemographicsClient();
                System.Console.WriteLine("SUCCESS: Created web service client instance.");
                PatientRegistryQueryFulfiller.PRPA_IN201307NOResponse patientRegistryResponse = svc.GetDemographics(patientRegistryRequest);
                System.Console.WriteLine("SUCCESS: Called getDemographics on service.");
                XmlDocument responseDoc = new XmlDocument();
                serializer = new XmlSerializer(typeof(PatientRegistryQueryFulfiller.PRPA_IN201308NO), "urn:hl7-org:v3");
                StringWriter strWriter = new StringWriter();
                serializer.Serialize(strWriter, (PatientRegistryQueryFulfiller.PRPA_IN201308NO)patientRegistryResponse.Item);
                System.Console.WriteLine("SUCCESS: Deserialized response to file");
                System.Console.WriteLine("Web service response is in: " + outputFile);
                System.Console.WriteLine("Press any key to exit");
    Last edited by janbrogger; 02-25-2012, 08:55 AM. Reason: added Mirth use of SoapUI


    • #3
      HTTP logging informative

      I downloaded and built Mirth. I turned on HTTP logging using tPipe.dump=true
      as a Java VM system property argument under Run configuration, and turned on console logging to a file.

      Using the standard JAX-WS generated Java client, the HTTP request is this:
      INFO: Trying web service call with wsimport generated classes
      SUCCESS: XML payload read from: C:\HL7\MirthTesting\read\PRPA_EX201307NO_10_Patien tReg_GetDemographics.xml
      SUCCESS: wsimport style: Created web service client instance.
      SUCCESS: wsimport style: Got http binding proxy.
      ---[HTTP request -]---
      Accept: [text/xml, multipart/related]
      Content-Type: [text/xml; charset=utf-8]
      SOAPAction: ["GetDemographics"]
      User-Agent: [JAX-WS RI 2.2.4-b01]
      <?xml version="1.0" ?><S:Envelope xmlns:S="">
      <S:Body><PRPA_IN201307NO xmlns="urn:hl7-org:v3" ITSVersion="XML_1.0">
      <id extension="080527104501_37" root="2.16.578.">
      <creationTime value="20080527104501"></creationTime>
      <versionCode code="NE2008"></versionCode>
      <interactionId extension="PRPA_IN201307NO" root="2.16.840.1.113883.1.6">
      <processingCode code="P"></processingCode>
      <processingModeCode code="T"></processingModeCode>
      <acceptAckCode code="NE"></acceptAckCode>
      <receiver typeCode="RCV">
      <device classCode="DEV" determinerCode="INSTANCE">
      <id extension="922" root="2.16.578.1.34.1"></id>
      <sender typeCode="SND"><device classCode="DEV" determinerCode="INSTANCE">
      <id extension="222" root="2.16.578.1.34.1"></id>
      <controlActProcess classCode="CACT" moodCode="EVN">
      <authorOrPerformer typeCode="AUT">
      <assignedPerson classCode="ASSIGNED">
      <id extension="12345" root="2.16.578."></id>
      <queryId extension="080527104501_37" root="2.16.578."></queryId>
      <statusCode code="new">
      <patientIdentifier><value extension="13125142356" root="2.16.578.1.34.1000.1"></value>
      and the server response is as expected OK:
      ---[HTTP response - http://serverurl:81/AddGetDemographi...mographics.svc - 200]---
      null: [HTTP/1.1 200 OK]
      Cache-Control: [private]
      Content-Length: [1392]
      Content-Type: [text/xml; charset=utf-8]
      Date: [Tue, 28 Feb 2012 07:28:58 GMT]
      Server: [Microsoft-IIS/7.5]
      X-AspNet-Version: [4.0.30319]
      X-Powered-By: [ASP.NET]
      <s:Envelope xmlns:s="">
      <s:Body><PRPA_IN201307NO-Response xmlns="urn:hl7-org:v3">
      <PRPA_IN201308NO ITSVersion="XML_1.0">
      <id root="2.16.578.1.34.922.3" extension="6fbec65a-af40-43cc-88de-64951d9fddfe"/>
      <creationTime value="20120228082857"/>
      <versionCode code="NE2008"/><interactionId root="2.16.840.1.113883.1.6" extension="PRPA_IN201308NO"/>
      <processingCode code="T"/>
      <processingModeCode code="T"/>
      <acceptAckCode code="NE"/>
      <receiver typeCode="RCV">
      <device determinerCode="INSTANCE" classCode="DEV"><id root="2.16.578.1.34.1" extension="222"/>
      <sender typeCode="SND">
      <device determinerCode="INSTANCE" classCode="DEV"><id root="2.16.578.1.34.1" extension="2.16.578."/></device>
      <typeCode code="AA"/>
      <id root="2.16.578." extension="080527104501_37"/></targetMessage>
      <controlActProcess moodCode="EVN" classCode="CACT">
      <authorOrPerformer typeCode="AUT">
      <assignedDevice classCode="ASSIGNED">
      <id root="2.16.578.1.34.1" extension="2.16.578."/></assignedDevice>
      <queryId root="2.16.578." extension="080527104501_37"/>
      <queryResponseCode code="NF"/><resultCurrentQuantity value="0"/>
      <resultRemainingQuantity value="0"/>
      The Mirth output shows that Mirth tries to send the SOAP envelope without any substitition and the SOAP action is empty.
      INFO 2012-02-28 09:39:41,608 [main] com.mirth.connect.server.Mirth: Mirth Connect 2.2.1 (Built on februar 25, 2012) server successfully started.
      INFO 2012-02-28 09:39:41,608 [main] com.mirth.connect.server.Mirth: This product was developed by Mirth Corporation ( and its contributors (c)2005-2012.
      INFO 2012-02-28 09:39:41,608 [main] com.mirth.connect.server.Mirth: Running Java HotSpot(TM) Client VM 1.7.0_03 on Windows XP (5.1, x86), derby, with charset windows-1252.
      ---[HTTP request - http://serverurl:81/AddGetDemographi...aphics.svc]---
      Accept: [text/xml, multipart/related]
      Content-Length: [2313390]
      Content-Type: [text/xml; charset=utf-8]
      SOAPAction: [""]
      User-Agent: [JAX-WS RI 2.2.4-b01]
      <?xml version="1.0" ?>
      <soapenv:Envelope xmlns:soapenv="" xmlns:urn="urn:hl7-org:v3"><soapenv:Body>
      <urn:PRPA_IN201307NO ITSVersion="XML_1.0" nullFlavor="?">
      <!--Zero or more repetitions:-->
      <urn:realmCode code="?" nullFlavor="?"></urn:realmCode>
      <urn:typeId assigningAuthorityName="?" displayable="?" extension="?" nullFlavor="?" root="?"></urn:typeId>
      <!--Zero or more repetitions:-->
      <urn:templateId assigningAuthorityName="?" displayable="?" extension="?" nullFlavor="?" root="?"></urn:templateId>
      <urn:id assigningAuthorityName="?" displayable="?" extension="?" nullFlavor="?" root="?"></urn:id>
      <urn:creationTime nullFlavor="?" value="?"></urn:creationTime>
      <urn:securityText language="?" mediaType="text/plain" nullFlavor="?" representation="TXT"></urn:securityText>
      <urn:versionCode code="?" nullFlavor="?"></urn:versionCode>
      <urn:interactionId assigningAuthorityName="?" displayable="?" extension="?" nullFlavor="?" root="?"></urn:interactionId>
      <!--Zero or more repetitions:-->
      <urnrofileId assigningAuthorityName="?" displayable="?" extension="?" nullFlavor="?" root="?"></urnrofileId>
      <urnrocessingCode code="?" nullFlavor="?"></urnrocessingCode>
      <urnrocessingModeCode code="?" nullFlavor="?"></urnrocessingModeCode>
      <urn:acceptAckCode code="?" nullFlavor="?"></urn:acceptAckCode>
      <urn:sequenceNumber nullFlavor="?" value="?"></urn:sequenceNumber>
      <!--Zero or more repetitions:-->
      <urn:attachmentText compression="?" integrityCheck="cid:800921637605" integrityCheckAlgorithm="SHA-1" language="?" mediaType="text/plain" nullFlavor="?" representation="TXT">
      and of course the server responds with "Bad request":
      ---[HTTP response - http://serverurl:81/AddGetDemographi...mographics.svc - 400]---
      null: [HTTP/1.1 400 Bad Request]
      Cache-Control: [private]
      Content-Type: [text/html]
      Date: [Tue, 28 Feb 2012 08:41:28 GMT]
      Server: [Microsoft-IIS/7.5]
      Transfer-Encoding: [chunked]
      X-AspNet-Version: [4.0.30319]
      X-Powered-By: [ASP.NET]
      Bad Request--------------------
      Any ideas?
      Last edited by janbrogger; 02-28-2012, 02:37 AM. Reason: removed plaintext url


      • #4
        I looked through the webinar. It appears that we've completely misunderstood how Mirth works. It is all about channels, destinations and transformations.

        I've decided to just play around with a file reader and file writer for now, to see what is really going on under the hood.

        To get this simple test up and running, we need to change the SOAP envelope to contain the example message somehow.

        Mirth is a nuclear submarine - powerful and mystical, but documentation is non-existent so it seems that unless you want to spend a lot of time like we just did, pay for training or support.


        • #5
          Solution found, posted in another thread

          A solution found, posted in a separate thread.

          Answer also posted to Stackoverflow.
          Last edited by janbrogger; 03-05-2012, 10:34 PM.