views:

197

answers:

3

Hello Comrades,

I've faced with a problem of sending complex requests with GroovyWS.

This is sample request generated by soapUI:

<soapenv:Envelope 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:dex="http://www.temp.com/com/dex" 
>
 <soapenv:Header/>
 <soapenv:Body>
  <dex:executeRequest>
     <!--Optional:-->
     <a>?</a>
     <!--Optional:-->
     <b>?</b>
     <!--Optional:-->
     <parameters>
        <!--Zero or more repetitions:-->
        <parameter>
           <!--Optional:-->
           <key>?</key>
           <!--Optional:-->
           <value>?</value>
        </parameter>
     </parameters>
     <!--Optional:-->
     <c>?</c>
     <!--Optional:-->
     <d>?</d>
  </dex:feedrequest>
 </soapenv:Body>
</soapenv:Envelope>

the piece of groovy code:

def proxy = webService.getClient(grailsApplication.config.ws.endpoint);
proxy.processdRequest(?);

So what I should pass instead of ?.

Thanks for you help.

-vova.

+1  A: 

GroovyWS dynamically creates classes for each of the argument types you need in order to pass data to the web service call. For instance, if the webservice call was:

public int passSomeArgs( Arg1Type a, Arg2Type b );

GroovyWS would dynamically create an Arg1Type class and an Arg2Type class, which you could access via a method on the proxy.

// this will instantiate an Arg1Type for you
def arg1 = proxy.create( "ns1.ns2.Arg1Type" );  
// this will instantiate an Arg2Type for you
def arg2 = proxy.create( "ns1.ns2.Arg2Type" );  

You can then populate the arg1/arg2 instance with data and make your call:

int ret = proxy.passSomeArgs( arg1, arg2 );

Note, there are probably some namespaces involved in the classes being created. I used the CXF logging that was printed as GroovyWS was processing the WSDL to see what CXF thought the class names should actually be.

Bill James
+1  A: 

Many thanks Bill.

I just want to add some info for future readers.

To turn on logging for GroovyWS in Grails:

log4j = {
   debug 'grails.app',
         'groovyx.net.ws',
         'org.apache.cxf'
}

With this as mentioned Bill you can see the names of the classes.


One more thing: parameters may have different type. Not List<?>. That's why it should be created too.

def params = proxy.create('com.temp.feeds.FeedRequestType$Parameters');

To retrieve available methods and fields for newly created objects you can use Groovy reflection:

params.class.methods.each{
        println it;
}
params.class.fields.each{
        println it;
}

That's all!

-vova

trnl
A: 

Thanks! I got GroovyWS working with a really complex webservice!

My steps: I turned on debug to get the root class, then did that reflection code to get inner classes, and go on setting properties and check if it is string or list.

And voilá!

def proxy = new WSClient(wsdl,this.class.classLoader)
proxy.initialize()

def f2bCobranca = proxy.create("br.com.f2b.soap.wsbilling.F2BCobranca") //got with debug on

//Show me inner classes of root class
f2bCobranca.class.fields.each { log.debug it }
f2bCobranca.class.methods.each { log.debug it }

f2bCobranca.cobranca = proxy.create('br.com.f2b.soap.wsbilling.F2BCobranca$Cobranca')
f2bCobranca.cobranca.demonstrativo << 'teste' //it's a list!
f2bCobranca.cobranca.sacadorAvalista = 'teste jose'
f2bCobranca.cobranca.desconto = proxy.create('br.com.f2b.soap.wsbilling.F2BCobranca$Cobranca$Desconto')
f2bCobranca.cobranca.multa = proxy.create('br.com.f2b.soap.wsbilling.F2BCobranca$Cobranca$Multa')

def sacado1 = proxy.create('br.com.f2b.soap.wsbilling.F2BCobranca$Sacado')
sacado1.nome = "teste ${new Date()}"
sacado1.email << '[email protected]'
sacado1.endereco = proxy.create('br.com.f2b.soap.wsbilling.F2BCobranca$Sacado$Endereco')
sacado1.telefone = proxy.create('br.com.f2b.soap.wsbilling.F2BCobranca$Sacado$Telefone')
sacado1.telefoneCom = proxy.create('br.com.f2b.soap.wsbilling.F2BCobranca$Sacado$TelefoneCom')
sacado1.telefoneCel = proxy.create('br.com.f2b.soap.wsbilling.F2BCobranca$Sacado$TelefoneCel')
sacado1.cpf = ''
sacado1.cnpj = ''
sacado1.observacao = ''
f2bCobranca.sacado << sacado1  

def retorno = proxy.RegisterWSBilling(f2bCobranca)
log.debug retorno
Wanderson Santos