Coder Social home page Coder Social logo

groovy-wslite's Introduction

groovy-wslite Build Status

Library for Groovy that provides no-frills SOAP and REST webservice clients.

This library assumes you know exactly what messages you want to send to your services and want full control over the request. No streams are used and all request/responses are buffered in memory for convenience.

Versions

Note

Please consult the [Changelog] (https://github.com/jwagenleitner/groovy-wslite/blob/master/CHANGELOG.md) for any breaking changes.

1.0

2.0 (beta)

  • JDK 1.7 or higher
  • Requires [Groovy 2.3] (http://groovy.codehaus.org) or higher
  • Plans
    • Use Groovy's built-in JSON parsing
    • Support for HEAD and PATCH verbs
    • Make use of @CompileStatic where appropriate
    • Make API more extensible
    • Clean up connection handling

SOAP

Example

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

def client = new SOAPClient('http://www.holidaywebservice.com/Holidays/US/Dates/USHolidayDates.asmx')
def response = client.send(SOAPAction:'http://www.27seconds.com/Holidays/US/Dates/GetMothersDay') {
    body {
        GetMothersDay('xmlns':'http://www.27seconds.com/Holidays/US/Dates/') {
            year(2011)
        }
    }
}

assert "2011-05-08T00:00:00" == response.GetMothersDayResponse.GetMothersDayResult.text()
assert 200 == response.httpResponse.statusCode
assert "ASP.NET" == response.httpResponse.headers['X-Powered-By']

Usage

def client = new SOAPClient("http://...")
def response = client.send(SOAPAction: "SomeAction",
                           connectTimeout:5000,
                           readTimeout:10000,
                           useCaches:false,
                           followRedirects:false,
                           sslTrustAllCerts:true) {
    version SOAPVersion.V1_2        // SOAPVersion.V1_1 is default
    soapNamespacePrefix "SOAP"      // "soap-env" is default
    encoding "ISO-8859-1"           // "UTF-8" is default encoding for xml
    envelopeAttributes "xmlns:hr":"http://example.org/hr"
    header(mustUnderstand:false) {
        auth {
            apiToken("1234567890")
        }
    }
    body {
        GetWeatherByZipCode(xmlns:"http://example.weather.org") {
            ZipCode("93657")
        }
    }
}

The header and body closures are passed to a MarkupBuilder in order to create the SOAP message.

If you have a string with XML content you want to include in you can use mkp.

def response = client.send {
    body {
        GetWeatherByZipCode(xmlns:"http://example.weather.org") {
            mkp.yieldUnescaped "<ZipCode>93657</ZipCode>"
        }
    }
}

You can also pass a raw string to the send method if you want absolute control over the resulting message.

client.send(
    """<?xml version='1.0' encoding='UTF-8'?>
       <soap-env:Envelope xmlns:SOAP='http://schemas.xmlsoap.org/soap/envelope/'>
           <soap-env:Body>
               <GetFoo>bar</GetFoo>
           </soap-env:Body>
       </soap-env:Envelope>"""
)

The SOAP version will be auto-detected using the namespace URI of the Envelope element, you can override this by specifying a SOAPVersion.

client.send(SOAPVersion.V1_2,
            """<?xml version='1.0' encoding='UTF-8'?>
               <soap-env:Envelope xmlns:SOAP='http://www.w3.org/2003/05/soap-envelope'>
                   <soap-env:Body>
                       <GetFoo>bar</GetFoo>
                    </soap-env:Body>
                </soap-env:Envelope>""")

You can also specify connection settings.

client.send(SOAPVersion.V1_2,
            connectTimeout:7000,
            readTimeout:9000,
            """<?xml version='1.0' encoding='UTF-8'?>
               <soap-env:Envelope xmlns:SOAP='http://www.w3.org/2003/05/soap-envelope'>
                   <soap-env:Body>
                       <GetFoo>bar</GetFoo>
                   </soap-env:Body>
               </soap-env:Envelope>""")

SSL

Using a custom SSL trust store

In addition to setting a global trust store and trust store password using the javax.net.ssl.trustStore and javax.net.ssl.trustStorePassword System properties, you can set a custom trust store on a client.

import wslite.soap.*

def client = new SOAPClient("https://www.example.com/ExampleService")
client.httpClient.sslTrustStoreFile = "~/mykeystore.jks"
client.httpClient.sslTrustStorePassword = "secret"

def response = client.send() {
    ....
}

You can also specify a custom trust store on a per request basis, this will override any custom trust store that may be set on the client.

def client = new SOAPClient("https://www.example.com/ExampleService")
def response = client.send(sslTrustStoreFile:"~/mykeystore.jks", sslTrustStorePassword:"secret") {
    ....
}

Note: sslTrustStorePassword is optional.

Trusting all SSL certs

When in development mode and dealing with lots of servers with self-signed certs it can be helpful to bypass a custom trust store and trust all certs automatically.

import wslite.soap.*

def client = new SOAPClient("https://www.example.com/ExampleService")
client.httpClient.sslTrustAllCerts = true

def response = client.send() {
    ....
}

You can also specify a the same parameter on a per request basis.

def client = new SOAPClient("https://www.example.com/ExampleService")
def response = client.send(sslTrustAllCerts:true) {
    ....
}

Note: sslTrustAllCerts overrides any custom trust store settings that may have already be set on the client or the request.

Response

The response is automatically parsed by XmlSlurper and provides several convenient properties for accessing the SOAP message.

response.envelope

To get straight to the Header or Body element...

response.header or response.body

You can access the first child element of the Body by name response.GetWeatherByZipCodeResponse

If you just want the text of the response use response.text.

You can also access the underlying HTTPRequest response.httpRequest and HTTPResponse response.httpResponse objects.

SOAP Faults

If the server responds with a SOAP Fault a SOAPFaultException will be thrown. The SOAPFaultException wraps a SOAPResponse that contains the Fault.

import wslite.soap.*

def client = new SOAPClient("http://www.webservicex.net/WeatherForecast2.asmx")
try {
    def response = client.send {
        ....
    }
} catch (SOAPFaultException sfe) {
    println sfe.message // faultcode/faultstring for 1.1 or Code/Reason for 1.2
    println sfe.text    // prints SOAP Envelope
    println sfe.httpResponse.statusCode
    println sfe.fault.detail.text() // sfe.fault is a GPathResult of Envelope/Body/Fault
} catch (SOAPClientException sce) {
    // This indicates an error with underlying HTTP Client (i.e., 404 Not Found)
}

Proxy

If behind proxy, you can set it in the request.

def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress('proxy.example.com', 8080))

def client = new SOAPClient("https://www.example.com/ExampleService")
def response = client.send(proxy:proxy) {
    ....
}

If the proxy requires authentication...

Authenticator.setDefault(new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication("username","password".toCharArray())
    }
})

You can also set the proxy on the SOAP client itself or via the standard java.net "http.proxyHost" and "http.proxyPort" system properties (or their "https.*" counterparts). To configure the client with a proxy, use code like this:

def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress('proxy.example.com', 8080))

def client = new SOAPClient("https://www.example.com/ExampleService")
client.httpClient.proxy = proxy
....

In decreasing precedence, groovy-wslite picks the proxy settings from:

  1. The request's proxy
  2. The client's proxy
  3. The java.net system properties
  4. No proxy

REST

Example

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

def client = new RESTClient("http://api.twitter.com/1/")
def response = client.get(path:'/users/show.json', query:[screen_name:'jwagenleitner', include_entities:true])

assert 200 == response.statusCode
assert "John Wagenleitner" == response.json.name

Methods

RESTClient supports the following methods:

  • head
  • get
  • delete
  • post
  • put
  • patch

Parameters

The methods can all take a map as a parameter (though not required) that give you control over the request.

def client = new RESTClient("http://api.twitter.com/1/")
def response = client.get( path:'/users/show.json',
                           accept: ContentType.JSON,
                           query:[screen_name:'jwagenleitner', include_entities:true],
                           headers:["X-Foo":"bar"],
                           connectTimeout: 5000,
                           readTimeout: 10000,
                           followRedirects: false,
                           useCaches: false,
                           sslTrustAllCerts: true )

Sending Content

In addition to a Map, the post/put methods take an additional parameter of a Closure.

def client = new RESTClient("http://some.service.net/")
def response = client.post(path: "/comments") {
    type ContentType.XML
    xml {
        Comment {
            Text("This is my comment.")
        }
    }
}

When sending content you can also send byte[], text, url encoded parameters, xml and json.

def response = client.post() {
    type "application/vnd.lock-in-proprietary-format"  // String or ContentType
    charset "US-ASCII"

    // one of the following
    bytes new File("payload.txt").bytes
    text "hello world"
    urlenc username: "homer", password: "simpson", timezone: "EST"
    xml { root() }
    json id:"525", department:"Finance"
}

You can also do multipart requests for uploading files and such. You don't need to specify content type as this will be multipart/form-data and will have a content boundary assigned to it.

def response = client.post() {

    // call once for each body-part
    multipart 'username', 'antony'.bytes
    multipart 'files[myfile.png]', myFile.bytes
    // specify content-type and filename
    multipart 'inputFile', 'test'.bytes, 'image/png', 'test.png'
}

Client Defaults

When interacting with a service that requires a particular Accept header or when sending content of the same type/charset, you can set those as defaults so they will be sent for every request (if they are not already specified in the request):

client.defaultAcceptHeader = "text/xml"
client.defaultContentTypeHeader = "application/json"
client.defaultCharset = "UTF-8"

HTTP Authorization

Currently only Basic Auth is supported.

Basic Auth

import wslite.http.auth.*
import wslite.rest.*

def client = new RESTClient("http://some.service.net")
client.authorization = new HTTPBasicAuthorization("homer", "simpson")

SSL

Using a custom SSL trust store

In addition to setting a global trust store and trust store password using the javax.net.ssl.trustStore and javax.net.ssl.trustStorePassword System properties, you can set a custom trust store on a client.

import wslite.rest.*

def client = new RESTClient("http://some.service.net")
client.httpClient.sslTrustStoreFile = "~/mykeystore.jks"
client.httpClient.sslTrustStorePassword = "myKeystorePassword"

def response = client.get()

You can also specify a custom trust store on a per request basis, this will override any custom trust store that may be set on the client.

def client = new RESTClient("http://some.service.net")
client.get(sslTrustStoreFile:"~/mykeystore.jks", sslTrustStorePassword:"secret")

Note: sslTrustStorePassword is optional.

Trusting all SSL certs

When in development mode and dealing with lots of servers with self-signed certs it can be helpful to bypass a custom trust store and trust all certs automatically.

import wslite.rest.*

def client = new RESTClient("http://some.service.net")
client.httpClient.sslTrustAllCerts = true

def response = client.get()

You can also specify a the same parameter on a per request basis.

def client = new RESTClient("http://some.service.net")
def response = client.get(sslTrustAllCerts:true)

Note: sslTrustAllCerts overrides any custom trust store settings that may have already be set on the client or the request.

Response

The response has the following properties:

  • url
  • statusCode // 200
  • statusMessage // "Ok"
  • contentType // "text/xml" (parameters are not included such as charset)
  • charset // UTF-8 (charset parameter parsed from the returned Content-Type header)
  • contentEncoding // from headers
  • contentLength // from headers
  • date // from headers
  • expiration // from headers
  • lastModified // from headers
  • headers // Map (case insensitive) of all headers
  • data // byte[] of any content returned from the server

The response also includes the original HTTPReqeust (ex. response.request).

Content Type Handling

In addition to the above response properties, there are handlers for text, xml and json responses.

For all text based responses (content type starts with "text/") there will be a text (i.e., response.text) property available for the response.

For xml based responses, an xml (i.e., response.xml) property is available that is of type GPathResult.

For json based responses, a json (i.e., response.json) property is available that is of type returned from groovy.json.JsonSlurper.

Proxies

If you want to send requests via a proxy, you can configure one in several ways. You can do it at the level of the request:

// SOAPClient
def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress('proxy.example.com', 8080))

def client = new SOAPClient("https://www.example.com/ExampleService")
def response = client.send(proxy:proxy) {
    ....
}

// RESTClient
def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress('proxy.example.com', 8080))

def client = new RESTClient("http://api.twitter.com/1/")
def response = client.get(path:'/users/show.json', proxy:proxy, query:[screen_name:'jwagenleitner', include_entities:true])

You can also set the proxy on the SOAP client or REST client itself:

def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress('proxy.example.com', 8080))

def client = new SOAPClient("https://www.example.com/ExampleService")
client.httpClient.proxy = proxy
....

Finally, you can use the standard java.net "http.proxyHost" and "http.proxyPort" system properties (or their "https.*" counterparts).

In decreasing precedence, groovy-wslite picks the proxy settings from:

  1. The request's proxy
  2. The client's proxy
  3. The java.net system properties
  4. No proxy

If the proxy requires authentication, then you will need to set an Authenticator:

Authenticator.setDefault(new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication("username","password".toCharArray())
    }
})

Using groovy-wslite in your project

groovy-wslite is available in Maven Central.

Maven

Releases

<dependency>
    <groupId>com.github.groovy-wslite</groupId>
    <artifactId>groovy-wslite</artifactId>
    <version>1.1.2</version>
</dependency>

Snapshots

<repositories>
    <repository>
        <id>groovy-wslite</id>
        <url>https://oss.sonatype.org/content/groups/public</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>com.github.groovy-wslite</groupId>
        <artifactId>groovy-wslite</artifactId>
        <version>2.0.0-SNAPSHOT</version>
    </dependency>
</dependencies>

Groovy Grape

Releases

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

Snapshots

@GrabResolver(name='groovy-wslite', root='https://oss.sonatype.org/content/groups/public', m2Compatible=true)
@Grab(group='com.github.groovy-wslite', module='groovy-wslite', version='2.0.0-SNAPSHOT', changing=true)

Using with Grails

The SOAP/RESTClients can easily be configured and used in your Grails application.

  • Add the dependency to grails-app/conf/BuildConfig.groovy.

Note: You must enable the mavenCentral() repository.

grails.project.dependency.resolution = {
    ....
    ....
    repositories {
        ....
        ....
        mavenCentral()
        // uncomment below in order to use snapshots
        //mavenRepo "https://oss.sonatype.org/content/groups/public"
    }
    dependencies {
        runtime 'com.github.groovy-wslite:groovy-wslite:1.1.2'
    }
}
  • Configure the clients in grails-app/conf/spring/resources.groovy

For example:

clientBasicAuth(wslite.http.auth.HTTPBasicAuthorization) {
    username = "Aladdin"
    password = "open sesame"
}

httpClient(wslite.http.HTTPClient) {
    connectTimeout = 5000
    readTimeout = 10000
    useCaches = false
    followRedirects = false
    sslTrustAllCerts = true
    // authorization = ref('clientBasicAuth')
    // proxy = myproxy
}

soapClient(wslite.soap.SOAPClient) {
    serviceURL = "http://example.org/soap"
    httpClient = ref('httpClient')
    // authorization = ref('clientBasicAuth')
}

restClient(wslite.rest.RESTClient) {
    url = "http://example.org/services"
    httpClient = ref('httpClient')
    authorization = ref('clientBasicAuth')
}
  • In your controller/service/taglib/etc. you can access the configured client(s) as you would any Grails service.

For example:

package org.example

class MyService {

    def restClient
    def soapClient

    def someServiceMethod() {
        def response = restClient.get()
        ....
    }

    def someOtherServiceMethod() {
        def response soapClient.send { ... }
    }
}

Using with Android

wslite can easily used in an Android-Project, but you need the following in your build.gradle of your android-project:

compile ('org.codehaus.groovy:groovy-json:2.4.3') {
    exclude group: 'org.codehaus.groovy'
}
compile ('org.codehaus.groovy:groovy-xml:2.4.3') {
    exclude group: 'org.codehaus.groovy'
}

in your dependency group. And the following parameters in your Android-Project proguard-rules.pro file:

-keep class wslite.**

Though my proguard-rules.pro file with groovy, SwissKnife and MPCharting library looks like:

-dontwarn org.codehaus.groovy.**
-dontwarn groovy**
-dontwarn com.vividsolutions.**
-dontwarn com.squareup.**
-dontwarn okio.**
-keep class org.codehaus.groovy.vmplugin.**
-keep class org.codehaus.groovy.runtime.**
-keep class groovy.**
-keepclassmembers class org.codehaus.groovy.runtime.dgm* {*;}
-keepclassmembers class ** implements org.codehaus.groovy.runtime.GeneratedClosure {*;}
-keepclassmembers class org.codehaus.groovy.reflection.GroovyClassValue* {*;}

# Don't shrink SwissKnife methods
-keep class com.arasthel.swissknife** { *; }

# Add this for any classes that will have SK injections
-keep class * extends android.app.Activity
-keepclassmembers class * extends android.app.Activity {*;}

-keep class com.github.mikephil.charting.** { *; }
-keep class wslite.**

A small example (with SwissKnife annotations):

@OnBackground
public void fetchContractData(String queryType) {
    try {
        ConnectivityManager cMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE)
        NetworkInfo networkInfo = cMgr.activeNetworkInfo
        if (networkInfo != null && networkInfo.isConnected()) {

            def client = new RESTClient("http://example.org:8080/MyApp/", new HTTPClient())
            client.authorization = new HTTPBasicAuthorization(credUserName, credUserPassword)

            def response = client.get(path: '/api/stat/contractAmount', query: [type: queryType])
            if (response.statusCode != 200)
                showErrorSnackbar(response.statusCode, response.statusMessage)
            else
                showDataInView(response.json)
        } else
            showErrorSnackbar("998", "no connection")
    } catch (Exception ex) {
        showErrorSnackbar("999", ex.message)
    }
}
    
@OnUIThread
public void showDataInView(data) {
    data.each { line ->
        ...
    }
}
    
@OnUIThread
public void showErrorSnackbar(code, message) {
    Snackbar.make(<view>, code + ": " + message, Snackbar.LENGTH_LONG).show()
}

Versioning

This project uses [Semantic Versioning] (http://semver.org/).

Building

groovy-wslite uses Gradle for the build process.

Build Instructions

  1. Fetch the latest code: git clone git://github.com/jwagenleitner/groovy-wslite.git
  2. (Optional) Run the unit tests using gradlew test
  3. (Optional) Run the integration tests using gradlew integrationTest
  4. (Optional) Run the code quality checks gradlew codenarcMain codenarcTest
  5. Go to the project directory and run: gradlew jar

You will find the built jar in ./build/libs.

groovy-wslite's People

Contributors

alvarosanchez avatar d10xa avatar glaforge avatar jacogr avatar jfaissolle avatar jwagenleitner avatar lstaples avatar marsla avatar mbarretta avatar namuol avatar nickkalgin avatar pledbrook avatar susannej avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

groovy-wslite's Issues

Build failure - Could not find property 'pgpSecretKeyRingFile'

Following the basic instructions from the README, I am unable to build groovy-wslite's jar file.

Here's the brief version of the error message:

FAILURE: Build failed with an exception.

* Where:
Build file '/tmp/groovy-wslite/build.gradle' line: 46

* What went wrong:
A problem occurred evaluating root project 'groovy-wslite'.
Cause: Could not find property 'pgpSecretKeyRingFile' on 
       root project 'groovy-wslite'.

I've posted detailed output (from running gradle jar --info --debug --stacktrace) to this gist.

I Cant use nested header" and "body" tags within the main body tag

For example when I try to create the following service, the tags within body and head are not rendered.

    ...

    def soapClient

    def sendSms(args) {

        def response = soapClient.send(
                SOAPAction: 'urn:servicioFrontera#ejecutar',
                connectTimeout:5000,
                readTimeout:10000,
                useCaches:false,
                followRedirects:false,
                sslTrustAllCerts:true ) {
                    version SOAPVersion.V1_1        // SOAPVersion.V1_1 is default
                    soapNamespacePrefix "SOAP"      // "soap-env" is default
                    encoding "ISO-8859-1"           // "UTF-8" is default encoding for xml
                    body {
                        ejecutar( 'xmlns:mns':'urn:servicioFrontera') {
                            xmlOrder(){
                                order{

                                     header{
                                                                          }
 body{
                                                                          }
                                    }
                                }
                            }
                        }
                    }
                }
 ...
 ...

Thank you.

JSON builder does not handle properly GStrings

When post'ing JSON data, looks like the builder only allows String values.

The following fails with a StackOverflowException

def value =  "a"
client.post() {
    json param: value
}

The following works:

def value =  "a"
client.post() {
    json param: value.toString()
}

Unable to Restfully Post String of XML content.

So I recently came across your package and have found using it to GET XML content. Now I am starting to test out the POST and can not get past this basic post function. Any ideas on what I might be doing incorrectly? Currently I am using version 0.5.2.

String post(String myXML) throws Exception {

    def client 

    println this.url + this.path2
    println myXML
    try {
        client = new RESTClient(this.url + this.path2)
        client.authorization = new HTTPBasicAuthorization(this.username, this.password)

        def response = client.post() {
            text myXML
        }

        return response.contentAsString
    } catch (Exception e) {
        println e.message
        return null
    }

}

When I attempt to run this I get

No signature of method: wslite.rest.RESTClient.post() is applicable for argument types: (Moodle.SchoolInfo$_post_closure1) values: [Moodle.SchoolInfo$_post_closure1@7846a55e]
Possible solutions: post(groovy.lang.Closure), post(java.util.Map, groovy.lang.Closure), put(groovy.lang.Closure), wait(), get(), wait(long)
null

Having a problem with using groovy-wslite in grails application.

Hi, I am writing a Grails application to access a SOAP web service and made the decision
to use groovy-wslite. I have been able to use groovy and get this to work, however I have
had nothing but problems trying to integrate this into my grails app.
I am using Grails 2.1.0, groovy-wslite:0.7.1, java 1.6

Here is what I have done:

  1. This is a maven app, so I put the dependency in the maven pom.xml file
com.github.groovy-wslite groovy-wslite 0.7.1 2. I added the exact code from the github site sample into the resources.groovy file and tweeked the service endpoint. 3. I wrote a view, controller and service that work together to put a key number in the request xml for the soap call. 4. In the service I used def soapClient 5. When I try to invoke the soapClient.send(servicerequest) method it errors out with "Cannot invoke method send() on null object"

Now this works in the groovy console perfectly fine. I tried adding the runtime dependency to
the BuildConfig.groovy file. Didn't help.

Any ideas would be really helpful!!

[Fatal Error] :1:1: Content is not allowed in prolog.

Hi, I'm having some issues calling the Marketo SOAP api. I'm getting an "[Fatal Error] :1:1: Content is not allowed in prolog." error no matter how I format the XML, I have used the MarkupBuilder along with a String format. For other calls to the Marketo API I found that the String format works where using the MarkupBuilder does not. But this could be a issue with how I'm building the XML.

I have tested the call in SoapUI 4.5.1 and it works fine.

I have also tried this in both the Releases and Snapshots

endpoint is "https://na-q.marketo.com/soap/mktows/1_8"
WSDL is the end point address with "?WSDL" at the end.

My Groovy Version is "2.0.1 JVM: 1.6.0_35 Vendor: Apple Inc. OS: Mac OS X"

def response = client.send(
"""<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mkt="http://www.marketo.com/mktows/">
   <soapenv:Header>
      <mkt:AuthenticationHeader>
         <mktowsUserId>${userID}</mktowsUserId>
         <requestSignature>${requestSignature}</requestSignature>
         <requestTimestamp>${requestTimestamp}</requestTimestamp>
      </mkt:AuthenticationHeader>
   </soapenv:Header>
   <soapenv:Body>
      <mkt:paramsRequestCampaign>
         <source>MKTOWS</source>
         <leadList>
            <leadKey>
               <keyType>EMAIL</keyType>
               <keyValue>${email}</keyValue>
            </leadKey>
         </leadList>
         <programName>Test Program</programName>
         <campaignName>Test Campaign</campaignName>
         <programTokenList>
            <attrib>
               <name>test</name>
               <value>9</value>
            </attrib>
         </programTokenList>
      </mkt:paramsRequestCampaign>
   </soapenv:Body>
</soapenv:Envelope>"""
)

Any help would be great!

-Thanks!

IBM JVM on AIX gets StackOverflowError

Replicating code:

import wslite.soap.SOAPClient
SOAPClient soapClient = new SOAPClient('http://localhost')
println soapClient.send() {}

Result:

Sending request...
Caught: java.lang.StackOverflowError
at wslite.http.HTTPHeaderMap.getKeyIgnoreCase(HTTPHeaderMap.groovy:44)
at wslite.http.HTTPHeaderMap.this$5$getKeyIgnoreCase(HTTPHeaderMap.groovy)
at wslite.http.HTTPHeaderMap.put(HTTPHeaderMap.groovy:26)
at wslite.http.HTTPHeaderMap.put(HTTPHeaderMap.groovy:30)
at wslite.http.HTTPHeaderMap.put(HTTPHeaderMap.groovy:30)
...
at wslite.http.HTTPHeaderMap.put(HTTPHeaderMap.groovy:30)
at wslite.http.HTTPHeaderMap.put(HTTPHeaderMap.groovy:30)
at wslite.http.HTTPHeaderMap.setProperty(HTTPHeaderMap.groovy)
at wslite.soap.SOAPClient.setContentTypeHeaderIfNotPresent(SOAPClient.groovy:144)
at wslite.soap.SOAPClient.this$2$setContentTypeHeaderIfNotPresent(SOAPClient.groovy)
at wslite.soap.SOAPClient.buildHTTPRequest(SOAPClient.groovy:76)
at wslite.soap.SOAPClient.this$2$buildHTTPRequest(SOAPClient.groovy)
at wslite.soap.SOAPClient.send(SOAPClient.groovy:56)
at wslite.soap.SOAPClient.send(SOAPClient.groovy:44)
at wslite.soap.SOAPClient.send(SOAPClient.groovy)
at test.run(test.groovy:5)

Is not a problem with Sun JVM (cannot be used on AIX of course) or if run from the Groovy source instead of the jar distribution.

I must confess to be using Groovy 1.7.5 since that is what is packaged with Grails 1.3.5. Does it really require Groovy 1.7.6 or better and could that be the problem? If so that means groovy-wslite can only be used with the latest version of Grails (1.3.7), doesn't it?

Debug SOAP requests/responses

In the src I see all requests are generated on memory and not saved in SOAPClient fields, but for debug purposer sometimes you need to see the raw request and response.

I would suggest to add these fields so one can inspect them after the .send() to check for problems.

What do you think?

Thanks for this great tool!

SSL truststore files that do not exist is not being handled correctly

@Grab(group='com.github.groovy-wslite', module='groovy-wslite', version='0.5.2')
import wslite.rest.*

try {
    def client = new RESTClient("https://www.google.com/")
    client.httpClient.sslTrustStoreFile = "c:/temp/keystore_that_does_not_exist.jks"
    def response = client.get()
} catch (ex) {
    println ex
}

This returns wslite.rest.RESTClientException: Cannot invoke method disconnect() on null object.

Calls to SOAPClient.send() remove values from the params map argument

SOAPClient#buildHTTPRequest modifies (removes) values passed in the params map to SOAPClient#send. The key SOAPAction is being removed and this would cause problems for callee's that want to reuse the params.

See RESTClient where we make a defensive copy first.

Here's a test case to show the problem:

@GrabResolver(name='groovy-wslite', root='https://oss.sonatype.org/content/groups/public', m2Compatible=true)
@Grab(group='com.github.groovy-wslite', module='groovy-wslite', version='0.2-SNAPSHOT', changing=true)
import wslite.soap.*

def myParams = [SOAPAction:'http://www.27seconds.com/Holidays/US/Dates/GetMartinLutherKingDay', 
                connectTimeout: 20000]

println "myParams before: ${myParams}"

def soapClient = new SOAPClient('http://www.holidaywebservice.com/Holidays/US/Dates/USHolidayDates.asmx')
def resp = soapClient.send(myParams) {
    body {
        GetMartinLutherKingDay('xmlns':'http://www.27seconds.com/Holidays/US/Dates/') {
            year(2011)
        }
    }
}

println "myParams after: ${myParams}"

assert "2011-01-15T00:00:00" == resp.GetMartinLutherKingDayResponse.GetMartinLutherKingDayResult.text()
assert 200 == resp.httpResponse.statusCode
assert myParams.SOAPAction == 'http://www.27seconds.com/Holidays/US/Dates/GetMartinLutherKingDay'
println "done"

setSoapActionHeaderIfNotPresent treats the empty string same as null, result is no SOAPAction header gets sent. invocation fails.

Hi.

I am trying to talk to a web service that insists on having SOAPAction header set.. when i invoke via SOAPui i see this
header value:

SOAPAction:

with soap UI there is no value for the header, but the header is there nonetheless.

I wanted to replicate this by sending raw xml to the web svc via ws lite. I used the version of SOAPClient.send() that takes a parameter map and a blob of raw XML for the soap input msg... like this >

def response = client.send(       [SOAPAction: '' ],     xmlRequest  ) 

However, i ran into what seems like a bug in SOAPClient.setSoapActionHeaderIfNotPresent () -- This
method treats the empty string same as null, And the result is no SOAPAction header gets sent when an invocation is made.
This causes the server i am communicating to choke and send me back an error response.

I needed to send the header so I modified the method as shown below. I'm sorry I don't have time to create a full patch, but I'm hoping the fix I am suggesting will make it into your code base some how. Thanks in advance - Chris

the fix <<<<

private void setSoapActionHeaderIfNotPresent(HTTPRequest httpRequest, SOAPVersion soapVersion, String soapAction) {

    // if (!soapAction) {       // <<<< --- i changed this .. to the line below
    if (soapAction == null) {
        return
    }
    if (soapVersion == SOAPVersion.V1_1) {
        if (!httpRequest.headers[SOAP.SOAP_ACTION_HEADER]) {
            httpRequest.headers[SOAP.SOAP_ACTION_HEADER] = soapAction
        }
    } else if (soapVersion == SOAPVersion.V1_2) {
        httpRequest.headers[HTTP.CONTENT_TYPE_HEADER] += '; ' + SOAP.SOAP_ACTION_V12_HEADER + '="' + soapAction + '"'
    }
}

EU VAT changes

The EU has changed its WSDL to a new address but now I am getting a 'wslite.soap.SOAPMessageParseException: Root element is definitions, expected Envelope
' error message but am unable to see how to rectify this...

proxy = new SOAPClient("http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl")
rate = proxy.send(SOAPAction:'http://ec.europa.eu/taxation_customs/vies/checkVatService'){
body('xmlns':'urn:ec.europa.eu:taxud:vies:services:checkVat:types'){
checkVat{
countryCode(cc)
vatNumber(vv)
}
}
}

Any pointers??

Increase MaxConnections value

I can't find a forum or anything for discussing usage, so I'll start here. If there is a better place to post this, please close it and redirect me to the right place.

I have an application where I am using wslite to make a connection from my application to a backend web services enabled application. The default 2 connections per host is a huge bottleneck for me and I am looking to change it.

All of the examples I have seen show setting the maxTotal and maxPerRoute settings on the connection manager and then assigning that to the httpClient.

I believe I can instantiate my own httpClient and tell wslite to use it, but is there any simple way to change those properties with the default SoapClient definition?

Thanks for the help!

Error on multipart response in SOAP WS

I want to call a SOAP WebService that returns the response in format multipart/related.
This results in a SOAPMessageParseException telling me that "Content Is Not Allowed In Prolog".

I had a look at the sources of SOAPClient.groovy and think this is maybe because it just calls:

        String soapMessageText = httpResponse.contentAsString
        def soapEnvelope = parseEnvelope(soapMessageText)

getContentAsString() seems to return the raw HTTP body.

Is there a way to attach a file to a POST

I'm trying to do a post to a service, and I have to pass both parameters and a file attachement. I'm having a hard time seeing how to do that. Is that possible?

I'm using the REST portion of the API.

Auto-detect SOAP Version for SOAPClient.send(String) calls

Rather than assume v1.1 when strings are passed to SOAPClient.send(), the method should auto-detect the soap version based on the namespaceURI of the root element (envelope). The client can still override using the SOAPClient.send(SOAPVersion, String) method.

Exception when service returns double quote-wrapped charset

service returns a content type of text/xml;charset="utf-8", which is causing an UnsupportedEncodingException. The double quotes are not being chopped off in the HTTP.parseCharsetParamFromContentType() method before being passed to the 'new String()' method in HttpResponse.getContentAsString()

When given a 204 (No Content) response, there's a fatal error

[Fatal Error] :-1:-1: Premature end of file.
17:13:12.858 [pool-1-thread-1] ERROR c.r.i.fileService.GroovyFileService - Unrecoverable error occured whilst trying to upload file to cloud files!
wslite.rest.RESTContentParseException: Premature end of file.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.6.0_32]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) ~[na:1.6.0_32]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) ~[na:1.6.0_32]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513) ~[na:1.6.0_32]
    at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:77) ~[groovy-all-1.8.5.jar:1.8.5]
    at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:102) ~[groovy-all-1.8.5.jar:1.8.5]
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:54) [groovy-all-1.8.5.jar:1.8.5]
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:182) [groovy-all-1.8.5.jar:1.8.5]
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:202) [groovy-all-1.8.5.jar:1.8.5]
    at wslite.rest.RESTClient.buildResponse(RESTClient.groovy:101) ~[groovy-wslite-0.7.0.jar:na]
    at wslite.rest.RESTClient.this$2$buildResponse(RESTClient.groovy) ~[groovy-wslite-0.7.0.jar:na]
    at wslite.rest.RESTClient$this$2$buildResponse.callCurrent(Unknown Source) ~[na:na]
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46) [groovy-all-1.8.5.jar:1.8.5]
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133) [groovy-all-1.8.5.jar:1.8.5]
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:145) [groovy-all-1.8.5.jar:1.8.5]
    at wslite.rest.RESTClient.executeMethod(RESTClient.groovy:83) ~[groovy-wslite-0.7.0.jar:na]
    at wslite.rest.RESTClient.this$2$executeMethod(RESTClient.groovy) ~[groovy-wslite-0.7.0.jar:na]
    at wslite.rest.RESTClient$this$2$executeMethod$0.callCurrent(Unknown Source) ~[na:na]
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46) [groovy-all-1.8.5.jar:1.8.5]
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133) [groovy-all-1.8.5.jar:1.8.5]
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:149) [groovy-all-1.8.5.jar:1.8.5]
    at wslite.rest.RESTClient.executeMethod(RESTClient.groovy:61) ~[groovy-wslite-0.7.0.jar:na]
    at wslite.rest.RESTClient.this$2$executeMethod(RESTClient.groovy) ~[groovy-wslite-0.7.0.jar:na]
    at wslite.rest.RESTClient$this$2$executeMethod.callCurrent(Unknown Source) ~[na:na]
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46) [groovy-all-1.8.5.jar:1.8.5]
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133) [groovy-all-1.8.5.jar:1.8.5]
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:145) [groovy-all-1.8.5.jar:1.8.5]
    at wslite.rest.RESTClient.get(RESTClient.groovy:45) ~[groovy-wslite-0.7.0.jar:na]
    at wslite.rest.RESTClient$get.call(Unknown Source) ~[na:na]
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42) [groovy-all-1.8.5.jar:1.8.5]
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108) [groovy-all-1.8.5.jar:1.8.5]
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116) [groovy-all-1.8.5.jar:1.8.5]

The code doesn't check to see if there is any content and so the XMLSlurper logic in the ResponseBuilder object dies a horrible death. Checking to see if there's any content at all would be a good first bet.

Logging

Provide a way to inject a logger so we don't have to add a dependency. Need to take a close look at the new Groovy @Log annotation. Out of the box we should probably default to a null logger and provide a stdout logger, but allow user to inject their own logger.

Add cookie support for Session-based WS

WS which are session-based (multi-operation with connect first and without token) are not handled by this library

If the HTTP library handled cookies, that would enable users using this kind of WS

EX : I have to connect to a SOAP webservice which has a Connect method which is to call first
subsequent calls to other operations trigger SOAPFault : "you are not connected"

Ability to set a default soap header that will be sent with each request

Might be useful to be able to set a default SOAP Header on a client. Some services have a login, then in future requests they expect a custom header be sent containing the credentials/token.

def soapClient = new SOAPClient(url:"https://...")
....
soapClient.defaultSOAPHeader(...)

Should provide a switch to turn off sending the header on a request by request basis.

Proxy example documentation error and suggested addition.

The home page examples have a minor problem with the proxy explanation.

First, there should be another closing parenthesis on the proxy line:

def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress('proxy.example.com', 8080)

Should be:

def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress('proxy.example.com', 8080))

In addition, this will not work if the proxy requires authentication, which is very poorly documented for the Java platform in general, so it would probably be a good idea to add the following:

Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new
PasswordAuthentication("username","password".toCharArray());
}})

SOAPResponse needs methods for accessing the soap message it wraps

The following is code from the SOAPClient. The SOAPResponse should have methods to make this type of access easier.

if (!soapResponse.Envelope.Body.Fault.isEmpty()) {
        def soapFault = buildSOAPFaultException(soapResponse.Envelope.Body.Fault)

A good start would be:

boolean hasFault()
GPathResult getFault() 
GPathResult getHeader()
GPathResult getBody()

Trouble with Keystores

Hi!

I love wslite. I am not trying to connect to a keystone that requires client authentication and when I specify sslKeystoreFile etc and whether or not I send it in on the send() call with a map or use System.setProperty(), I keep getting the following error:

sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I am using Grails 1.3.7 and running on amazon elastic beanstalk but this error is actually happening on my development machine.

Would you have any ideas about how to fix/where to put the .jks files (preferably somewhere in the war file so I can upload into the EBS and not have to rebuild my site's environment using a custom image.)

THANKS!

sun.net.www.http.PosterOutputStream no such property bytes

See http://groovy.329449.n5.nabble.com/Groovy-WSLite-SOAP-Request-Issue-Urgent-tp5710008.html.

I am using Groovy-WSLite 0.7.0 to send a soap request. However when I invoke client.send method regardless the args that I used in this method, it always returned the following error.

wslite.soap.SOAPClientException: 200 OK -- 200 OK -- 200 OK -- No such property: bytes for class: sun.net.www.http.PosterOutputStream

I used the following code.

 def client = new SOAPClient('http://rvwpremapp01:8080/arsys/WSDL/public/rvwpremapp01/HPD_IncidentInterface_Create_WS_App') 

   def response=client.send("""<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'  

xmlns:urn='urn:HPD_IncidentInterface_Create_WS_App'><soapenv:Header><urn:AuthenticationInfo><urn:userName>Allen1</urn:userName>        

<urn:password></urn:password></urn:AuthenticationInfo></soapenv:Header><soapenv:Body><urn:HelpDesk_Submit_Service>      

<urn:First_Name>test</urn:First_Name><urn:Impact>1-Extensive/Widespread</urn:Impact><urn:Last_Name>user1</urn:Last_Name>        

<urn:Reported_Source>Other</urn:Reported_Source><urn:Service_Type>User Service Request</urn:Service_Type><urn:Status>New</urn:Status>        

<urn:Action>Further Investigation</urn:Action><urn:Summary>Test</urn:Summary>        

<urn:Urgency>1-Critical</urn:Urgency><urn:Work_Info_Date>2012-05- 

31T13:00:00</urn:Work_Info_Date></urn:HelpDesk_Submit_Service></soapenv:Body></soapenv:Envelope>""") 

Also if I tried to use

@Grab(group='com.github.groovy-wslite', module='groovy-wslite', version='0.7.0') 
import wslite.soap.* 

I got the below error, but if I comment out '@Grab...', it works fine on this part, but still can't send request. 

 unexpected token: import @ line 7, column 1. 
   import wslite.soap.* 
   ^ 

1 error 

I only put the Groovy-WSLite jar file into the lib folder for this deployment, not sure if there is anything else that I need to install to make it work.

JSON code should be wrapped rather than modified directly

I'm using the JSON-java library for JSON parsing and have modified it in order to provide a Map interface to JSONObject and List interface to JSONArray. Instead of modifying the code directly it should be wrapped with wrapper classes that implement the correct interface to make updating to the latest lib version easier.

Xml tags built-in?

This may not be an issue with wslite but instead my lack of familiarity.

I'm working with a SSL-guarded web service. For the method, it demands an appropriate namespace.. There is documentation for that. For the parameters, it demands an empty string xmlns. Without it, the method fails. Using wslite syntax, is it possible to make this call...or do I have to feed raw xml?

Complex types as parameters

There is documentation on submitting simple data types (strings, booleans, etc) as parameters. What about objects, based on classes with subclasses. Does this need to be broken down into simple data types, all the way down through the hierarchy? If it's possible, what does the syntax look like?

SOAPClient not handling character encoding correctly

SOAP messages are encoded to bytes using the system default encoding. This is causing issues for systems that do not have their encoding set to UTF-8. Currently, the Content-Type header charset is harded to UTF-8. Need to allow for handling character encodings when encoding is specified in the closure or if the user passed a Content-Type header with a charset parameter.

Error handling OneWay WebService method call

While trygin to invoke a Oneway method on WebService endpoint I got the following exception:

[Fatal Error] :1:1: Premature end of file.
Caught: wslite.soap.SOAPMessageParseException: Premature end of file.
wslite.soap.SOAPMessageParseException: Premature end of file.
at wslite.soap.SOAPClient.buildSOAPResponse(SOAPClient.groovy:92)
at wslite.soap.SOAPClient.this$2$buildSOAPResponse(SOAPClient.groovy)
at wslite.soap.SOAPClient$this$2$buildSOAPResponse.callCurrent(Unknown Source)
at wslite.soap.SOAPClient.send(SOAPClient.groovy:63)
at wslite.soap.SOAPClient$send$0.callCurrent(Unknown Source)
at wslite.soap.SOAPClient.send(SOAPClient.groovy:44)
at wslite.soap.SOAPClient.send(SOAPClient.groovy)
at wslite.soap.SOAPClient$send.call(Unknown Source)
at au.com.optus.mcas.ws.client.email.SendEmail.run(SendEmail.groovy:43)
Caused by: org.xml.sax.SAXParseException: Premature end of file.
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1231)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
at wslite.soap.SOAPClient.parseEnvelope(SOAPClient.groovy:98)
at wslite.soap.SOAPClient.this$2$parseEnvelope(SOAPClient.groovy)
at wslite.soap.SOAPClient$this$2$parseEnvelope.callCurrent(Unknown Source)
at wslite.soap.SOAPClient.buildSOAPResponse(SOAPClient.groovy:86)

... 8 more

The call to the webservice does take place and completes successful but the SOAP client tries to read a response regardless.

I have uploaded a standalone test harness that can be used to troubleshoot this issue to the following location:
https://www.box.com/s/e31499a522cc8d78a05f

IncompatibleClassChangeError issue

When trying to create a simple soap based webservice using grails following the
Mother's day example as shown, I recieve a IncompatibleClassChangeError as shown:

Stacktrace follows:
org.codehaus.groovy.grails.web.servlet.mvc.exceptions.ControllerExecutionException: Executing action [failoverServer] of controller [net.sococo.serverconfig.FailoverServerController] caused exception: java.lang.IncompatibleClassChangeError: the number of constructors during runtime and compile time for java.lang.Exception do not match. Expected 4 but got 5
at java.lang.Thread.run(Thread.java:722)
Caused by: org.codehaus.groovy.runtime.InvokerInvocationException: java.lang.IncompatibleClassChangeError: the number of constructors during runtime and compile time for java.lang.Exception do not match. Expected 4 but got 5
... 1 more
Caused by: java.lang.IncompatibleClassChangeError: the number of constructors during runtime and compile time for java.lang.Exception do not match. Expected 4 but got 5
at wslite.http.HTTPClientException.(HTTPClientException.groovy:29)
at wslite.soap.SOAPClientException.(SOAPClientException.groovy:28)
at wslite.soap.SOAPClient.send(SOAPClient.groovy:61)
at wslite.soap.SOAPClient$send$0.callCurrent(Unknown Source)
at wslite.soap.SOAPClient.send(SOAPClient.groovy:48)
at wslite.soap.SOAPClient.send(SOAPClient.groovy)
at wslite.soap.SOAPClient$send.call(Unknown Source)
at net.sococo.serverconfig.FailoverServerController$_closure1.doCall(FailoverServerController.groovy:21)
at net.sococo.serverconfig.FailoverServerController$_closure1.doCall(FailoverServerController.groovy)

I wasnt sure where else to post this, please help with this issue that is occuring.

david

RESTClient defaults

RESTClient should provide default settings for accept and content-type (for request). If these header values are not provided in the request these defaults should be applied.

There should also be a default for charset that will effect string to byte conversions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.