On Dec 14, 2011, at 9:26 AM, Daniel Kulp wrote:

> On Tuesday, December 13, 2011 12:20:21 PM Rahul Somasunderam wrote:
>> Hi,
>> 
>> I'm working on a health project. There are a bunch of standards that we use
>> that are available to us as a WSDL. The WSDLs are located at
>> ftp://ftp.ihe.net/TF_Implementation_Material/ITI/wsdl/
>> 
>> However different implementors serve the WSDL with different namespaces in
>> the WSDL. And this seems to make it hard for me to integrate with any
>> random implementor.
>> 
>> For instance, this is my own server using CXF -
>> http://107.20.211.185/hd/services/xdsregistryb?wsdl This is NIST
>> implementing the same using Axis2 -
>> http://ihexds.nist.gov:9080/tf6/services/xdsregistryb
>> 
>> I've created a testcase that shows how my CXF client code fails.
>> 
>> How am I to deal with changing namespaces in WSDLs?
> 
> Well, that Axis2 wsdl is COMPLETELY bogus compared to the specifications that 
> you list in the first link.   It's not just the namespaces.  (the namespaces 
> ARE part of the spec and thus the services that implement the standard/spec 
> should be respecting that)   However, the structure of the messages are also 
> completely different.    Look at the request for the AdhocQuery operation.
> 
> For the spec and for the CXF service, a SOAP:Body would have a child element 
> of:
> {urn:oasis:names:tc:ebxml-regrep:xsd:query:3.0}AdhocQueryRequest
> 
> For the Axis2 service, the soap body would actually be empty.  No content 
> what 
> so ever.   The message in the wsdl looks like:
> <wsdl:message name="AdhocQueryRequestRequest"/>
> 
> Basically, the CXF service properly looks like the standard, the other one 
> does not at all resemble it.
> 

That's true, but I don't control what technology is used by another 
implementor. I still need to be able to talk to their implementation using my 
client code.
Is there some simpler way of doing this in CXF?

I tinkered with CXF default behavior at each step of the process:
1. During service creation I need to parse the WSDL and provide the service 
QName. This means there's a second call by CXF to the WSDL.
2. To create the port, I need to specify the port QName again. Unfortunately, 
there are multiple ports available in the Axis2 WSDL and I need to identify the 
one with SOAP 1.2.
3. Then the method call is again a problem, because method names are not 
identical, and I don't know how to get around it. Is it possible to have CXF 
use the action names instead of method names?

  private def doTest(String endpoint, String patientId) {
    // Constants
    def soap12 = new Namespace("http://schemas.xmlsoap.org/wsdl/soap12/";)
    def wsdl = new Namespace("http://schemas.xmlsoap.org/wsdl/";)

    // Derivations
    def endpointUrl = endpoint.toURL()
    def webServiceDef = new XmlParser().parseText(endpointUrl.text)
    def targetNamespace = webServiceDef.@targetNamespace
    def serviceName = webServiceDef[wsdl.service][email protected]()
    println "Target Namespace: ${targetNamespace}"
    println "Service Name: ${serviceName}"

    def soap12Binding = webServiceDef[wsdl.binding].find { binding ->
      binding[soap12.binding]
    }
    println "Binding name: ${soap12Binding?.@name}"

    def soap12Port = webServiceDef[wsdl.service][wsdl.port].find { port ->
      [email protected](soap12Binding.@name)
    }
    println "Port name: ${soap12Port?.@name}"


    def service = new DocumentRegistryService(endpointUrl, new 
QName(targetNamespace, serviceName))
    def port = service.getPort(new QName(targetNamespace, soap12Port.@name), 
DocumentRegistryPortType)

    def resp = port.documentRegistryRegistryStoredQuery(new AdhocQueryRequest(
        responseOption: new ResponseOptionType(returnType: 'LeafClass', 
returnComposedObjects: true),
        adhocQuery: new AdhocQueryType(
            id: "urn:uuid:14d4debf-8f97-4251-9a74-a90016b0af0d",
            slot: [
                new SlotType1(
                    name: '$XDSDocumentEntryPatientId',
                    valueList: new ValueListType(value: [patientId]),
                ),
                new SlotType1(name: '\$XDSDocumentEntryStatus',
                    valueList: new ValueListType(value: 
['urn:oasis:names:tc:ebxml-regrep:StatusType:Approved'])
                )
            ]
        )
    ))
  }


I get this exception when testing against the Axis2 site:
java.lang.Error: Undefined operation name DocumentRegistry_RegistryStoredQuery
        at 
com.sun.xml.internal.ws.model.JavaMethodImpl.freeze(JavaMethodImpl.java:316)
        at 
com.sun.xml.internal.ws.model.AbstractSEIModelImpl.freeze(AbstractSEIModelImpl.java:93)
        at 
com.sun.xml.internal.ws.model.RuntimeModeler.buildRuntimeModel(RuntimeModeler.java:250)
        at 
com.sun.xml.internal.ws.client.WSServiceDelegate.createSEIPortInfo(WSServiceDelegate.java:687)
        at 
com.sun.xml.internal.ws.client.WSServiceDelegate.addSEI(WSServiceDelegate.java:675)
        at 
com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:330)
        at 
com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:313)
        at 
com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:295)
        at javax.xml.ws.Service.getPort(Service.java:92)
        at javax.xml.ws.Service$getPort.call(Unknown Source)
        at ihe.iti.xds_b._2007.NamespaceTest.doTest(NamespaceTest.groovy:51)
        at 
ihe.iti.xds_b._2007.NamespaceTest.testAgainstNist(NamespaceTest.groovy:75)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at 
com.intellij.junit3.JUnit3IdeaTestRunner.doRun(JUnit3IdeaTestRunner.java:139)
        at 
com.intellij.junit3.JUnit3IdeaTestRunner.startRunnerWithArgs(JUnit3IdeaTestRunner.java:52)
        at 
com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:199)
        at 
com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:62)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)


Which makes sense because the operation names are different. However the action 
names are the same. Is there some way I can tinker with it to get the right 
operation name to be called?

R,
rahul


> -- 
> Daniel Kulp
> [email protected] - http://dankulp.com/blog
> Talend Community Coder - http://coders.talend.com

Reply via email to