Missing classes of HttpBuilder in Groovy - groovy

Here is simple request I try to do and watch response
def httpReq = new HTTPBuilder("http://${url}")
httpReq.request(Method.GET, ContentType.JSON) {
response.success = { resp ->
println("Ok " + resp.status.toString())
}
response.failure = { resp ->
println("Not ok" + resp.status.toString())
}
This returns an Error:
java.lang.ClassNotFoundException: org.apache.commons.collections.iterators.ArrayIterator
I think that ArrayIterator defined in jdk. I added manually org.apache.commons:commons-collections4:4.4 but it doesn't help.

TL;DR
Don't waste your time by gathering deps. Use a build tool like Gradle
or Maven - or use Groovys Grapes if only a script is needed and Groovy
is installed (or easily installable) on your target.
Using grape
You have to pick up all the transitive dependencies (this means the correct packages with the correct versions). E.g. with #Grab:
#Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7.1')
import groovyx.net.http.HTTPBuilder
def http = new HTTPBuilder('http://www.google.com')
def html = http.get( path : '/search', query : [q:'Groovy'] )
If you really want to gather all the deps manually grape can also
help. It can tell you, what jars are needed:
% grape resolve org.codehaus.groovy.modules.http-builder http-builder 0.7.1
$HOME/.groovy/grapes/org.codehaus.groovy.modules.http-builder/http-builder/jars/http-builder-0.7.1.jar
$HOME/.groovy/grapes/org.apache.httpcomponents/httpclient/jars/httpclient-4.2.1.jar
$HOME/.groovy/grapes/org.apache.httpcomponents/httpcore/jars/httpcore-4.2.1.jar
$HOME/.groovy/grapes/commons-logging/commons-logging/jars/commons-logging-1.1.1.jar
$HOME/.groovy/grapes/commons-codec/commons-codec/jars/commons-codec-1.6.jar
$HOME/.groovy/grapes/net.sf.json-lib/json-lib/jars/json-lib-2.3-jdk15.jar
$HOME/.groovy/grapes/commons-beanutils/commons-beanutils/jars/commons-beanutils-1.8.0.jar
$HOME/.groovy/grapes/commons-collections/commons-collections/jars/commons-collections-3.2.1.jar
$HOME/.groovy/grapes/commons-lang/commons-lang/jars/commons-lang-2.4.jar
$HOME/.groovy/grapes/net.sf.ezmorph/ezmorph/jars/ezmorph-1.0.6.jar
$HOME/.groovy/grapes/net.sourceforge.nekohtml/nekohtml/jars/nekohtml-1.9.16.jar
$HOME/.groovy/grapes/xerces/xercesImpl/jars/xercesImpl-2.9.1.jar
$HOME/.groovy/grapes/xml-apis/xml-apis/jars/xml-apis-1.3.04.jar
$HOME/.groovy/grapes/xml-resolver/xml-resolver/jars/xml-resolver-1.2.jar
From this list you can build up your own classpath to pass to groovy and
work without grape. E.g.:
% cat no-grape.groovy
import groovyx.net.http.HTTPBuilder
def http = new HTTPBuilder('http://www.google.com')
def html = http.get( path : '/search', query : [q:'Groovy'] )
% groovy -cp `grape resolve org.codehaus.groovy.modules.http-builder http-builder 0.7.1 | paste -s -d:` no-grape.groovy
...

Related

Compile Groovy Script from command prompt which contains soapui libraries

I am trying to create a script library and compile a groovy class as described in https://stackoverflow.com/a/35498212/9997207
Groovy Script
import groovy.json.*
import com.eviware.soapui.*
class ScriptLibrary {
def context
def testRunner
def log
def boolean setHeaderValues(userId, password){
try{
loginTestStep = testRunner.testCase.testSuite.testCases["SetHeaderParameters"].testSteps["SetHeaderParametersJsonRequest"]
def request = loginTestStep.getPropertyValue("Request").toString()
def jsonReq = new JsonSlurper().parseText(request);
def builder = new JsonBuilder(jsonReq)
builder.content.userId=userId
builder.content.password=password
def jsonReqAsString = JsonOutput.toJson(jsonReq)
loginTestStep.setPropertyValue("Request",jsonReqAsString)
def contextJsonRequest = new WsdlTestRunContext(loginTestStep);
loginTestStep.run(testRunner,contextJsonRequest)
def response = loginTestStep.getPropertyValue("Response").toString()
def jsonResponse = new JsonSlurper().parseText(response);
def accessTokenFromResponse = jsonResponse.accessToken.toString()
def userPermissionFromResponse = jsonResponse.userPermissionIds.toString()
def userIdFromResponse = jsonResponse.userId.toString()
testRunner.testCase.testSuite.project.setPropertyValue("HEADER_USER_ID", userIdFromResponse)
testRunner.testCase.testSuite.project.setPropertyValue("HEADER_USER_PERMISSION", userPermissionFromResponse)
testRunner.testCase.testSuite.project.setPropertyValue("HEADER_ACCESS_TOKEN", accessTokenFromResponse)
log.info "Header set with values "+userIdFromResponse+":::"+userPermissionFromResponse+":::"+accessTokenFromResponse
setHeader = true
}
return setHeader
}
catch (Exception ex) {
log.info "Header Not Set " +ex
setHeader = false
testRunner.testCase.testSuite.project.setPropertyValue("HEADER_USER_ID", "")
testRunner.testCase.testSuite.project.setPropertyValue("HEADER_USER_PERMISSION", "")
testRunner.testCase.testSuite.project.setPropertyValue("HEADER_ACCESS_TOKEN", "")
return setHeader
}
}
}
Getting following compilation error while trying to compile the groovy script from the command prompt
C:\Path\apache-groovy-binary-2.5.1\groovy-2.5.1\bin\GroovyScripts>groovy ScriptLibrary.groovy
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
C:\Path\apache-groovy-binary-2.5.1\groovy-2.5.1\bin\GroovyScripts\ScriptLibrary.groovy: 20: unable to resolve class WsdlTestRunContext
# line 20, column 26.
def contextJsonRequest = new WsdlTestRunContext(loginTestStep);
^
1 error
You have to include soupui-{version}.jar file in the classpath to resolve this dependency issue. You can find it in SoapUI-{version}/bin folder. Let's say that SoapUI 5.4.0 is located in /tmp/SoapUI-5.4.0/. In this case I can compile a script with following command:
groovyc -d classes -cp ".:/tmp/SoapUI-5.4.0/bin/soapui-5.4.0.jar" script.groovy
Keep in mind that this command is run from the folder where script.groovy is located and compiled class can be found in ./classes/script.class

Using commons-vfs sync ant task from groovy

Trying to use the commons-vfs sync ant task from Groovy. Solved most of the things, but still having some issues. Here is my groovy script:
#Grapes([
#Grab(group='org.apache.commons', module='commons-vfs2', version='2.0'),
#Grab(group='com.jcraft', module='jsch', version='0.1.53'),
#GrabConfig(systemClassLoader = true)
])
import groovy.xml.NamespaceBuilder
import groovy.io.FileType
localRootDir = 'forUpdateSite'
updateServer = 'some.remote.server.com'
remoteRootDir = '/var/www/directory'
println("Syncing files from ${localRootDir} to ${updateServer} ${remoteRootDir}");
def ant = new AntBuilder()
def vfs = NamespaceBuilder.newInstance(ant, 'antlib:org.apache.commons.vfs2.tasks')
def remoteURI = "sftp://username:{FAKEENCRYPTEDPASSWORD}#${updateServer}${remoteRootDir}"
vfs.sync (destdir: remoteURI) {
src() {
file: localRootDir
}
}
At this point the only thing I am missing is how to specify the local directory and files. This example gives me this stack trace:
Syncing files from forUpdateSite to some.remote.server.com /var/www/directory
Caught: : No source file specified.
: No source file specified.
at org.apache.commons.vfs2.tasks.AbstractSyncTask.addConfiguredSrc(AbstractSyncTask.java:149)
at org.apache.tools.ant.IntrospectionHelper$AddNestedCreator.istore(IntrospectionHelper.java:1469)
at org.apache.tools.ant.IntrospectionHelper$AddNestedCreator.store(IntrospectionHelper.java:1463)
at org.apache.tools.ant.IntrospectionHelper$Creator.store(IntrospectionHelper.java:1370)
at org.apache.tools.ant.UnknownElement.handleChild(UnknownElement.java:582)
at org.apache.tools.ant.UnknownElement.handleChildren(UnknownElement.java:349)
at org.apache.tools.ant.UnknownElement.configure(UnknownElement.java:201)
at org.apache.tools.ant.UnknownElement.maybeConfigure(UnknownElement.java:163)
at syncToUpdateSite.run(syncToUpdateSite.groovy:53)
Turned out to be pretty simple:
#Grapes([
#Grab(group='org.apache.commons', module='commons-vfs2', version='2.0'),
#Grab(group='com.jcraft', module='jsch', version='0.1.53'),
#GrabConfig(systemClassLoader = true)
])
import groovy.xml.NamespaceBuilder
import groovy.io.FileType
localRootDir = 'forUpdateSite'
updateServer = 'some.remote.server.com'
remoteRootDir = '/var/www/directory'
println("Syncing files from ${localRootDir} to ${updateServer} ${remoteRootDir}");
def ant = new AntBuilder()
def vfs = NamespaceBuilder.newInstance(ant, 'antlib:org.apache.commons.vfs2.tasks')
def remoteURI = "sftp://username:{FAKEENCRYPTEDPASSWORD}#${updateServer}${remoteRootDir}"
vfs.sync (destdir: remoteURI,
src: localRootDir)
Note that you have to include the jsch module with #Grab for the sftp URL parsing to work. I was getting the stack trace below before I included that.
Caught: : Badly formed URI "sftp://username:***#some.remote.server.com/var/www/directory".
: Badly formed URI "sftp://username:***#some.remote.server.com/var/www/directory".
at org.apache.commons.vfs2.tasks.AbstractSyncTask.execute(AbstractSyncTask.java:227)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at syncToUpdateSite.run(syncToUpdateSite.groovy:52)
Caused by: org.apache.commons.vfs2.FileSystemException: Badly formed URI "sftp://username:***#some.remote.server.com/var/www/directory".
at org.apache.commons.vfs2.provider.url.UrlFileProvider.findFile(UrlFileProvider.java:91)
at org.apache.commons.vfs2.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:713)
at org.apache.commons.vfs2.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:649)
at org.apache.commons.vfs2.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:636)
at org.apache.commons.vfs2.tasks.VfsTask.resolveFile(VfsTask.java:56)
at org.apache.commons.vfs2.tasks.AbstractSyncTask.handleFiles(AbstractSyncTask.java:247)
at org.apache.commons.vfs2.tasks.AbstractSyncTask.execute(AbstractSyncTask.java:218)
... 3 more
Caused by: java.net.MalformedURLException: unknown protocol: sftp
at org.apache.commons.vfs2.provider.url.UrlFileProvider.findFile(UrlFileProvider.java:72)
... 9 more

How to get testStep responseAsXml in groovyScript

Concerning soapUI and groovy, I'm trying to get assertion (working) and response both in XML into a variable. I get the error
groovy.lang.MissingMethodException: No signature of method: com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep.getResponseAsXml() is applicable for argument types: () values: [] error at line: 6
I have tried adding import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep but still cant figure it. I did another attempt with message exchange, also to no avail - from what i understand you can't actually use messageExchange in this particular instance
import com.eviware.soapui.model.testsuite.Assertable.AssertionStatus
def TestCase = testRunner.getTestCase()
def StepList = TestCase.getTestStepList()
StepList.each
{
if(it.metaClass.hasProperty(it,'assertionStatus'))
{
if(it.assertionStatus == AssertionStatus.FAILED)
{
def ass = it.getAssertableContentAsXml()
def res = it.getResponseContentAsXml()
log.error "${it.name} " + "${it.assertionStatus}"
log.info ass + res
}
}
}
If you want to get the response from com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep, a possible way is first get the testStep from this class using getTestStep() method.
This method returns a object of class com.eviware.soapui.model.testsuite.TestStep, from this object you can get the testSteps properties like request, response, endpoint... using getPropertyValue(java.lang.string) method.
So in your case to get the response use:
def res = it.getTestStep().getPropertyValue('Response')
instead of:
def res = it.getResponseContentAsXml()
As #tim_yates comments the exception description in this case it's pretty clear, so please take a look at the SOAPUI api and at the links provided in the answer for the next time :).
Hope this helps,

Executing a Java jar file from within a SoapUI groovy script not working

I am new to SoapUI and Groovy so please forgive this post as it has been posted a number of times in Stackoverflow however I cannot find a fix.
SoapUI version: 4.5.2
I have 2 questions if you guys don't mind:
I have an executable jar file that I've put in the the \bin\ext directory along with another jar that is considered a dependency jar within the code in the jar so I hope it will reference there. The groovy code I found in Stackoverflow that should execute this jar is as follows but does not work as I don't see any output anywhere in the SoapUI directory.
Here is the code:
def command = "java -jar UpdateAppIdXMLRequest.jar file.xml"
def process = command.execute()
process.waitFor()
def output = process.in.text
log.info output
This jar creates 25 xml files that should be able to be picked up by the SoapUI and put them in as TestSteps in the same project. In my java code in what path do I put these files?
Here is the code in my jar:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
class UpdateAppIdXMLRequest {
static main(args) {
try {
SAXBuilder builder = new SAXBuilder();
File xmlFile = new File("c:\\file.xml");
Document doc = (Document) builder.build(xmlFile);
Element rootNode = doc.getRootElement();
// Create loop to create 25 testStepApps
for (int i = 1; i < 26; i++) {
// Get current AppID, incrementAppID and update the ApplicationNumber attribute value for next test script.
int appID = Integer.parseInt(rootNode.getAttributeValue("ApplicationNumber"));
appID++;
String appIDValue = Integer.toString(appID);
rootNode.getAttribute("ApplicationNumber").setValue(appIDValue);
XMLOutputter xmlOutput = new XMLOutputter();
// Create new XML file with next AppID
xmlOutput.setFormat(Format.getPrettyFormat());
xmlOutput.output(doc, new FileWriter("c:\\testStepApp" + i + ".xml"));
// xmlOutput.output(doc, System.out);
// System.out.println("File updated!");
}
} catch (IOException io) {
io.printStackTrace();
} catch (JDOMException e) {
e.printStackTrace();
}
}
}
Any help/direction would be appreciated.
Thanks.
In order to do so, I recommend that you use directly groovy test step instead of a jar, this way you have more flexibility an you have not recompile the jar each time you must need to change something.
So, in order to achieve your goal, at first you need to create a TestCase inside your project, create a SOAP Test Step and Groovy Test Step inside like this:
I will use SOAP Test Step to create the other test steps (to create test steps it needs the wsdl:operation and so on, and it's more easy to copy the test step that create directly).
In the Groovy Test Step I will put the necessary code to do the work which is showed below:
import com.eviware.soapui.support.XmlHolder
import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestRequestStepFactory
// read your request template
def requestFile = new File("C:/file.xml");
// parse it as xml
def requestXml = new XmlHolder(requestFile.text)
// get the current testCase to add testSteps later
def tc = testRunner.testCase;
// get the testStep as template to create the other requests
def tsTemplate = tc.getTestStepByName("Template");
// loop to create 25 testStep
for(int i = 1; i < 26; i++){
// xpath expression to get applicationNumber attribute in root node
def xpathNodeAttr = "/*/#ApplicationNumber";
// get the root node attribute applicationNumber throught an XPATH
int appId = Integer.parseInt(requestXml.getNodeValue(xpathNodeAttr));
// add 1 to appId
appId++;
// set the value again in the attribute
requestXml.setNodeValue(xpathNodeAttr,appId);
def testStepName = "TestStep_ApplicationNumber_"+ String.valueOf(appId)
log.info testStepName;
log.info testStepName.getClass().getName()
log.info tc.getClass().getName()
// create a new testStepConfig
def testStepFactory = new WsdlTestRequestStepFactory();
def testStepConfig = testStepFactory.createConfig( tsTemplate.getOperation(), testStepName )
// add the new testStep to TestCase
def newTestStep = tc.insertTestStep( testStepConfig, -1 )
// set the request which just create
newTestStep.getTestRequest().setRequestContent(requestXml.getXml())
}
This code it's basically your java code "translated" to groovy and added the necessary code to create the test steps. In a few words this code reads a request from a file, and create 25 test steps in the current test case using the request, in each request it only changes the ApplicationNumber attribute of the root node adding it +1.
EDIT BASED ON COMMENT:
If you use a REST Request step instead of SOAP Request Step you have to change a bit your groovy code to use com.eviware.soapui.impl.wsdl.teststeps.registry.RestRequestStepFactory and getTestRequest() method on it. So if you have a REST Service with a POST method create a Test Case with a REST Request test step and Groovy Test Step like this:
And use this groovy code instead, basically this code it's the same and works like the code above and makes the same thing with REST Request instead of SOAP Request:
import com.eviware.soapui.support.XmlHolder
import com.eviware.soapui.impl.wsdl.teststeps.registry.RestRequestStepFactory
// read your request template
def requestFile = new File("C:/file.xml");
// parse it as xml
def requestXml = new XmlHolder(requestFile.text)
// get the current testCase to add testSteps later
def tc = testRunner.testCase;
// get the testStep as template to create the other requests
def tsTemplate = tc.getTestStepByName("Template");
// loop to create 25 testStep
for(int i = 1; i < 26; i++){
// xpath expression to get applicationNumber attribute in root node
def xpathNodeAttr = "/*/#ApplicationNumber";
// get the root node attribute applicationNumber throught an XPATH
int appId = Integer.parseInt(requestXml.getNodeValue(xpathNodeAttr));
// add 1 to appId
appId++;
// set the value again in the attribute
requestXml.setNodeValue(xpathNodeAttr,appId);
def testStepName = "TestStep_ApplicationNumber_"+ String.valueOf(appId)
log.info testStepName;
log.info testStepName.getClass().getName()
log.info tc.getClass().getName()
// create a new testStepConfig
def testStepFactory = new RestRequestStepFactory();
def testStepConfig = testStepFactory.createConfig( tsTemplate.getTestRequest(), testStepName )
// add the new testStep to TestCase
def newTestStep = tc.insertTestStep( testStepConfig, -1 )
// set the request which just create
newTestStep.getTestRequest().setRequestContent(requestXml.getXml())
}
Hope this helps.

Groovy + Antbuilder: How to use Grape to with taskdef?

This is related to . I'm trying to dynamically add the maven-ant-tasks jars with Grape, simulating this:
<taskdef uri="antlib:org.apache.maven.artifact.ant"
resource="org/apache/maven/artifact/ant/antlib.xml"
classpathref="ant.classpath" />
I've tried to use Grape.grab() to make maven-ant-tasks available to AntBuilder like this:
import groovy.grape.Grape
println "grab..."
Grape.grab(group:'ant', module:'ant', version:'1.7.0', classLoader:this.class.classLoader.rootLoader)
Grape.grab(group: 'org.apache.maven', module: 'maven-ant-tasks', version: '2.0.9')
println "ant taskdef..."
def ant = new AntBuilder()
ant.taskdef (resource: "org/apache/maven/artifact/ant/antlib.xml" )
but that doesn't work because Grape adds the modules to a different ClassLoader from the one that ANT engine is using. So, I took the advice from this AntBuilder classpath question and made Grape use the root ClassLoader:
import groovy.grape.Grape
println "grab..."
Grape.grab(group:'ant', module:'ant', version:'1.7.0', classLoader:this.class.classLoader.rootLoader)
Grape.grab(group: 'org.apache.maven', module: 'maven-ant-tasks', version: '2.0.9', classLoader: this.class.classLoader.rootLoader)
println "ant taskdef..."
def ant = new AntBuilder()
ant.taskdef (resource: "org/apache/maven/artifact/ant/antlib.xml" )
Now it throws a LinkageError:
Caught: : java.lang.LinkageError: loader constraint violation: when resolving overridden method "org.apache.tools.ant.helper.ProjectHelper2$RootHandler.setDocumentLocator(Lorg/xml/sax/Locator;)V" the class loader (instance of org/codehaus/groovy/tools/RootLoader) of the current class, org/apache/tools/ant/helper/ProjectHelper2$RootHandler, and its superclass loader (instance of <bootloader>), have different Class objects for the type org/xml/sax/Locator used in the signature
at test.mavenanttasks.run(mavenanttasks.groovy:11)
Any hints on getting this to work? Or, is the whole thing a bad idea?
I found this: http://groovy.codehaus.org/Using+Ant+Libraries+with+AntBuilder
First, put maven-ant-tasks in the root classloader with:
#Grapes([
#Grab(group = 'org.apache.maven', module = 'maven-ant-tasks', version = '2.1.3'),
#GrabConfig(systemClassLoader = true)
])
Alternatively, for older versions of Groovy:
Grape.grab(group: 'org.apache.maven', module: 'maven-ant-tasks', version: '2.1.3', classLoader: this.class.classLoader.rootLoader)
The Maven ANT tasks are an 'AntLib', and they can be loaded like this:
import groovy.xml.NamespaceBuilder
def ant = new AntBuilder()
def mvn = NamespaceBuilder.newInstance(ant, 'antlib:org.apache.maven.artifact.ant')
We can create ant path(classpath) using java.net.URLClassLoader or it's subclass
eg:
<!-- language: groovy -->
#Grapes([
#Grab(group='org.jacoco', module='org.jacoco.ant', version= '0.7.4.201502262128'),
#Grab(group='org.jacoco', module='org.jacoco.core', version= '0.7.4.201502262128'),
#Grab('org.jacoco:org.jacoco.report:0.7.4.201502262128'),
])
class Tool {
def dump(args){
println "do dump...:$args"
println "DumpTask:"+org.jacoco.ant.DumpTask.classLoader;
def ant = new AntBuilder();
def path1 = ant.path{
org.jacoco.ant.DumpTask.classLoader.getURLs().each {
ant.pathelement(location:it.getFile())
}
}
println "path11:$path1";
// classname way
// ant.taskdef(name:"dump",classname:"org.jacoco.ant.DumpTask",classpath:path1);
// ant.dump(args);
//namespace way
ant.taskdef(uri:'antlib:org.jacoco.ant',resource:'org/jacoco/ant/antlib.xml',classpath:path1);
def jacoco=groovy.xml.NamespaceBuilder.newInstance(ant, 'antlib:org.jacoco.ant')
jacoco.dump(args);
}
}

Resources