Repository: authorjapps/zerocode
Pull request #38 (2018-02-24 17:53:43)

Zcode sonatype release branch


Patch:
diff --git a/README.md b/README.md
index 007901ad..bc6c84b0 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
 ## REST BDD - ZeroCode Testing Framework
-[![Build Status](https://travis-ci.org/authorjapps/zerocode.svg?branch=master)](https://travis-ci.org/authorjapps/zerocode)
+[![Build Status](https://travis-ci.org/authorjapps/zerocode.svg?branch=master)](https://travis-ci.org/authorjapps/zerocode) 
+
+[![Github Pre-Releases](https://img.shields.io/github/downloads-pre/atom/atom/latest/total.svg)](https://github.com/authorjapps/zerocode-hello-world/archive/master.zip) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](https://github.com/authorjapps/zerocode/blob/master/LICENSE) [![PyPI](https://img.shields.io/pypi/status/Django.svg)]() [![GitHub issue comments](https://img.shields.io/github/issues/detail/comments/badges/shields/979.svg)](https://github.com/authorjapps/zerocode/issues) [![zero code zerocode hello world](https://img.shields.io/badge/automation-testing-green.svg)](https://github.com/authorjapps/zerocode-hello-world) [![zerocode REST API Automation](https://img.shields.io/badge/REST%20API-automation-green.svg)](https://github.com/authorjapps/zerocode-hello-world) [![zerocode SOAP Testing Automation API Automation](https://img.shields.io/badge/SOAP%20testing-automation-blue.svg)](https://github.com/authorjapps/zerocode/issues/28)
 
 Execute your complex business scenario steps with simple jsons which defines your RESTful service behaviour.
 
@@ -14,10 +16,10 @@ Latest maven release:
 <dependency>
     <groupId>org.jsmart</groupId>
     <artifactId>zerocode-rest-bdd</artifactId>
-    <version>1.1.23</version> <!-- But check here for latest: http://search.maven.org/#search%7Cga%7C1%7Czerocode -->
+    <version>1.1.25</version> 
 </dependency>
 ```
-
+But check here for latest- https://github.com/authorjapps/zerocode/releases -or- http://search.maven.org/#search%7Cga%7C1%7Czerocode
 
 Save yourselves from:
 <pre><code><del>
@@ -100,6 +102,9 @@ And the "hello_world_get.json" is as below:
 - [Passing Headers to the REST API](#20) 
 - [Setting Jenkins env propperty and picking environment specific properties file](#21)
 - [LocalDate and LocalDateTime format example](#22)
+- [SOAP method invocation example using xml input](#23)
+- [SOAP method invocation where Corporate Proxy enabled](#24)
+- [MIME Type Converters- XML to JSON, prettyfy XML etc](#25)
 - [General place holders and assertion place holder table](#99)
 
 
@@ -663,6 +668,20 @@ See here how to Use SSL HttpClient : [See usage of @UseHttpClient](https://githu
 
 See here custom one : [See usage of @UseHttpClient](https://github.com/authorjapps/helpme/blob/master/zerocode-rest-help/src/test/java/org/jsmart/zerocode/testhelp/zcmore/ZeroCodeUnitRunnerWithCustomHttpClient.java)
 
+e.g.
+```
+@UseHttpClient(SslTrustHttpClient.class)
+@TargetEnv("hosts_ci.properties")
+@RunWith(ZeroCodeUnitRunner.class)
+public class SslTrustUseHttpClientTest {
+
+    @Test
+    @JsonTestCase("foo/bar/test_case_file.json")
+    public void testASmartTestCase_createUpdate() throws Exception {
+
+    }
+}
+```
 
 #### 17:
 #### Externalizing RESTful host and port into properties file(s).
@@ -763,6 +782,7 @@ public class EnvPropertyHelloWorldTest {
 
 
 #### 22:
+
 #### LocalDate and LocalDateTime format example
 
 ```
@@ -805,8 +825,8 @@ output: 2018-02-11T21:31:21.77481041     // "uuuu-MM-dd'T'HH:mm:ss.A"
 output: 2018-02-14                       // "uuuu-MM-dd" or "yyyy-MM-dd"
 Default: date.toString(): 2018-02-11T21:31:20.989          // .toString()
 ```
-### See here more:
-==> https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
+### See here more-
+https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
 
 ```
      H       hour-of-day (0-23)          number            0
@@ -829,8 +849,349 @@ All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. The follo
  d       day-of-month                number            10
 ```
 
-#### 99:
+#### 23:
+
+#### SOAP method invocation example with xml input
+
+You can invoke SOAP as below which is already supported by zerocode lib, or you can write your own SOAP executor using Java(if 
+you want to, but you don't have to). 
+(If you want- Then, in the README file go to section -> "Calling java methods(apis) for specific tasks" )
+
+```
+{
+    "scenarioName": "GIVEN a SOAP end poinr WHEN I invoke a method with a request XML, THEN I will ge the SOAP response in XML",
+    "steps": [
+        {
+            "name": "invoke_currency_conversion",
+            "url": "http://<target-domain.com>/<path etc>",
+            "operation": "POST",
+            "request": {
+                "headers": {
+                    "Content-Type": "text/xml; charset=utf-8",
+                    "SOAPAction": "<get this from WSDL file, this has the port or method or action name in the url>"
+                    //"SOAPAction": "\"<or wrap it in double quotes as some SOAP servers understand it>\""
+                },
+                "body": "escaped request XML message ie the soap:Envelope message"
+                -or- // pick from- src/test/resources/soap_requests/xml_files/soap_request.xml
+                "body": "${XML.FILE:soap_requests/xml_files/soap_request.xml}" 
+            },
+            "assertions": {
+                "status": 200
+            }
+        }
+    ]
+}
+```
+
+e.g. below-
+This example invokes a free SOAP service over internet.
+Note:
+If this service is down, the invocation might fail.
+So better to test against an available SOAP service to you or a local stub service.
+
+```
+{
+    "scenarioName": "GIVEN a SOAP end poinr WHEN I invoke a method with a request XML, THEN I will ge the SOAP response in XML",
+    "steps": [
+        {
+            "name": "invoke_currency_conversion",
+            "url": "http://www.webservicex.net/CurrencyConvertor.asmx",
+            "operation": "POST",
+            "request": {
+                "headers": {
+                    "Content-Type": "text/xml; charset=utf-8",
+                    "SOAPAction": "http://www.webserviceX.NET/ConversionRate"
+                    //"SOAPAction": "\"http://www.webserviceX.NET/ConversionRate\""
+                },
+                "body": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n  <soap:Body>\n    <ConversionRate xmlns=\"http://www.webserviceX.NET/\">\n      <FromCurrency>AFA</FromCurrency>\n      <ToCurrency>GBP</ToCurrency>\n    </ConversionRate>\n  </soap:Body>\n</soap:Envelope>"
+                // -or- 
+                // "body": "${XML.FILE:soap_requests/xml_files/soap_request.xml}"
+            },
+            "assertions": {
+                "status": 200
+            }
+        }
+    ]
+}
+```
+
+You should received the below-
+```
+Response:
+{
+  "status" : 200,
+  "headers" : {
+    "Date" : [ "Fri, 16 Feb 2018 05:38:27 GMT" ],
+    "Server" : [ "Microsoft-IIS/7.0" ]
+  },
+  
+  "rawBody" : "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><soap:Body><ConversionRateResponse xmlns=\"http://www.webserviceX.NET/\"><ConversionRateResult>-1</ConversionRateResult></ConversionRateResponse></soap:Body></soap:Envelope>"
+}
+*responseTimeStamp:2018-02-16T05:38:35.254
+*Response delay:653.0 milli-secs
+ ```
+
+
+#### 24:
+#### SOAP method invocation where Corporate Proxy enabled
+You need to use a HttpClient ie override the BasicHttpClient and set proxies to it as below-
+```
+        Step-1)
+        CredentialsProvider credsProvider = createProxyCredentialsProvider(proxyHost, proxyPort, proxyUserName, proxyPassword);
+
+        Step-2)
+        HttpHost proxy = new HttpHost(proxyHost, proxyPort);
+ 
+        Step-3) method Step-1
+        private CredentialsProvider createProxyCredentialsProvider(String proxyHost, int proxyPort, String proxyUserName, String proxyPassword) {
+
+                CredentialsProvider credsProvider = new BasicCredentialsProvider();
+        
+                credsProvider.setCredentials(
+        
+                        new AuthScope(proxyHost, proxyPort),
+        
+                        new UsernamePasswordCredentials(proxyUserName, proxyPassword));
+        
+                return credsProvider;
+        }
+ 
+        Step-4) 
+        Set the values from Step-1 and Step-2
+        
+        HttpClients.custom()
+
+                .setSSLContext(sslContext)
 
+                .setSSLHostnameVerifier(new NoopHostnameVerifier())
+
+                .setDefaultCookieStore(cookieStore)
+
+                .setDefaultCredentialsProvider(credsProvider)    //<------------- From Step-1
+
+                .setProxy(proxy)                                 //<------------- From Step-2
+
+                .build();
+```
+
+You can inject the Corporate Proxy details to the custom {{HttpClient}} li below from a config file simply by annotating 
+the key names from the host config file which is used by the runner for mentioning host and port.
+e.g. below:
+See an example here-
+https://github.com/authorjapps/zerocode/blob/master/src/main/java/org/jsmart/zerocode/core/httpclient/soap/SoapCorporateProxySslHttpClient.java
+
+Usage example here:
+https://github.com/authorjapps/zerocode/blob/master/src/test/java/org/jsmart/zerocode/core/soap/SoapCorpProxySslHttpClientTest.java
+
+How to use?
+```
+@UseHttpClient(SoapCorporateProxySslHttpClient.class)
+@TargetEnv("soap_host_with_corp_proxy.properties")
+@RunWith(ZeroCodeUnitRunner.class)
+public class SoapCorpProxySslHttpClientTest {
+
+    @Ignore
+    @Test
+    @JsonTestCase("foo/bar/soap_test_case_file.json")
+    public void testSoapWithCorpProxyEnabled() throws Exception {
+
+    }
+}
+```
+
+Explanation below- 
+
+```
+@TargetEnv("hello_world_host.properties")
+@RunWith(ZeroCodeUnitRunner.class)
+public class HelloWorldTest {
+     // @Test
+     // tests here
+}
+
+soap_host_with_corp_proxy.properties
+---------------------------
+# Web Server host and port
+restful.application.endpoint.host=https://soap-server-host/ServiceName
+restful.application.endpoint.port=443
+
+# Web Service context; Leave it blank in case you do not have a common context
+restful.application.endpoint.context=
+
+#sample test purpose - if you remove this from ehre, then make sure to remove from Java file
+corporate.proxy.host=http://exam.corporate-proxy-host.co.uk
+corporate.proxy.port=80
+corporate.proxy.username=HAVYSTARUSER
+corporate.proxy.password=i#am#here#for#soap#
+
+
+Your HttpClient:
+----------------
+See-
+https://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientProxyAuthentication.java
+
+public class YourHttpClient {
+
+    @Inject
+    @Named("corporate.proxy.host")
+    private String proxyHost;
+
+    @Inject
+    @Named("corporate.proxy.port")
+    private String proxyPort;
+
+    @Inject
+    @Named("corporate.proxy.username")
+    private String proxyUserName;
+
+    @Inject
+    @Named("corporate.proxy.password")
+    private String proxyPassword;
+
+    // Build the client using these.
+}
+```
+
+#### 25:
+#### MIME Type Converters- XML to JSON, prettyfy XML etc
+e.g.
+##### xmlToJson
+```
+{
+            "name": "xml_to_json",
+            "url": "org.jsmart.zerocode.converter.MimeTypeConverter",
+            "operation": "xmlToJson",
+            "request": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n  <soap:Body>\n    <ConversionRate xmlns=\"http://www.webserviceX.NET/\">\n      <FromCurrency>AFA</FromCurrency>\n      <ToCurrency>GBP</ToCurrency>\n    </ConversionRate>\n  </soap:Body>\n</soap:Envelope>",
+            "assertions": {
+                "soap:Envelope": {
+                    "xmlns:xsd": "http://www.w3.org/2001/XMLSchema",
+                    "xmlns:soap": "http://schemas.xmlsoap.org/soap/envelope/",
+                    "xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
+                    "soap:Body": {
+                        "ConversionRate": {
+                            "xmlns": "http://www.webserviceX.NET/",
+                            "FromCurrency": "AFA",
+                            "ToCurrency": "GBP"
+                        }
+                    }
+                }
+            }
+        }
+```
+
+##### jsonToJson
+Various input and output. Depending upon the usecase, you can use that method.
+
+```
+{
+    "scenarioName": "Given a json string or json block, convert to equivalent json block",
+    "steps": [
+        {
+            "name": "json_block_to_json",
+            "url": "org.jsmart.zerocode.converter.MimeTypeConverter",
+            "operation": "jsonBlockToJson",
+            "request": {
+                "headers": {
+                    "hdrX": "valueX"
+                },
+                "body": {
+                    "id": 1001,
+                    "addresses": [
+                        {
+                            "postCode": "PXY"
+                        },
+                        {
+                            "postCode": "LMZ DDD"
+                        }
+                    ]
+                }
+            },
+            "assertions": {
+                "headers": {
+                    "hdrX": "valueX"
+                },
+                "body": {
+                    "id": 1001,
+                    "addresses": [
+                        {
+                            "postCode": "PXY"
+                        },
+                        {
+                            "postCode": "${$.json_block_to_json.request.body.addresses[1].postCode}"
+                        }
+                    ]
+                }
+            }
+        },
+        {
+            "name": "json_to_json",
+            "url": "org.jsmart.zerocode.converter.MimeTypeConverter",
+            "operation": "jsonToJson",
+            "request": "${$.json_block_to_json.request.headers}",
+            "assertions": {
+                "hdrX": "valueX"
+            }
+        },
+        {
+            "name": "body_json_to_json",
+            "url": "org.jsmart.zerocode.converter.MimeTypeConverter",
+            "operation": "jsonToJson",
+            "request": "${$.json_block_to_json.request.body}",
+            "assertions": {
+                "id": 1001,
+                "addresses": [
+                    {
+                        "postCode": "PXY"
+                    },
+                    {
+                        "postCode": "LMZ DDD"
+                    }
+                ]
+            }
+        },
+        {
+            "name": "json_node_to_json",
+            "url": "org.jsmart.zerocode.converter.MimeTypeConverter",
+            "operation": "jsonBlockToJson",
+            "request": {
+                "headers": {
+                    "hdrX": "valueX"
+                },
+                "body": {
+                    "id": 1001,
+                    "addresses": [
+                        {
+                            "postCode": "PXY"
+                        }
+                    ]
+                }
+            },
+            "assertions": {
+                "headers": {
+                    "hdrX": "valueX"
+                },
+                "body": {
+                    "id": 1001,
+                    "addresses": [
+                        {
+                            "postCode": "${$.json_block_to_json.request.body.addresses[0].postCode}"
+                        }
+                    ]
+                }
+            }
+        }
+    ]
+}
+```
+Available methods are- 
+* xmlToJson
+* jsonToJson
+* jsonBlockToJson
+* jsonNodeToJson
+* prettyXml
+
+
+#### 99:
 #### Place holders for End Point Mocking
 
 | Place Holder  | Output        | More  |
diff --git a/pom.xml b/pom.xml
index 1763aa53..bacc3ce1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
 
     <artifactId>zerocode-rest-bdd</artifactId>
     <groupId>org.jsmart</groupId>
-    <version>1.1.26-SNAPSHOT</version>
+    <version>1.1.27-SNAPSHOT</version>
 
     <packaging>jar</packaging>
     <name>ZeroCode REST BDD</name>
diff --git a/src/main/java/org/jsmart/zerocode/converter/MimeTypeConverter.java b/src/main/java/org/jsmart/zerocode/converter/MimeTypeConverter.java
index 361048ba..2668c40e 100644
--- a/src/main/java/org/jsmart/zerocode/converter/MimeTypeConverter.java
+++ b/src/main/java/org/jsmart/zerocode/converter/MimeTypeConverter.java
@@ -30,11 +30,10 @@ public class MimeTypeConverter implements Converter {
 
     @Override
     public Object xmlToJson(String xmlContent) {
-        final String xmlFormated = prettyFormat(xmlContent);
 
-        LOGGER.info("\n------------------------- XML -----------------------------\n"
-                + xmlFormated +
-                "\n------------------------- * -----------------------------\n");
+        // Just print it so that anyone can pick the
+        // formatted xml for their usage from the console.
+        prettyXml(xmlContent);
 
         String jsonNotPretty = XML.toJSONObject(xmlContent).toString();
 
@@ -50,7 +49,9 @@ public class MimeTypeConverter implements Converter {
 
     /**
      * Converts input JSON string (usually escaped e.g. "{\"a\": \"b\", \"active\": true}" ) to JSON block
-     * See also- method jsonBlockToJson for unescaped json to json block.
+     * See also-
+     * - method jsonBlockToJson for unescaped json to json block.
+     * - method jsonNodeToJson for unescaped json to json block.
      *
      * @param jsonString
      * @return
@@ -73,11 +74,18 @@ public class MimeTypeConverter implements Converter {
         return jsonNode;
     }
 
-    public static String prettyFormat(String input) {
-        return prettyFormat(input, 2);
+    public static String prettyXml(String input) {
+
+        final String formattedXml = prettyXmlWithIndentType(input, 2);
+
+        LOGGER.info("\n--------------------- Pretty XML -------------------------\n"
+                + formattedXml +
+                "\n------------------------- * -----------------------------\n");
+
+        return formattedXml;
     }
 
-    public static String prettyFormat(String originalXml, int indentType) {
+    public static String prettyXmlWithIndentType(String originalXml, int indentType) {
         try {
             Source xmlInput = new StreamSource(new StringReader(originalXml));
             StringWriter stringWriter = new StringWriter();
diff --git a/src/main/java/org/jsmart/zerocode/core/httpclient/soap/SoapCorporateProxySslHttpClient.java b/src/main/java/org/jsmart/zerocode/core/httpclient/soap/SoapCorporateProxySslHttpClient.java
new file mode 100644
index 00000000..77e6dba4
--- /dev/null
+++ b/src/main/java/org/jsmart/zerocode/core/httpclient/soap/SoapCorporateProxySslHttpClient.java
@@ -0,0 +1,197 @@
+package org.jsmart.zerocode.core.httpclient.soap;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import org.apache.commons.io.IOUtils;
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CookieStore;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.entity.EntityBuilder;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.RequestBuilder;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLContextBuilder;
+import org.apache.http.impl.client.BasicCookieStore;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.jsmart.zerocode.core.httpclient.BasicHttpClient;
+import org.jsmart.zerocode.core.utils.HelperJsonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.SSLContext;
+import javax.ws.rs.core.Response;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Map;
+
+import static java.lang.String.format;
+import static org.apache.http.entity.ContentType.APPLICATION_JSON;
+import static org.jsmart.zerocode.core.utils.HelperJsonUtils.getContentAsItIsJson;
+
+public class SoapCorporateProxySslHttpClient implements BasicHttpClient {
+    private static final Logger LOGGER = LoggerFactory.getLogger(SoapCorporateProxySslHttpClient.class);
+
+    @Inject
+    @Named("corporate.proxy.host")
+    private String proxyHost;
+
+    @Inject
+    @Named("corporate.proxy.port")
+    private int proxyPort;
+
+    @Inject
+    @Named("corporate.proxy.username")
+    private String proxyUserName;
+
+    @Inject
+    @Named("corporate.proxy.password")
+    private String proxyPassword;
+
+    private Object COOKIE_JSESSIONID_VALUE;
+
+    @Override
+    public Response execute(String httpUrl, String methodName, Map<String, Object> headers, Map<String, Object> queryParams, Object body) throws Exception {
+
+        LOGGER.info("###SOAP Http Client with Corporate Proxy enabled via SSL");
+
+        /** ---------------------------
+         * Get the request body content
+         * ----------------------------
+         */
+        String reqBodyAsString = getContentAsItIsJson(body);
+
+        CloseableHttpClient httpclient = createSslHttpClient();
+
+        /** -----------------------
+         * set the query parameters
+         * ------------------------
+         */
+        if (queryParams != null) {
+            httpUrl = setQueryParams(httpUrl, queryParams);
+        }
+
+        RequestBuilder requestBuilder = RequestBuilder
+                .create(methodName)
+                .setUri(httpUrl);
+
+        if (reqBodyAsString != null) {
+            HttpEntity httpEntity = EntityBuilder.create()
+                    .setContentType(APPLICATION_JSON)
+                    .setText(reqBodyAsString)
+                    .build();
+            requestBuilder.setEntity(httpEntity);
+        }
+
+        /** --------------
+         * set the headers
+         * ---------------
+         */
+        if (headers != null) {
+            Map headersMap = headers;
+            for (Object key : headersMap.keySet()) {
+                requestBuilder.addHeader((String) key, (String) headersMap.get(key));
+            }
+        }
+
+        /** -----------------------------------------------------------------------------------
+         * Setting cookies:
+         *
+         * Highly discouraged to use sessions, but in case of any server dependent upon session,
+         * then it's taken care here.
+         * ------------------------------------------------------------------------------------
+         */
+        if (COOKIE_JSESSIONID_VALUE != null) {
+            requestBuilder.addHeader("Cookie", (String) COOKIE_JSESSIONID_VALUE);
+        }
+
+        /** ----------------------
+         * now execute the request
+         * -----------------------
+         */
+        CloseableHttpResponse httpResponse = httpclient.execute(requestBuilder.build());
+
+        Response serverResponse = Response
+                .status(httpResponse.getStatusLine().getStatusCode())
+                .entity(IOUtils.toString(httpResponse.getEntity().getContent(), "UTF-8"))
+                .build();
+
+
+        Header[] allHeaders = httpResponse.getAllHeaders();
+        Response.ResponseBuilder responseBuilder = Response.fromResponse(serverResponse);
+        for (Header thisHeader : allHeaders) {
+            String headerKey = thisHeader.getName();
+            responseBuilder = responseBuilder.header(headerKey, thisHeader.getValue());
+
+            /** ---------------
+             * Session handled
+             * ----------------
+             */
+            if ("Set-Cookie".equals(headerKey)) {
+                COOKIE_JSESSIONID_VALUE = serverResponse.getMetadata().get(headerKey);
+            }
+        }
+        serverResponse = responseBuilder.build();
+
+        return serverResponse;
+    }
+
+    private CloseableHttpClient createSslHttpClient() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
+        SSLContext sslContext = new SSLContextBuilder()
+                .loadTrustMaterial(null, (certificate, authType) -> true).build();
+
+        CookieStore cookieStore = new BasicCookieStore();
+
+        CredentialsProvider credsProvider = createProxyCredentialsProvider(proxyHost, proxyPort, proxyUserName, proxyPassword);
+
+        HttpHost proxy = new HttpHost(proxyHost, proxyPort);
+
+        return HttpClients.custom()
+                .setSSLContext(sslContext)
+                .setSSLHostnameVerifier(new NoopHostnameVerifier())
+                .setDefaultCookieStore(cookieStore)
+                .setDefaultCredentialsProvider(credsProvider)
+                .setProxy(proxy)
+                .build();
+    }
+
+    private CredentialsProvider createProxyCredentialsProvider(String proxyHost, int proxyPort, String proxyUserName, String proxyPassword) {
+
+        CredentialsProvider credsProvider = new BasicCredentialsProvider();
+
+        credsProvider.setCredentials(
+                new AuthScope(proxyHost, proxyPort),
+                new UsernamePasswordCredentials(proxyUserName, proxyPassword));
+
+        return credsProvider;
+
+    }
+
+
+    private String setQueryParams(String httpUrl, Map<String, Object> queryParams) {
+        String qualifiedQueryParams = createQualifiedQueryParams(queryParams);
+        httpUrl = httpUrl + qualifiedQueryParams;
+        return httpUrl;
+    }
+
+    private String createQualifiedQueryParams(Object queryParams) {
+        String qualifiedQueryParam = "?";
+        Map queryParamsMap = HelperJsonUtils.readHeadersAsMap(queryParams);
+        for (Object key : queryParamsMap.keySet()) {
+            if ("?".equals(qualifiedQueryParam)) {
+                qualifiedQueryParam = qualifiedQueryParam + format("%s=%s", key, queryParamsMap.get(key));
+            } else {
+                qualifiedQueryParam = qualifiedQueryParam + format("&%s=%s", key, queryParamsMap.get(key));
+            }
+        }
+        return qualifiedQueryParam;
+    }
+
+}
+
diff --git a/src/main/java/org/jsmart/zerocode/core/httpclient/ssl/SslTrustHttpClient.java b/src/main/java/org/jsmart/zerocode/core/httpclient/ssl/SslTrustHttpClient.java
index 88fc5af2..24ba6841 100644
--- a/src/main/java/org/jsmart/zerocode/core/httpclient/ssl/SslTrustHttpClient.java
+++ b/src/main/java/org/jsmart/zerocode/core/httpclient/ssl/SslTrustHttpClient.java
@@ -30,7 +30,7 @@ import static org.apache.http.entity.ContentType.APPLICATION_JSON;
 import static org.jsmart.zerocode.core.utils.HelperJsonUtils.getContentAsItIsJson;
 
 public class SslTrustHttpClient implements BasicHttpClient {
-    private static final Logger LOGGER = LoggerFactory.getLogger(RestEasyDefaultHttpClient.class);
+    private static final Logger LOGGER = LoggerFactory.getLogger(SslTrustHttpClient.class);
 
     private Object COOKIE_JSESSIONID_VALUE;
 


Test patch:
diff --git a/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeJsonTestProcesorImpl.java b/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeJsonTestProcesorImpl.java
index e08a7e47..414e8dfe 100644
--- a/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeJsonTestProcesorImpl.java
+++ b/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeJsonTestProcesorImpl.java
@@ -18,6 +18,7 @@ import org.jsmart.zerocode.core.engine.assertion.FieldHasSubStringValueAsserter;
 import org.jsmart.zerocode.core.engine.assertion.FieldIsNotNullAsserter;
 import org.jsmart.zerocode.core.engine.assertion.FieldIsNullAsserter;
 import org.jsmart.zerocode.core.engine.assertion.JsonAsserter;
+import org.jsmart.zerocode.core.utils.SmartUtils;
 
 import java.io.IOException;
 import java.math.BigDecimal;
@@ -52,6 +53,7 @@ public class ZeroCodeJsonTestProcesorImpl implements ZeroCodeJsonTestProcesor {
     private static final String STATIC_ALPHABET = "STATIC.ALPHABET:";
     private static final String LOCALDATE_TODAY = "LOCAL.DATE.TODAY:";
     private static final String LOCALDATETIME_NOW = "LOCAL.DATETIME.NOW:";
+    private static final String XML_FILE = "XML.FILE:";
 
     private static final List<String> availableTokens = Arrays.asList(
             PREFIX_ASU,
@@ -59,7 +61,8 @@ public class ZeroCodeJsonTestProcesorImpl implements ZeroCodeJsonTestProcesor {
             RANDOM_STRING_PREFIX,
             STATIC_ALPHABET,
             LOCALDATE_TODAY,
-            LOCALDATETIME_NOW
+            LOCALDATETIME_NOW,
+            XML_FILE
     );
 
     /*
@@ -113,6 +116,12 @@ public class ZeroCodeJsonTestProcesorImpl implements ZeroCodeJsonTestProcesor {
                         String formatPattern = runTimeToken.substring(LOCALDATETIME_NOW.length());
                         DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatPattern);
                         parammap.put(runTimeToken, LocalDateTime.now().format(formatter));
+                    } else if (runTimeToken.startsWith(XML_FILE)) {
+                        String xmlFileResource = runTimeToken.substring(XML_FILE.length());
+                        final String xmlString = getXmlContent(xmlFileResource);
+                        // Used escapeJavaScript, do not use escapeXml as it replaces
+                        // with GT LT etc ie what exactly you don't want
+                        parammap.put(runTimeToken, escapeJavaScript(xmlString));
                     }
                 }
             });
@@ -148,7 +157,8 @@ public class ZeroCodeJsonTestProcesorImpl implements ZeroCodeJsonTestProcesor {
                 if(thisPath.endsWith(RAW_BODY)){
                     /**
                      * In case the rawBody is used anywhere in the steps as $.step_name.response.rawBody,
-                     * then it must be escaped as the content was not a simple string convertible to json.
+                     * then it must be escaped as the content was not a simple JSON string to be able
+                     * to convert to json. Hence without throwing exception, treat as string content.
                      */
                     String escapedString = escapeJavaScript(JsonPath.read(scenarioState, thisPath));
                     paramMap.put(thisPath, escapedString);
@@ -387,4 +397,14 @@ public class ZeroCodeJsonTestProcesorImpl implements ZeroCodeJsonTestProcesor {
         return availableTokens;
     }
 
+    public String getXmlContent(String xmlFileResource){
+        try {
+            return SmartUtils.readJsonAsString(xmlFileResource);
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new RuntimeException("Oops! Problem occurred while reading the XML file '" + xmlFileResource
+                    + "', details:" + e);
+        }
+    }
+
 }
diff --git a/src/test/java/org/jsmart/zerocode/core/soap/SoapCorpProxySslHttpClientTest.java b/src/test/java/org/jsmart/zerocode/core/soap/SoapCorpProxySslHttpClientTest.java
new file mode 100644
index 00000000..781aafea
--- /dev/null
+++ b/src/test/java/org/jsmart/zerocode/core/soap/SoapCorpProxySslHttpClientTest.java
@@ -0,0 +1,26 @@
+package org.jsmart.zerocode.core.soap;
+
+import org.jsmart.zerocode.core.domain.JsonTestCase;
+import org.jsmart.zerocode.core.domain.TargetEnv;
+import org.jsmart.zerocode.core.domain.UseHttpClient;
+import org.jsmart.zerocode.core.httpclient.soap.SoapCorporateProxySslHttpClient;
+import org.jsmart.zerocode.core.httpclient.ssl.SslTrustHttpClient;
+import org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner;
+import org.jsmart.zerocode.core.tests.customrunner.TestOnlyZeroCodeUnitRunner;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@UseHttpClient(SoapCorporateProxySslHttpClient.class)
+@TargetEnv("soap_host_with_corp_proxy.properties")
+@RunWith(ZeroCodeUnitRunner.class)
+public class SoapCorpProxySslHttpClientTest {
+
+    @Ignore
+    @Test
+    @JsonTestCase("01_verification_test_cases/21_ssl_trust.json")
+    public void testASmartTestCase_createUpdate() throws Exception {
+
+    }
+}
+
diff --git a/src/test/java/org/jsmart/zerocode/core/soap/SoapEndPointTest.java b/src/test/java/org/jsmart/zerocode/core/soap/SoapEndPointTest.java
index 8d5a40ef..d0037a1c 100644
--- a/src/test/java/org/jsmart/zerocode/core/soap/SoapEndPointTest.java
+++ b/src/test/java/org/jsmart/zerocode/core/soap/SoapEndPointTest.java
@@ -14,11 +14,17 @@ import org.junit.runner.RunWith;
 @RunWith(ZeroCodeUnitRunner.class)
 public class SoapEndPointTest {
 
-    @Ignore("This works. Ignored only to avoid build failure when the internet site is down")
+    @Ignore("This works fine. Ignored only to avoid build failure if the internet site is down")
     @Test
     @JsonTestCase("16_soap/soap_endpoint_soap_action_post_200.json")
     public void testSoapEndPointWith_SOAPAction() throws Exception {
 
     }
+
+    @Test
+    @JsonTestCase("16_soap/soap_request_xml_from_external_xml_file.json")
+    public void testSoapRequestFromExternal_xmlFile() throws Exception {
+
+    }
 }
 
diff --git a/src/test/resources/16_soap/soap_endpoint_soap_action_post_200.json b/src/test/resources/16_soap/soap_endpoint_soap_action_post_200.json
index f7b25312..802465ef 100644
--- a/src/test/resources/16_soap/soap_endpoint_soap_action_post_200.json
+++ b/src/test/resources/16_soap/soap_endpoint_soap_action_post_200.json
@@ -37,6 +37,5 @@
                 }
             }
         }
-
     ]
 }
diff --git a/src/test/resources/16_soap/soap_request_xml_from_external_xml_file.json b/src/test/resources/16_soap/soap_request_xml_from_external_xml_file.json
new file mode 100644
index 00000000..d55b298e
--- /dev/null
+++ b/src/test/resources/16_soap/soap_request_xml_from_external_xml_file.json
@@ -0,0 +1,31 @@
+{
+    "scenarioName": "GIVEN a SOAP end point WHEN I invoke a method with a xml input file, THEN I will get the response",
+    "steps": [
+        {
+            "name": "invoke_currency_conversion",
+            "url": "/CurrencyConvertor.asmx",
+            "operation": "POST",
+            "request": {
+                "headers": {
+                    "Content-Type": "text/xml; charset=utf-8",
+                    "SOAPAction": "http://www.webserviceX.NET/ConversionRate"
+                },
+                "body": "${XML.FILE:16_soap/xml_files/soap_request.xml}"
+            },
+            "assertions": {
+                "status": 200,
+                "rawBody": "$CONTAINS.STRING:<ConversionRateResult>-1</ConversionRateResult>"
+            }
+        },
+        {
+            "name": "response_xml_to_json",
+            "url": "org.jsmart.zerocode.converter.MimeTypeConverter",
+            "operation": "prettyXml",
+            "request": "${$.invoke_currency_conversion.response.rawBody}",
+            "assertions": {
+
+            }
+        }
+
+    ]
+}
diff --git a/src/test/resources/16_soap/xml_files/soap_request.xml b/src/test/resources/16_soap/xml_files/soap_request.xml
new file mode 100644
index 00000000..68042d6d
--- /dev/null
+++ b/src/test/resources/16_soap/xml_files/soap_request.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
+    <soap:Body>
+        <ConversionRate xmlns="http://www.webserviceX.NET/">
+            <FromCurrency>AFA</FromCurrency>
+            <ToCurrency>GBP</ToCurrency>
+        </ConversionRate>
+    </soap:Body>
+</soap:Envelope>
\ No newline at end of file
diff --git a/src/test/resources/17_xml_to_json_converter/10_xml_to_json_format_happy.json b/src/test/resources/17_xml_to_json_converter/10_xml_to_json_format_happy.json
index 0fad282e..5776c0f2 100755
--- a/src/test/resources/17_xml_to_json_converter/10_xml_to_json_format_happy.json
+++ b/src/test/resources/17_xml_to_json_converter/10_xml_to_json_format_happy.json
@@ -1,45 +1,43 @@
 {
-  "scenarioName": "Given xml input Give me json output",
-  "steps": [
-    {
-      "name": "xml_to_json",
-        "url": "org.jsmart.zerocode.converter.MimeTypeConverter",
-        "operation": "xmlToJson",
-      "request": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n  <soap:Body>\n    <ConversionRate xmlns=\"http://www.webserviceX.NET/\">\n      <FromCurrency>AFA</FromCurrency>\n      <ToCurrency>GBP</ToCurrency>\n    </ConversionRate>\n  </soap:Body>\n</soap:Envelope>",
-      "assertions": {
-        "soap:Envelope" : {
-          "xmlns:xsd" : "http://www.w3.org/2001/XMLSchema",
-          "xmlns:soap" : "http://schemas.xmlsoap.org/soap/envelope/",
-          "xmlns:xsi" : "http://www.w3.org/2001/XMLSchema-instance",
-          "soap:Body" : {
-            "ConversionRate" : {
-              "xmlns" : "http://www.webserviceX.NET/",
-              "FromCurrency" : "AFA",
-              "ToCurrency" : "GBP"
+    "scenarioName": "Given xml input Give me json output",
+    "steps": [
+        {
+            "name": "xml_to_json",
+            "url": "org.jsmart.zerocode.converter.MimeTypeConverter",
+            "operation": "xmlToJson",
+            "request": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n  <soap:Body>\n    <ConversionRate xmlns=\"http://www.webserviceX.NET/\">\n      <FromCurrency>AFA</FromCurrency>\n      <ToCurrency>GBP</ToCurrency>\n    </ConversionRate>\n  </soap:Body>\n</soap:Envelope>",
+            "assertions": {
+                "soap:Envelope": {
+                    "xmlns:xsd": "http://www.w3.org/2001/XMLSchema",
+                    "xmlns:soap": "http://schemas.xmlsoap.org/soap/envelope/",
+                    "xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
+                    "soap:Body": {
+                        "ConversionRate": {
+                            "xmlns": "http://www.webserviceX.NET/",
+                            "FromCurrency": "AFA",
+                            "ToCurrency": "GBP"
+                        }
+                    }
+                }
             }
-          }
-        }
-      }
-    },
-    {
-      "name": "xml_to_json_json_path",
-      "url": "org.jsmart.zerocode.converter.MimeTypeConverter",
-      "operation": "xmlToJson",
-      "request": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n  <soap:Body>\n    <ConversionRate xmlns=\"http://www.webserviceX.NET/\">\n      <FromCurrency>AFA</FromCurrency>\n      <ToCurrency>GBP</ToCurrency>\n    </ConversionRate>\n  </soap:Body>\n</soap:Envelope>",
-      "assertions": {
-        "soap:Envelope" : {
-          "xmlns:xsd" : "${$.xml_to_json.response.soap:Envelope.xmlns:xsd}",
-          "xmlns:soap" : "http://schemas.xmlsoap.org/soap/envelope/",
-          "soap:Body" : {
-            "ConversionRate" : {
-              "FromCurrency" : "${$.xml_to_json.response.soap:Envelope.soap:Body.ConversionRate.FromCurrency}",
-              "ToCurrency" : "GBP"
+        },
+        {
+            "name": "xml_to_json_json_path",
+            "url": "org.jsmart.zerocode.converter.MimeTypeConverter",
+            "operation": "xmlToJson",
+            "request": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n  <soap:Body>\n    <ConversionRate xmlns=\"http://www.webserviceX.NET/\">\n      <FromCurrency>AFA</FromCurrency>\n      <ToCurrency>GBP</ToCurrency>\n    </ConversionRate>\n  </soap:Body>\n</soap:Envelope>",
+            "assertions": {
+                "soap:Envelope": {
+                    "xmlns:xsd": "${$.xml_to_json.response.soap:Envelope.xmlns:xsd}",
+                    "xmlns:soap": "http://schemas.xmlsoap.org/soap/envelope/",
+                    "soap:Body": {
+                        "ConversionRate": {
+                            "FromCurrency": "${$.xml_to_json.response.soap:Envelope.soap:Body.ConversionRate.FromCurrency}",
+                            "ToCurrency": "GBP"
+                        }
+                    }
+                }
             }
-          }
         }
-      }
-    }
-
-
-  ]
+    ]
 }
diff --git a/src/test/resources/soap_host_with_corp_proxy.properties b/src/test/resources/soap_host_with_corp_proxy.properties
new file mode 100755
index 00000000..4c1263fe
--- /dev/null
+++ b/src/test/resources/soap_host_with_corp_proxy.properties
@@ -0,0 +1,11 @@
+#
+restful.application.endpoint.host=https://soap-server.co.uk/ServiceName
+restful.application.endpoint.port=443
+
+# Google Map Service Context
+restful.application.endpoint.context=
+
+corporate.proxy.host=example.proxy.corp.co.uk
+corporate.proxy.port=80
+corporate.proxy.username=APPLEORANGE
+corporate.proxy.password=can3eat