2015-12-09 5 views
2

Я пытаюсь сделать общий метод для отправки запросов SOAP и получения ответов. Я программирую с помощью Groovy, и я использую библиотеку wslite, чтобы помочь мне с SOAP. Вот пример фрагмент кода для создания запроса SOAP и получить ответ:Динамическое построение замыканий с карты?

@Grab('com.github.groovy-wslite:groovy-wslite:1.1.2') 
import wslite.soap.* 

SOAPClient client = new SOAPClient('http://www.dneonline.com/calculator.asmx') 
def response = client.send(SOAPAction: 'http://tempuri.org/Add') { 
    body { 
      Add(xmlns: 'http://tempuri.org/') { 
       intA(x) 
       intB(y) 
      } 
    } 
} 

По общем, я имел в виду возможности динамически создать запрос SOAP (учитывая определенную информацию, такие как имя службы/методы, параметры, содержащиеся в метод и т. д.) и получить ответ SOAP. Я думаю примерно следующее:

@Grab('com.github.groovy-wslite:groovy-wslite:1.1.2') 
import wslite.soap.* 

def getResponse(String clientURL, String action, String service, String serviceNamespace, Map parameters, ...) { 
    SOAPClient client = new SOAPClient(clientURL) 
    def response = client.send(SOAPAction: action) { 
      body { 
       "$service"(xmlns: serviceNameSpace) { 
       ... 
       } 
      } 
    } 
} 

Моя проблема заключается в создании крышки для тела запроса. Как, в примере, если мой метод получил serviceAdd, а serviceNamespacehttp://tempuri.org/, и parameter карты так: [intA: x, intB: y] ... Как объединить все эти, так что я могу построить этот вид закрытия:

Add(xmlns: 'http://tempuri.org/') { 
    intA(x) 
    intB(y) 
} 

Я довольно много новичок в Groovy, так что не будьте слишком суровы. Если есть лучший способ реализовать эту концепцию общего метода, я бы с удовольствием это услышал. Концепция похожа на this. Но я предпочел бы играть с Map, чем String. На самом деле я не использую Grails. Просто Гровой.

+4

будет '[intA: x, intB: y] .each {fn, arg -> delegate." $ Fn "(arg)}' do? – cfrick

ответ

2

Короче говоря, cfrick правильно:

[intA: x, intB: y].each{fn,arg -> delegate."$fn"(arg) } 

Как это работает?

простой способ, чтобы увидеть, как это работает, чтобы имитировать его с поддельным класса клиента:

groovy.util.NodeBuilder 

class Client { 
    def send(String action, Closure closure) { 
     closure.delegate = new NodeBuilder() 

     closure() 
    } 
} 

def client = new Client() 

def response = client.send('http://tempuri.org/Add') { 
    body { 
     Add(xmlns: 'http://tempuri.org/') { 
       intA(1) 
       intB(2) 
      } 
    } 
} 

assert response.Add[0][email protected] == 'http://tempuri.org/' 
assert response.Add.intA.text() == '1' 
assert response.Add.intB.text() == '2' 

В приведенном выше примере объект response создается в Groovy NodeBuilder. Это просто быстрый способ прототипа того, что обрабатывает закрытие, переданное Client.send().

С помощью этого кода тестируемого Попробую, что cfrick предложил и подтвердить, что он работает:

def doIt(String action, String service, String serviceNamespace, Map params) { 
    def client = new Client() 

    client.send(action) { 
     body { 
      "$service"(xmlns: serviceNamespace) { 
        params.each { method, argument -> 
         delegate."$method"(argument) 
        } 
       } 
     } 
    } 
} 

response = doIt('http://tempuri.org/Add', 'Add', 'http://tempuri.org/', [intA: 1, intB: 2]) 

assert response.Add[0][email protected] == 'http://tempuri.org/' 
assert response.Add.intA.text() == '1' 
assert response.Add.intB.text() == '2' 

Запрос Body

Кроме того, вы можете вынесет процесс создания тела запроса:

def getRequestBody(String service, String serviceNamespace, Map params) { 
    { -> 
     "$service"(xmlns: serviceNamespace) { 
      params.each { method, argument -> 
       delegate."$method"(argument) 
      } 
     } 
    } 
} 

def doIt(String action, String service, String serviceNamespace, Map params) { 
    def client = new Client() 

    client.send(action) { 
     body(getRequestBody(service, serviceNamespace, params)) 
    } 
} 
+0

Может быть, слишком поздно спросить, но можно ли определить такой метод 'getRequestBody()', который вернет необходимое 'body {...}' закрытие? В дополнение к этому, имея возможность вызвать 'getRequestBody()' в таком месте, как: 'client.send ('http: // ...') {getRequestBody()}'? Как это может быть сделано? – Gee

+0

Да, но вы не можете называть его как 'client.send ('http: // ...') {getRequestBody()}'. Вместо этого вы можете закодировать 'getRequestBody' для использования как' client.send ('http: // ...') {body (getRequestBody())} 'или' client.send ('http: // ...' , getRequestBody()) '. Я добавил демонстрацию первого метода. –

Смежные вопросы