{"id":10954,"date":"2013-01-03T09:00:00","date_gmt":"2013-01-03T08:00:00","guid":{"rendered":"http:\/\/pjagielski.github.com\/2013\/01\/03\/using-wslite-in-practice"},"modified":"2022-08-01T12:15:04","modified_gmt":"2022-08-01T10:15:04","slug":"using-wslite-in-practice","status":"publish","type":"post","link":"https:\/\/touk.pl\/blog\/2013\/01\/03\/using-wslite-in-practice\/","title":{"rendered":"Using WsLite in practice"},"content":{"rendered":"<h2 id=\"tldr\">TL;DR<\/h2>\n<p>There is a example working <a href=\"https:\/\/github.com\/pjagielski\/wslite-example\">GitHub project<\/a> which covers unit testing and request\/response logging when using WsLite.<\/p>\n<h2 id=\"why-groovy-wslite-\"><span id=\"why-groovy-wslite\">Why Groovy WsLite ?<\/span><\/h2>\n<p>I\u2019m a huge fan of <a href=\"https:\/\/github.com\/jwagenleitner\/groovy-wslite\">Groovy WsLite<\/a> project for calling SOAP web services. Yes, in a real world you have to deal with those &#8211; big companies have huge amount of \u201clegacy\u201d code and are crazy about homogeneous architecture &#8211; only SOAP, Java, Oracle, AIX\u2026<\/p>\n<p>But I also never been comfortable with XFire\/CXF approach of web service client code generation. I wrote a bit about other posibilites in <a href=\"http:\/\/jagielu.com\/2010\/09\/16\/virtual-esb-application-integration\">this post<\/a>. With JAXB you can also experience some freaky classloading errors &#8211; as Tomek described <a href=\"http:\/\/refaktor.blogspot.com\/2012\/09\/classloader-problem-with-java-7-and.html\">on his blog<\/a>. In a large commercial project the \u201cthe less code the better\u201d principle is significant. And the code generated from XSD could look kinda ugly &#8211; especially more complicated structures like sequences, choices, anys etc.<\/p>\n<p>Using WsLite with native Groovy concepts like <code>XmlSlurper<\/code> could be a great choice. But since it\u2019s a dynamic approach you have to be really careful &#8211; write good unit tests and log requests. Below are my few hints for using WsLite in practice.<\/p>\n<h2 id=\"unit-testing\">Unit testing<\/h2>\n<p>Suppose you have some invocation of WsLite SOAPClient (original WsLite example):<\/p>\n<div class=\"highlight\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">def getMothersDay(long _year) {\r\n    def response = client.send(SOAPAction: action) {\r\n       body {\r\n           GetMothersDay('xmlns':'http:\/\/www.27seconds.com\/Holidays\/US\/Dates\/') {\r\n              year(_year)\r\n           }\r\n       }\r\n    }\r\n    response.GetMothersDayResponse.GetMothersDayResult.text()\r\n}\r\n<\/pre>\n<\/div>\n<p>How can the unit test like? My suggestion is to mock <code>SOAPClient<\/code> and write a simple helper to test that builded XML is correct. Example using great <a href=\"http:\/\/code.google.com\/p\/spock\/\">SpockFramework<\/a>:<\/p>\n<div class=\"highlight\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"xml\">void setup() {\r\n   client = Mock(SOAPClient)\r\n   service.client = client\r\n}\r\n\r\ndef \"should pass year to GetMothersDay and return date\"() {\r\n  given:\r\n      def year = 2013\r\n  when:\r\n      def date = service.getMothersDay(year)\r\n  then:\r\n      1 * client.send(_, _) &gt;&gt; { Map params, Closure requestBuilder -&gt;\r\n            Document doc = buildAndParseXml(requestBuilder)\r\n            assertXpathEvaluatesTo(\"$year\", '\/\/ns:GetMothersDay\/ns:year', doc)\r\n            return mockResponse(Responses.mothersDay)\r\n      }\r\n      date == \"2013-05-12T00:00:00\"\r\n}\r\n<\/pre>\n<\/div>\n<p>This uses a real cool feature of Spock &#8211; even when you mock the invocation with \u201cany mark\u201d (_), you are able to get actual arguments. So we can build XML that would be passed to <code>SOAPClient's<\/code> <code>send<\/code> method and check that specific XPaths are correct:<\/p>\n<div class=\"highlight\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">void setup() {\r\n    engine = XMLUnit.newXpathEngine()\r\n    engine.setNamespaceContext(new SimpleNamespaceContext(namespaces()))\r\n}\r\n\r\nprotected Document buildAndParseXml(Closure xmlBuilder) {\r\n    def writer = new StringWriter()\r\n    def builder = new MarkupBuilder(writer)\r\n    builder.xml(xmlBuilder)\r\n    return XMLUnit.buildControlDocument(writer.toString())\r\n}\r\n\r\nprotected void assertXpathEvaluatesTo(String expectedValue,\r\n                                      String xpathExpression, Document doc) throws XpathException {\r\n    Assert.assertEquals(expectedValue,\r\n            engine.evaluate(xpathExpression, doc))\r\n}\r\n\r\nprotected Map namespaces() {\r\n    return [ns: 'http:\/\/www.27seconds.com\/Holidays\/US\/Dates\/']\r\n}\r\n<\/pre>\n<\/div>\n<p>The <a href=\"http:\/\/xmlunit.sourceforge.net\/\">XMLUnit<\/a> library is used just for <code>XpathEngine<\/code>, but it is much more powerful for comparing XML documents. The <code>NamespaceContext<\/code> is needed to use correct prefixes (e.g. <code>ns:GetMothersDay<\/code>) in your Xpath expressions.<\/p>\n<p>Finally &#8211; the mock returns <code>SOAPResponse<\/code> instance filled with envelope parsed from some constant XML:<\/p>\n<div class=\"highlight\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">protected SOAPResponse mockResponse(String resp) {\r\n    def envelope = new XmlSlurper().parseText(resp)\r\n    new SOAPResponse(envelope: envelope)\r\n}\r\n<\/pre>\n<\/div>\n<h2 id=\"request-and-response-logging\">Request and response logging<\/h2>\n<p>The WsLite itself doesn\u2019t use any logging framework. We usually handle it by adding own <code>sendWithLogging<\/code> method:<\/p>\n<div class=\"highlight\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">private SOAPResponse sendWithLogging(String action, Closure cl) {\r\n    SOAPResponse response = client.send(SOAPAction: action, cl)\r\n    log(response?.httpRequest, response?.httpResponse)\r\n    return response\r\n}\r\n\r\nprivate void log(HTTPRequest request, HTTPResponse response) {\r\n    log.debug(\"HTTPRequest $request with content:\\n${request?.contentAsString}\")\r\n    log.debug(\"HTTPResponse $response with content:\\n${response?.contentAsString}\")\r\n}\r\n<\/pre>\n<\/div>\n<p>This logs the actual request and response send through <code>SOAPClient<\/code>.<br \/>\nBut it logs only when invocation is successful and errors are much more interesting\u2026 So here goes <code>withExceptionHandler<\/code> method:<\/p>\n<div class=\"highlight\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">private SOAPResponse withExceptionHandler(Closure cl) {\r\n    try {\r\n        cl.call()\r\n    } catch (SOAPFaultException soapEx) {\r\n        log(soapEx.httpRequest, soapEx.httpResponse)\r\n        def message = soapEx.hasFault() ? soapEx.fault.text() : soapEx.message\r\n        throw new InfrastructureException(message)\r\n    } catch (HTTPClientException httpEx) {\r\n        log(httpEx.request, httpEx.response)\r\n        throw new InfrastructureException(httpEx.message)\r\n    }\r\n}\r\ndef send(String action, Closure cl) {\r\n    withExceptionHandler {\r\n        sendWithLogging(action, cl)\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>envelope<\/p>\n<h2 id=\"xmlslurper-gotchas\">XmlSlurper gotchas<\/h2>\n<p>Working with XML document with <code>XmlSlurper<\/code> is generally great fun, but is some cases could introduce some problems.<br \/>\nA trivial example is parsing an id with a number to <code>Long<\/code> value:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">def id = Long.valueOf(edit.'@id' as String)<\/pre>\n<p>The <code>Attribute<\/code> class (which <code>edit.'@id'<\/code> evaluates to) can be converted to String using <code>as<\/code> operator, but converting to <code>Long<\/code> requires using <code>valueOf<\/code>.<\/p>\n<p>The second example is a bit more complicated. Consider following XML fragment:<\/p>\n<div class=\"highlight\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"xml\">&lt;edit id=\"3\"&gt;\r\n   &lt;params&gt;\r\n      &lt;param value=\"label1\" name=\"label\"\/&gt;\r\n      &lt;param value=\"2\" name=\"param2\"\/&gt;\r\n   &lt;\/params&gt;\r\n   &lt;value&gt;123&lt;\/value&gt;\r\n&lt;\/edit&gt;\r\n&lt;edit id=\"6\"&gt;\r\n   &lt;params&gt;\r\n      &lt;param value=\"label2\" name=\"label\"\/&gt;\r\n      &lt;param value=\"2\" name=\"param2\"\/&gt;\r\n   &lt;\/params&gt;\r\n   &lt;value&gt;456&lt;\/value&gt;\r\n&lt;\/edit&gt;\r\n<\/pre>\n<\/div>\n<p>We want to find id of <code>edit<\/code> whose <code>label<\/code> is <strong>label1<\/strong>. The simplest solution seems to be:<\/p>\n<div class=\"highlight\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">def param = doc.edit.params.param.find { it['@value'] == 'label1' }\r\ndef edit = params.parent().parent()<\/pre>\n<\/div>\n<p>But it doesn\u2019t work! The <code>parent<\/code> method returns multiple <code>edits<\/code>, not only the one that is parent of given <code>param<\/code>\u2026<\/p>\n<p>Here\u2019s the correct solution:<\/p>\n<div class=\"highlight\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">doc.edit.find { edit -&gt;\r\n    edit.params.param.find { it['@value'] == 'label1' }\r\n}\r\n<\/pre>\n<\/div>\n<h2 id=\"example\">Example<\/h2>\n<p>The example working project covering those hints could be found on <a href=\"https:\/\/github.com\/pjagielski\/wslite-example\">GitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"TL;DR\nThere is a example working GitHub project which covers unit testing and request\/response logging when using WsLite.\nWhy Groovy WsLite ?\nI&rsquo;m a huge fan of Groovy WsLite project for calling SOAP web services. Yes, in a real world you have to deal with those &#8211; big companies have huge amount of &ldquo;legacy&rdquo; code and are crazy about homogeneous architecture &#8211; only SOAP, Java, Oracle, AIX&hellip; \nBut I also never been comfortable with XFire\/CXF approach of web service client code generation. I wrote a bit about other posibilites in this post. With JAXB you can also experience some freaky classloading errors &#8211; as Tomek described on his blog. In a large commercial project the &ldquo;the less code the better&rdquo; principle is significant. And the code generated from XSD could look kinda ugly &#8211; especially more complicated structures like sequences, choices, anys etc.\nUsing WsLite with native Groovy concepts like XmlSlurper could be a great choice. But since it&rsquo;s a dynamic approach you have to be really careful &#8211; write good unit tests and log requests. Below are my few hints for using WsLite in practice.\nUnit testing\nSuppose you have some invocation of WsLite SOAPClient (original WsLite example):\n\ndef getMothersDay(long _year) {\r\n    def response = client.send(SOAPAction: action) {\r\n       body {\r\n           GetMothersDay('xmlns':'http:\/\/www.27seconds.com\/Holidays\/US\/Dates\/') {\r\n              year(_year)\r\n           }\r\n       }\r\n    }\r\n    response.GetMothersDayResponse.GetMothersDayResult.text()\r\n}\r\n\n\nHow can the unit test like? My suggestion is to mock SOAPClient and write a simple helper to test that builded XML is correct. Example using great SpockFramework: \n\nvoid setup() {\r\n   client = Mock(SOAPClient)\r\n   service.client = client\r\n}\r\n\r\ndef \"should pass year to GetMothersDay and return date\"() {\r\n  given:\r\n      def year = 2013\r\n  when:\r\n      def date = service.getMothersDay(year)\r\n  then:\r\n      1 * client.send(_, _) &gt;&gt; { Map params, Closure requestBuilder -&gt;\r\n            Document doc = buildAndParseXml(requestBuilder)\r\n            assertXpathEvaluatesTo(\"$year\", '\/\/ns:GetMothersDay\/ns:year', doc)\r\n            return mockResponse(Responses.mothersDay)\r\n      }\r\n      date == \"2013-05-12T00:00:00\"\r\n}\r\n\n\nThis uses a real cool feature of Spock &#8211; even when you mock the invocation with &ldquo;any mark&rdquo; (_), you are able to get actual arguments. So we can build XML that would be passed to SOAPClient's send method and check that specific XPaths are correct:\n\nvoid setup() {\r\n    engine = XMLUnit.newXpathEngine()\r\n    engine.setNamespaceContext(new SimpleNamespaceContext(namespaces()))\r\n}\r\n\r\nprotected Document buildAndParseXml(Closure xmlBuilder) {\r\n    def writer = new StringWriter()\r\n    def builder = new MarkupBuilder(writer)\r\n    builder.xml(xmlBuilder)\r\n    return XMLUnit.buildControlDocument(writer.toString())\r\n}\r\n\r\nprotected void assertXpathEvaluatesTo(String expectedValue,\r\n                                      String xpathExpression, Document doc) throws XpathException {\r\n    Assert.assertEquals(expectedValue,\r\n            engine.evaluate(xpathExpression, doc))\r\n}\r\n\r\nprotected Map namespaces() {\r\n    return [ns: 'http:\/\/www.27seconds.com\/Holidays\/US\/Dates\/']\r\n}\r\n\n\nThe XMLUnit library is used just for XpathEngine, but it is much more powerful for comparing XML documents. The NamespaceContext is needed to use correct prefixes (e.g. ns:GetMothersDay) in your Xpath expressions.\nFinally &#8211; the mock returns SOAPResponse instance filled with envelope parsed from some constant XML:\n\nprotected SOAPResponse mockResponse(String resp) {\r\n    def envelope = new XmlSlurper().parseText(resp)\r\n    new SOAPResponse(envelope: envelope)\r\n}\r\n\n\nRequest and response logging\nThe WsLite itself doesn&rsquo;t use any logging framework. We usually handle it by adding own sendWithLogging method:\n\nprivate SOAPResponse sendWithLogging(String action, Closure cl) {\r\n    SOAPResponse response = client.send(SOAPAction: action, cl)\r\n    log(response?.httpRequest, response?.httpResponse)\r\n    return response\r\n}\r\n\r\nprivate void log(HTTPRequest request, HTTPResponse response) {\r\n    log.debug(\"HTTPRequest $request with content:\\n${request?.contentAsString}\")\r\n    log.debug(\"HTTPResponse $response with content:\\n${response?.contentAsString}\")\r\n}\r\n\n\nThis logs the actual request and response send through SOAPClient.\nBut it logs only when invocation is successful and errors are much more interesting&hellip; So here goes withExceptionHandler method:\n\nprivate SOAPResponse withExceptionHandler(Closure cl) {\r\n    try {\r\n        cl.call()\r\n    } catch (SOAPFaultException soapEx) {\r\n        log(soapEx.httpRequest, soapEx.httpResponse)\r\n        def message = soapEx.hasFault() ? soapEx.fault.text() : soapEx.message\r\n        throw new InfrastructureException(message)\r\n    } catch (HTTPClientException httpEx) {\r\n        log(httpEx.request, httpEx.response)\r\n        throw new InfrastructureException(httpEx.message)\r\n    }\r\n}\r\ndef send(String action, Closure cl) {\r\n    withExceptionHandler {\r\n        sendWithLogging(action, cl)\r\n    }\r\n}\r\n\n\nXmlSlurper gotchas\nWorking with XML document with XmlSlurper is generally great fun, but is some cases could introduce some problems.\nA trivial example is parsing an id with a number to Long value:\n\ndef id = Long.valueOf(edit.'@id' as String)\r\n\n\nThe Attribute class (which edit.'@id' evaluates to) can be converted to String using as operator, but converting to Long requires using valueOf.\nThe second example is a bit more complicated. Consider following XML fragment:\n\n&lt;edit id=\"3\"&gt;\r\n   &lt;params&gt;\r\n      &lt;param value=\"label1\" name=\"label\"\/&gt;\r\n      &lt;param value=\"2\" name=\"param2\"\/&gt;\r\n   &lt;\/params&gt;\r\n   &lt;value&gt;123&lt;\/value&gt;\r\n&lt;\/edit&gt;\r\n&lt;edit id=\"6\"&gt;\r\n   &lt;params&gt;\r\n      &lt;param value=\"label2\" name=\"label\"\/&gt;\r\n      &lt;param value=\"2\" name=\"param2\"\/&gt;\r\n   &lt;\/params&gt;\r\n   &lt;value&gt;456&lt;\/value&gt;\r\n&lt;\/edit&gt;\r\n\n\nWe want to find id of edit whose label is label1. The simplest solution seems to be:\n\ndef param = doc.edit.params.param.find { it['@value'] == 'label1' }\r\ndef edit = params.parent().parent()\r\n\n\nBut it doesn&rsquo;t work! The parent method returns multiple edits, not only the one that is parent of given param&hellip; \nHere&rsquo;s the correct solution:\n\ndoc.edit.find { edit -&gt;\r\n    edit.params.param.find { it['@value'] == 'label1' }\r\n}\r\n\n\nExample\nThe example working project covering those hints could be found on GitHub.\n","protected":false},"author":5,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[50,107],"class_list":{"0":"post-10954","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-development-design","7":"tag-groovy","8":"tag-xml"},"_links":{"self":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/10954","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/comments?post=10954"}],"version-history":[{"count":12,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/10954\/revisions"}],"predecessor-version":[{"id":14759,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/10954\/revisions\/14759"}],"wp:attachment":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/media?parent=10954"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/categories?post=10954"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/tags?post=10954"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}