Forum Discussion

HP-Plano-TX-Soa's avatar
HP-Plano-TX-Soa
Occasional Contributor
13 years ago

How to create a Groovy JAR file for SoapUI using Eclipse

I need to know the steps required to create an Eclipse-Kepler groovy project for use in soapUI Free. I want to create a JAR file which soapUI Free will import.

I have already created a package of classes called "customScripts", which contains several Groovy scripts. SoapUI Pro picks up this package and uses it, simply by placing the package folder in

the correct soapUI Pro path. But I need to create a JAR file from this identical groovy package, "customScripts", so that I can place the JAR file in the ..../bin/ext/ folder of the soapUI Free

version. This will enable my "customScripts" to be used in that free version of soapUI.

I have installed Eclipse Kepler, and I have added both the Groovy and soapUI plugins. I have created a Groovy project, and placed my "customScripts" Groovy source files in the src directory of

the Project. However, Eclipse complains that the "customScripts" package does not match the Project Package - which is "Default". I note that when I attempt to edit the Project Package, I get a

long drop-down list of Packages, and I am not able to chose the name "customScripts". I have to chose from a predetermined set of packages. These look like Packages that tell the Project what

environment I am wanting to target - like Groovy, or soapUI, and specific variants within that general environment. Maybe I am confused about what the Package needs to be - I am very new to

Java-Groovy JAR file creation.

Can someone provide a tutorial on the simplest way to create a JAR file from my "customScripts" Groovy package, one that soapUI Free will be able to import and use?

18 Replies

  • HP-Plano-TX-Soa's avatar
    HP-Plano-TX-Soa
    Occasional Contributor
    "no such Property - com - for class customScripts...." - hmmmm

    Does this mean that "com" has to be added as a Property to my class? Like "log", "context", "testCase" and "testSuite" are Properties and are included in my constructor? How do I add the com property, since the location from where I am calling this particular TearDown() method doesn't have a "com" Property?

    Somehow, I should be able to tell my custom scripts that com is a valid Property, and I should be able to use com.?? in my scripts.
  • nmrao's avatar
    nmrao
    Community Hero
    Sorry i should have bee little clear while posting my previous response. It was intented to look the relevant class names and existing methods as I felt you were doing some thing related.

    As mentioned in my earlier replies, I could not see the class in any library which you are importing in your teardown script.

    And tried your teardownscript directly in soapui groovy script, could not be run. Do run this script directly in soapui with out any issue? If that works, then it will also work from library, I believe.
  • HP-Plano-TX-Soa's avatar
    HP-Plano-TX-Soa
    Occasional Contributor
    The SoapUI.logMonitor object I am invoking does exist in the source you linked.

    I can directly run the operational code in my Teardown() method, doing so from the soapUI TestCase teardown script, and I get no errors. The com.eviware.soapui.SoapUI.logMonitor object is found, and the logging I ask it to perform works as expected.

    I just tried this again, in the Free version, and it works with no errors at all. All the operational code in my Teardown() method, including the use of the com.eviware.soapui.SoapUI.logMonitor object, works exactly as expected, when I run it directly inside the TestCase Teardown Script.

    But when I try to run it from the JAR file as a method inside a class I get the error that says "com" is not a valid property for the Teardown() method.
  • nmrao's avatar
    nmrao
    Community Hero
    Well, tried again your teardownscript was put in a Test Case's TearDown Script. Note that removed com between , in two places of the script and getting the below exception.


    Mon Aug 19 23:31:04 IST 2013:ERROR:groovy.lang.GroovyRuntimeException: Failed to create Script instance for class: class teardownScripts. Reason: java.lang.InstantiationException: teardownScripts
    groovy.lang.GroovyRuntimeException: Failed to create Script instance for class: class teardownScripts. Reason: java.lang.InstantiationException: teardownScripts
    at org.codehaus.groovy.runtime.InvokerHelper.createScript(InvokerHelper.java:430)
    at groovy.lang.GroovyShell.parse(GroovyShell.java:743)
    at groovy.lang.GroovyShell.parse(GroovyShell.java:770)
    at groovy.lang.GroovyShell.parse(GroovyShell.java:761)
    at com.eviware.soapui.support.scripting.groovy.SoapUIGroovyScriptEngine.compile(SoapUIGroovyScriptEngine.java:148)
    at com.eviware.soapui.support.scripting.groovy.SoapUIGroovyScriptEngine.run(SoapUIGroovyScriptEngine.java:93)
    at com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase.runTearDownScript(WsdlTestCase.java:951)
    at com.eviware.soapui.impl.wsdl.support.AbstractTestCaseRunner.runTearDownScripts(AbstractTestCaseRunner.java:202)
    at com.eviware.soapui.impl.wsdl.support.AbstractTestCaseRunner.internalFinally(AbstractTestCaseRunner.java:183)
    at com.eviware.soapui.impl.wsdl.support.AbstractTestCaseRunner.internalFinally(AbstractTestCaseRunner.java:42)
    at com.eviware.soapui.impl.wsdl.support.AbstractTestRunner.run(AbstractTestRunner.java:163)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)
    Caused by: java.lang.InstantiationException: teardownScripts
    at java.lang.Class.newInstance0(Class.java:359)
    at java.lang.Class.newInstance(Class.java:327)
    at org.codehaus.groovy.runtime.InvokerHelper.createScript(InvokerHelper.java:408)
    ... 16 more
  • HP-Plano-TX-Soa's avatar
    HP-Plano-TX-Soa
    Occasional Contributor
    Rao,

    You can't place the class definition and the Teardown() method and all the source of the package "customScripts" inside the TestCase teardown and expect it to work. It's not a groovy script in that form - and SoapUI expects to see a groovy script in the TestCase teardown, not a full package declaration with class and methods, like you need to place in a JAR file.

    You are way over-complicating the issue.

    Here is what I can place in the TestCase teardown, and run, with no errors - note that the logMonitor object is seen just fine - so the question is why the same com.eviware object (or any com.? object) can't be used from a groovy script that is packaged in a JAR file?

    if (context.expand('${#TestCase#ScriptLogVerbose}') != "YES")
    {
    return
    }

    // Log the testCase name, status and all the testStep messages
    //
    testCaseName = testRunner.testCase.name
    log.info testCaseName

    if ( testRunner.getStatus().toString() == 'FAILED' )
    {
    log.info ("$testCaseName has failed")
    }
    else
    {
    log.info ("$testCaseName has Passed")
    }

    for ( testStepResult in testRunner.getResults() )
    {
    testStep = testStepResult.getTestStep()
    tstype = testStep.config.type
    // log.info tstype
    tsname = testStepResult.testStep.name
    myRequestStep = testRunner.testCase.getTestStepByName("$tsname")

    if ( tstype == "request" && myRequestStep.testRequest.messageExchange != null)
    {
    request = new String(myRequestStep.testRequest.messageExchange.rawRequestData)
    response = new String(myRequestStep.testRequest.messageExchange.rawResponseData)
    log.info ("$tsname: RAW REQUEST: " + request)
    log.info ("$tsname: RAW RESPONSE: " + response)
    }

    sts = testStepResult.getStatus().toString()
    log.info ("$tsname has status of: " + "$sts")
    testStepResult.messages.each() { msg -> log.info (tsname + ": " + msg) }
    }

    if (context.expand('${#TestCase#SaveLogFiles}') != "YES")
    {
    return
    }

    // Give SoapUI script logging a chance to catch up before attempting to capture the script log to a file

    sleep (5000)

    // Save the TestCase Log, error log and script log to a combined log file
    //
    // "soapUI log" can be replaced with http log, jetty log, script log, error log etc based on the need.

    def logArea = com.eviware.soapui.SoapUI.logMonitor.getLogArea( "script log" )

    def path = context.expand('${#Project#Log_files_loc}')
    def date = new Date()
    def datefmt = new java.text.SimpleDateFormat('yyyy_MM_dd_kkmmss')
    timestamp = datefmt.format(date)
    log.info timestamp

    def logFile = new File(path + testCaseName + "_" + timestamp + ".txt")
    log.info (path + testCaseName + "_" + timestamp + ".txt")
    logFile.write("============================= SCRIPT LOGS: ===============================\r\n\r\n")
    if( logArea !=null )
    {
    def model = logArea.model
    if( model.size > 0 ) {
    for( c in 0..(model.size-1) ) {
    logFile.append(model.getElementAt( c ).toString() + "\r\n")
    // logFile.append("\r\n")
    }
    }
    }
  • HP-Plano-TX-Soa's avatar
    HP-Plano-TX-Soa
    Occasional Contributor
    Ok - I have a work-around, if not a solution, for the problem. The error complains that "com.eviware....." is not a property of my teardownScripts class.

    So, I created a reference to com.eviware.soapui.SoapUI.logMonitor and I pass that as a property to my custom teardownScripts class, like this (from inside the soapUI TestCase teardown):

    def [b]logMon[/b] = com.eviware.soapui.SoapUI.logMonitor
    def tdscript = new customScripts.teardownScripts(log, context, testRunner, testCase, [b]logMon[/b])
    tdscript.Teardown()


    Now, inside my teardownScripts class, I added the logMon Property (to both the class definition and to its constructor), and I use it to invoke desired methods on the com.eviware.soapui.SoapUI.logMonitor object, instead of trying to import com.eviware.soapui.SoapUI.logMonitor and trying to reference it directly, which produces the error that "com" is not a valid property of my class.

    The JAR file I create for the SoapUI Free version to use, which contains my entire package of custom scripts, now works perfectly. And both the Pro and the Free version can use the same central groovy script library (albeit from different sources - Pro from the source library itself, and Free from the JAR file created from that selfsame source library). This is important, since we don't want to produce test automation that won't run on the Free version.

    This is pretty silly, really. In the Free version you should be able to simply import com.eviware.soapui.SoapUI.logMonitor and use it from inside a groovy script that is JAR'ed up and placed in the ...\bin\ext\ directory. You shouldn't have to explicitly make it a Property of your class and pass it in, as I am having to do here.

    If someone has a real solution, I'm sure plenty of people would appreciate knowing about it, since I can't be the only person trying to produce automation that will run seamlessly on both the Free and Pro versions of SoapUI.
  • HP-Plano-TX-Soa's avatar
    HP-Plano-TX-Soa
    Occasional Contributor
    I can dispense with this work-around 'solution' if there is a way to get to the com.eviware.soapui.SoapUI.logMonitor object via any of the references that are already present in the soapUI TestCase teardown script context - there are four I know of - context, testRunner, testCase and log. Since I already have these Properties in my own customScripts Package of groovy classes, then I should try to use one of them to get to the desired logMonitor object if I can.

    Is it possible to get to logMonitor via any of these four references? I would think this could be done either using the log or the testRunner reference, or maybe using the context reference. I'm not sure where to start to get the answer.