6

ReadyAPI 'semantic analysis' error. I have stored my script libraries in bin folder and I am calling the getBuildingInfo method from the groovy test script of ReadyAPI. Most of the time this method works fine but once in a while I get this error. I want to find out what the exact issue and fix the root cause. I tested the code in eclipse and it works perfectly fine.

ERROR:BUG! exception in phase 'semantic analysis' in source unit 'Script15.groovy' The lookup for PropertiesQuery caused a failed compilaton. There should not have been any compilation from this call. BUG! exception in phase 'semantic analysis' in source unit 'Script15.groovy' The lookup for PropertiesQuery caused a failed compilaton. There should not have been any compilation from this call.

14: Apparent variable 'Database' was found in a static scope but doesn't refer to a local variable, static field or class. Possible causes: You attempted to reference a variable in the binding or an instance variable from a static context. You misspelled a classname or statically imported field. Please check the spelling. You attempted to use a method 'Database' but left out brackets in a place not allowed by the grammar. @ line 14, column 17. def dbConn = Database.getDbConnection(env);

public class Database {

public static Connection getDbConnection (String env){

    Connection conn = null;
    Class.forName("com.mysql.jdbc.Driver")

    switch (env){
        case "TEST":
            conn = DriverManager.getConnection("a","b","c")
            break;
        case "DEV":
            conn = DriverManager.getConnection("a","b","d")
            break;
    }

    return conn;
}

public static void closeDbConnection(Connection conn) {

    conn.close();
}
}  


class PropertiesQuery {
    public static String getBuildingInfo(String env, String id, int row ){
        String result = "111";


        def query = "SELECT col1, col2 FROM tabl1 WHERE id = 1"

        def dbConn =  Database.getDbConnection(env);
        def stmt = dbConn.createStatement()
        def rs = stmt.executeQuery(query);

        while(rs.absolute(row)){
            rs.getString("col1")
            rs.getString("col2")

            result = rs.getString("col1") +"/"+rs.getString("col2")
            return result;
        }
    }   
}
Rao
  • 20,781
  • 11
  • 57
  • 77
ktmrocks
  • 361
  • 1
  • 5
  • 18
  • Couple of things. 1. query statement does not end with double quotes. 2. where is `env` used in `getDBConnection` method? – Rao Sep 14 '17 at 03:18
  • Two classes are located in the same script? How do you load/call the getBuildingInfo method? – daggett Sep 14 '17 at 06:32
  • @Rao sorry the missing closing double quote in the query and use of env variable in getDBConnection was typo in my part. I have corrected that. – ktmrocks Sep 14 '17 at 13:26
  • @daggett these classes are stored in separate files as .GROOVY file. Basically in SoapUI Pro under Preference there is a way where you can map the location of the script library folder and when I call the method from groovy script test step of SoapUI (PropertiesQuery.getBuildingInfo("TEST","123" 1)) it will load the class file. I believe the issue is loading the classes properly. I have seen the same code working fine sometimes and not working other times. If I take the same code in Eclipse then it will work 100% of the time. I want to get the bottom of it and be certain that it works 100% – ktmrocks Sep 14 '17 at 13:32
  • Update .... I tried again today and I can say this SoapUI issue. Here is the scenario: 1) I edited the working file that uses getDBConnection and did not change anything. I try to run the script and it gives that error. 2) I run a different groovy script that does not use getDBConnection method. It works ok. 3) I come back to the previous script where it calls getDBConnection method and run it. It runs fine this time. This makes me believe this is SoapUI issue. I still want to get to bottom of it though. – ktmrocks Sep 14 '17 at 21:16
  • Where did you place those class files in ready-api? – Rao Sep 18 '17 at 17:01
  • in OpenSource version i just adding the path where groovy classes located to the classpath in `soapui.bat` (for windows): `set CLASSPATH=%CLASSPATH%;c:\path\to\classes`. after this groovy engine correctly loads classes if the class has correct file name. for example the class `PropertiesQuery` must have file name `PropertiesQuery.groovy` – daggett Sep 18 '17 at 22:10
  • @ktmrocks, have you got chance to look my earlier comment? would you mind replying that? – Rao Sep 21 '17 at 09:50
  • @Rao I have placed those .groovy files in C:\Program Files\SmartBear\ReadyAPI-2.1.0\bin\scripts this is mapped from Preference > Ready API > Script library – ktmrocks Sep 22 '17 at 14:42
  • @ktmrocks, thanks. How are you calling the above methods from groovy script test step? – Rao Sep 25 '17 at 14:21
  • @Rao I am calling these as a regular static method the way I do in eclipse. Class.method() – ktmrocks Sep 25 '17 at 17:43

1 Answers1

1

I have my own Groovy script for returning a SQL connection. Instead of naming the driver, I use the Groovy SQL package....

Oh, there is a gotcha with connecting to databases that I noticed on my machine. Not sure if it is a wider problem, but I have it and have mentioned it elsewhere on here. When I launch SoapUI, I cannot run a test that uses a db connection as it fails. What I have to do is got to the environments screen, select one of my connections and click the 'Test Connection' button. After that, I can run any tests. It is bizarre, but it seems on my machine that clicking test connection simply blows the air out of the pipe...

import groovy.sql.Sql

class jdbcConnections {

jdbcConnections() {

}

def getJdbcConnection(conDetails, log) {

    def connString = conDetails.getConnectionString()
    def url = 'jdbc:oracle:thin:' + connString.substring(connString.indexOf('@'),connString.size());
    def userName = connString.replace('jdbc:oracle:thin:', '');
    userName = userName.substring(0,userName.indexOf('/'));
    def password = connString.substring(connString.indexOf('/') + 1,connString.indexOf('@'));

    log.info('      Connecting to database ' + conDetails.getName() + '.  Using account ' + userName + ' at URL ' + url );

    return Sql.newInstance(url, userName, password, conDetails.getDriver());

}

def getJdbcConnection(conDetails)
{
    def connString = conDetails.getConnectionString()
    def url = 'jdbc:oracle:thin:' + connString.substring(connString.indexOf('@'),connString.size());
    def userName = connString.replace('jdbc:oracle:thin:', '');
    userName = userName.substring(0,userName.indexOf('/'));
    def password = connString.substring(connString.indexOf('/') + 1,connString.indexOf('@'));

    return Sql.newInstance(url, userName, password, conDetails.getDriver());
}

}

The connection details I pass in are from the Environments/JDBC connections screen.

Chris Adams
  • 1,376
  • 1
  • 8
  • 15
  • thank you. I will check this and get back if this works. I have raised the issue with SmartBear as well. They are looking into this as well. For now I decided to use built in JDBC connection of the ReadyAPI. – ktmrocks Sep 22 '17 at 14:44