Forum Discussion

bqualters's avatar
bqualters
Occasional Contributor
3 years ago
Solved

New to SoapUi and programming...can anyone tell me what "No signature of method..blah blah" means?

As a new SoapUI user I am TRYING to learn how to write basic code ...and often get error messages that start with "No signature of method blah blah blah" - like for example the split command.  The message will then continue saying "Possible solution...and then lists several methods and almost always includes the method that it errored on.  What the frick does this mean?  for example - I tried to use a split command to create an array from the first row of the recordset returned from a SQL statement - and wanted to store the different parts into the array for usage elsewhere.  for example - 

 

[SKU:TRANS SKU SNIND E, DESCRIPTION:Trans SKU w/ SNI E].1

 

the above is the returned first row of data from my query and I wanted to create variables using the format of  columnName+rowNumber and then set the value for it based on the value returned in this string so in the end I would end up with (for this row) two variables - SKU1 set to TRANS SKU SNIND E and DESCRIPTION1 set to Trans SKU w/ SNI E.  

 

Now if there is a way to reference these without doing this and WITHOUT previously KNOWING the column names sent in the SQL (as this will be dynamic) please tell me - I've seen people reference the values like this $row.SKU and $row.DESCRIPTION  - but that only works when you KNOW the names of the columns sent in the query.

 

So I tried to use a split command like this:     currRec = split( "$row."+recordNum,",")  (where recordNum was the row indicator number to get the above data) BUT it errors telling me -->

groovy.lang.MissingMethodException: No signature of method: Script51.split() is applicable for argument types: (String, String) values: [[SKU:TRANS SKU SNIND E, DESCRIPTION:Trans SKU w/ SNI E].1, , ] Possible solutions: split(groovy.lang.Closure), wait(), sprintf(java.lang.String, [Ljava.lang.Object;), sprintf(java.lang.String, java.lang.Object), inspect(), wait(long) error at line: 26

 

SO WHAT AM I EXPECTED TO DO HERE????  Is 'split' really not a valid method???

Do I need to import a library?  If so, how do you figure out which library needs to be imported?  This goes for all of these so please don't get hung up on the split - so many commands give me this error that IF importing a library is the answer - please tell me HOW to find the right library for each method I'm trying to use.  I see so many examples on these community boards of code that I try to use - and they don't work when I cut and paste and I get this same No signature of method error!  So obviously they did something I didn't at the beginning of their script that was not identified.  What is it???  

 

And please - I am a NEWBIE - if you are going to answer like I should already know things please save yourself the time and don't respond -I can be talked down to by my wife and I don't need you -  if you are actually trying to help - have at it! Explanations are WAY BETTER than "DO THIS" and never explaining WHY to do that!

  • Hi,

     

    Before we look at your questions, my examples are all based on a simple 'CUST' table.  This table has five columns:-

    • ID
    • SURNAME
    • FORENAME
    • STREET
    • CITY

    In my table, I have this dataset...

    ID SURNAME FORENAME STREET CITY
    1 Jones Steve Market St London
    2 Brown James New St Salford
    3 Head Michael Newby St Liverpool
    4 Marr Johnny Bridge St Manchester

     

    Firstly, split method.  The split method is used to split a string into an array using some character.

    The below example shows how you can use split, but its a faff.

            log.info("Get all customers")
            def custSql = "select * from cust where id = 1";
            def customers = dbConn.rows(custSql);
            // Let's have a look at db response.
            log.info(customers);
    
            // The response is split by commas, but the below will not work.  This returns the error you asked about.
            // customers is an array list and there is no split method for that object type.
            // String[] mySplitArray = customers.split(",");
            
            // However, the string object does have a split method.  Let's convert our array list to a string.
            def myArray = customers.toString();
            log.info(myArray);
            String[] mySplitArray = myArray.split(",");
            log.info(mySplitArray);  //Just returns an object id.  We now need to work with this as an array.
    
            for (row in mySplitArray){
                log.info(row);
            }

     

    How to find column names.  I'm using Oracle and there is a query find the columns in a table.  See the below example..

            log.info("Getting column names");
            def columnSql = "select column_name from user_tab_cols where table_name = 'CUST'";
            def columns = dbConn.rows(columnSql);
    
            // Columns is an array list, so the following log statement will return column names as an array list
            log.info(columns);
    
            // Because columns is an array list, we can find the number of columns using the size() method.
            // The ${something} syntax interpolates the variable into the string to display.
            // Much neater than joining values together like.... log.info("Number of columns is " + columns.size() + ".");
            log.info("Number of columns is ${columns.size()}.");
    
            // We can iterate over the array list by using for each.  E.g.
            for(column in columns){
                log.info(column); // Returns something like a key/value pair.
                log.info(column["COLUMN_NAME"]); // Returns just the actual name.
            
            }
    
            // Becuase we know the number columns, we can also use a traditional for loop.
            for (int i = 0; i < columns.size(); i++) {
                def columnName = columns[i]["COLUMN_NAME"];
                log.info("The column name at postion ${i} is ${columnName}.");
            }

     

    With the ability to find column names, we can use this with a query to tease out values from a record.  See below....

            // Without knowing the column names, we can still query the CUST table and log each column value.
    
            log.info("Getting column names");
            def columnSql = "select column_name from user_tab_cols where table_name = 'CUST'";
            def columns = dbConn.rows(columnSql);
    
            def custByIdSql = "select * from cust where id = 1";
            def cust = dbConn.rows(custByIdSql);
    
            for(column in columns){
                def currentColumn = column["COLUMN_NAME"];
                log.info(cust[0][currentColumn]);
            
            }

     

    We can apply this to a query that returns multiple rows....

            // Without knowing the column names, we can still query the CUST table and log each column value.
    
            log.info("Getting column names");
            def columnSql = "select column_name from user_tab_cols where table_name = 'CUST'";
            def columns = dbConn.rows(columnSql);
    
            log.info("Get all customers")
            def custSql = "select * from cust";
            def customers = dbConn.rows(custSql);
    
            // Iterate over each customer record, and for each customer, iterate over the column names and put the details into a single line.
            for(customer in customers){
                def customerString = "";
                for(column in columns){
                    def currentColumn = column["COLUMN_NAME"];
                    customerString += currentColumn + " - " + customer[currentColumn] + ".  ";
                }
                log.info(customerString);
            }

     

    So, this is all great if the query selects all columns.  E.g. select * from cust.  But in your question, you say you don't know what columns may have been asked, so need to find a way to tease out the column names from the response.

     

    Here's an example....

            // Your example db response looks like [SKU:TRANS SKU SNIND E, DESCRIPTION:Trans SKU w/ SNI E]
            // It's likely in an array list, so turn it into a string.  I've called the db rows response dbResponse for the example.
            // def myString = dbResponse.toString()
            
            // Here I have to assume myString looks like [SKU:TRANS SKU SNIND E, DESCRIPTION:Trans SKU w/ SNI E]
            def myString = "[SKU:TRANS SKU SNIND E, DESCRIPTION:Trans SKU w/ SNI E]";
    
            // Now we can split...
            def myArray = myString.split(",");
    
            log.info(myArray[0]);
            log.info(myArray[1]);
    
            // In your Q, you wanted variable names that includes the row number.  That's tricky and not something I'd recommend.  For a kick off, 
            // I wouldn't know how to create a dynamic variable name, and if they're dynamic how will you reference them later?  Personally, I'd stick with arrays...
    
            def columns = [];
    
            for (item in myArray) {
                // Some entries have a [ or a ].  Lets get rid.
    
                item = item.replace("[", "");
                item = item.replace("]", "");
    
                // Each 'item' is a name value pair sepated by a colon.  We can use that to split again.
                def nameValue = item.split(":");
    
                // The column name is always the left-hand side of the pair, so we only need element zero.
                def columnName = nameValue[0];
                columns.add(columnName);
    
                // We could have done 
                // columns.add(nameValue[0])
    
            }
            // Nice, we now have the columns from db response.
            log.info(columns.toString());
    
            // With this column array, you can now pull values from your db response by applying some of the earlier examples above.

     

     

  • Hi,

    Typically, I head straight to Google.  The intellisense in ReadyAPI isn't great and I don't rely on it.  

     

    If I want to know what methods are available, I search for the class definition using Google.  When looking at your issue and found db responses were an array list, I Googled that.  So a couple of points there, if you have some variable and you want to know the class, use the getClass() method.  E.g.

     

     

    // This will log the class name for a given object.
    log.info(myObject.getClass());
    
    // This returns class.java.util.ArrayList

     

     

    Googling the class name took me to the official Java docs and this page... ArrayList.html 

    From here I could then see the methods available to me.

     

    java.utils are already imported, so no issues there in calling methods.  But, I'd take the same approach to find the lib to import.

     

    For example, here is some Groovy script to load a file.

     

    def fullFilePath = "c:\temp\some-file-of-interest.txt";
    
    log.info("Opening file ${fullFilePath}.");
    
    String fileContents = new File(fullFilePath).text;
    
    return fileContents;

     

     

    This will throw an error because of a missing import.  Here, I would Google something like, "groovy java new File example".  The first link in the results took me to tutorialspoint.com.

     

    And there is the import....

    In this case, that's job done.

     

    I know you said not to focus on Split, but it's worth a quick look.  In your original post, you mentioned


    So I tried to use a split command like this:     currRec = split( "$row."+recordNum,",")  (where recordNum was the row indicator number to get the above data) BUT it errors telling me -->

    groovy.lang.MissingMethodException: No signature of method: Script51.split() is applicable for argument types: (String, String) values: [[SKU:TRANS SKU SNIND E, DESCRIPTION:Trans SKU w/ SNI E].1, , ] Possible solutions: split(groovy.lang.Closure), wait(), sprintf(java.lang.String, [Ljava.lang.Object;), sprintf(java.lang.String, java.lang.Object), inspect(), wait(long) error at line: 26

     

    SO WHAT AM I EXPECTED TO DO HERE????  Is 'split' really not a valid method???

    Do I need to import a library?  If so, how do you figure out which library needs to be imported?  

     


    This isn't a missing import.  split("something",",") won't work.  Here, whatever example you've borrowed from, is saying there is a function called split that takes two parameters.  There isn't and that's what this part of the error "split() is applicable for argument types: (String, String)" says.

     

    How to approach this?  Back to Google and search for "java groovy split".  Again, first hit is tutorialspoint and an example...

     

    Split isn't a function.  It's a method on the string class, we need to call it like "hello-world".split("-") instead of split("hello-world", ",")

     

    Thinking about imports in general, I can only actually think of a handful I've had to use.  These are for file handling, SQL and database connectivity, JSON parser and XML Parser.  Everything else I've done is using core language without imports.  If something went wrong with my scripts, I'd definitely be more inclined to think I have a code error before an import issue.

     

    There are some great and some not-so-great resources out there.  For things Groovy and SoapUI?ReadyAPI related, have a look at ou-ryperd.net .  This is an excellent resource and one I have recommended three times in the last fortnight.  There is also StackOverflow, which can be a mixed bag.

     

    But, this forum is the best for Groovy with ReadyAPI or SoapUI.  Don't struggle, fire off lots of questions, even if you think too simple or too obvious.  Typically, quick/easy problems are answered very, very fast.  I know you had to wait a few days for a response to this thread, but there were a few things to think about!

     

     

     

  • bqualters's avatar
    bqualters
    3 years ago

    And THAT folks...is how you answer a question!  Thanks Chris - tons of info here.  My problem is I am a self taught WinRunner /UFT tester who has zero classroom training on scripting of any sort, so I carried alot of expectations over to Groovy that I shouldn't - like a good built in reference manual.  But hey..that's why it's free...the error messages are NOT very intuitive - as you pointed out with the split example..I thought since it showed the (string,string) that it recognized the syntax but that I needed to load a library to be able to use it...again - BOOKMARKING this answer as a reference for future stuff.  I am making pretty good progress on creating an engine to automatically run my functional testing stuff - knowing the basics of the language will make it alot easier so THANK YOU!

4 Replies

  • ChrisAdams's avatar
    ChrisAdams
    Champion Level 3

    Hi,

     

    Before we look at your questions, my examples are all based on a simple 'CUST' table.  This table has five columns:-

    • ID
    • SURNAME
    • FORENAME
    • STREET
    • CITY

    In my table, I have this dataset...

    ID SURNAME FORENAME STREET CITY
    1 Jones Steve Market St London
    2 Brown James New St Salford
    3 Head Michael Newby St Liverpool
    4 Marr Johnny Bridge St Manchester

     

    Firstly, split method.  The split method is used to split a string into an array using some character.

    The below example shows how you can use split, but its a faff.

            log.info("Get all customers")
            def custSql = "select * from cust where id = 1";
            def customers = dbConn.rows(custSql);
            // Let's have a look at db response.
            log.info(customers);
    
            // The response is split by commas, but the below will not work.  This returns the error you asked about.
            // customers is an array list and there is no split method for that object type.
            // String[] mySplitArray = customers.split(",");
            
            // However, the string object does have a split method.  Let's convert our array list to a string.
            def myArray = customers.toString();
            log.info(myArray);
            String[] mySplitArray = myArray.split(",");
            log.info(mySplitArray);  //Just returns an object id.  We now need to work with this as an array.
    
            for (row in mySplitArray){
                log.info(row);
            }

     

    How to find column names.  I'm using Oracle and there is a query find the columns in a table.  See the below example..

            log.info("Getting column names");
            def columnSql = "select column_name from user_tab_cols where table_name = 'CUST'";
            def columns = dbConn.rows(columnSql);
    
            // Columns is an array list, so the following log statement will return column names as an array list
            log.info(columns);
    
            // Because columns is an array list, we can find the number of columns using the size() method.
            // The ${something} syntax interpolates the variable into the string to display.
            // Much neater than joining values together like.... log.info("Number of columns is " + columns.size() + ".");
            log.info("Number of columns is ${columns.size()}.");
    
            // We can iterate over the array list by using for each.  E.g.
            for(column in columns){
                log.info(column); // Returns something like a key/value pair.
                log.info(column["COLUMN_NAME"]); // Returns just the actual name.
            
            }
    
            // Becuase we know the number columns, we can also use a traditional for loop.
            for (int i = 0; i < columns.size(); i++) {
                def columnName = columns[i]["COLUMN_NAME"];
                log.info("The column name at postion ${i} is ${columnName}.");
            }

     

    With the ability to find column names, we can use this with a query to tease out values from a record.  See below....

            // Without knowing the column names, we can still query the CUST table and log each column value.
    
            log.info("Getting column names");
            def columnSql = "select column_name from user_tab_cols where table_name = 'CUST'";
            def columns = dbConn.rows(columnSql);
    
            def custByIdSql = "select * from cust where id = 1";
            def cust = dbConn.rows(custByIdSql);
    
            for(column in columns){
                def currentColumn = column["COLUMN_NAME"];
                log.info(cust[0][currentColumn]);
            
            }

     

    We can apply this to a query that returns multiple rows....

            // Without knowing the column names, we can still query the CUST table and log each column value.
    
            log.info("Getting column names");
            def columnSql = "select column_name from user_tab_cols where table_name = 'CUST'";
            def columns = dbConn.rows(columnSql);
    
            log.info("Get all customers")
            def custSql = "select * from cust";
            def customers = dbConn.rows(custSql);
    
            // Iterate over each customer record, and for each customer, iterate over the column names and put the details into a single line.
            for(customer in customers){
                def customerString = "";
                for(column in columns){
                    def currentColumn = column["COLUMN_NAME"];
                    customerString += currentColumn + " - " + customer[currentColumn] + ".  ";
                }
                log.info(customerString);
            }

     

    So, this is all great if the query selects all columns.  E.g. select * from cust.  But in your question, you say you don't know what columns may have been asked, so need to find a way to tease out the column names from the response.

     

    Here's an example....

            // Your example db response looks like [SKU:TRANS SKU SNIND E, DESCRIPTION:Trans SKU w/ SNI E]
            // It's likely in an array list, so turn it into a string.  I've called the db rows response dbResponse for the example.
            // def myString = dbResponse.toString()
            
            // Here I have to assume myString looks like [SKU:TRANS SKU SNIND E, DESCRIPTION:Trans SKU w/ SNI E]
            def myString = "[SKU:TRANS SKU SNIND E, DESCRIPTION:Trans SKU w/ SNI E]";
    
            // Now we can split...
            def myArray = myString.split(",");
    
            log.info(myArray[0]);
            log.info(myArray[1]);
    
            // In your Q, you wanted variable names that includes the row number.  That's tricky and not something I'd recommend.  For a kick off, 
            // I wouldn't know how to create a dynamic variable name, and if they're dynamic how will you reference them later?  Personally, I'd stick with arrays...
    
            def columns = [];
    
            for (item in myArray) {
                // Some entries have a [ or a ].  Lets get rid.
    
                item = item.replace("[", "");
                item = item.replace("]", "");
    
                // Each 'item' is a name value pair sepated by a colon.  We can use that to split again.
                def nameValue = item.split(":");
    
                // The column name is always the left-hand side of the pair, so we only need element zero.
                def columnName = nameValue[0];
                columns.add(columnName);
    
                // We could have done 
                // columns.add(nameValue[0])
    
            }
            // Nice, we now have the columns from db response.
            log.info(columns.toString());
    
            // With this column array, you can now pull values from your db response by applying some of the earlier examples above.

     

     

  • ChrisAdams's avatar
    ChrisAdams
    Champion Level 3

    Hi,

    Typically, I head straight to Google.  The intellisense in ReadyAPI isn't great and I don't rely on it.  

     

    If I want to know what methods are available, I search for the class definition using Google.  When looking at your issue and found db responses were an array list, I Googled that.  So a couple of points there, if you have some variable and you want to know the class, use the getClass() method.  E.g.

     

     

    // This will log the class name for a given object.
    log.info(myObject.getClass());
    
    // This returns class.java.util.ArrayList

     

     

    Googling the class name took me to the official Java docs and this page... ArrayList.html 

    From here I could then see the methods available to me.

     

    java.utils are already imported, so no issues there in calling methods.  But, I'd take the same approach to find the lib to import.

     

    For example, here is some Groovy script to load a file.

     

    def fullFilePath = "c:\temp\some-file-of-interest.txt";
    
    log.info("Opening file ${fullFilePath}.");
    
    String fileContents = new File(fullFilePath).text;
    
    return fileContents;

     

     

    This will throw an error because of a missing import.  Here, I would Google something like, "groovy java new File example".  The first link in the results took me to tutorialspoint.com.

     

    And there is the import....

    In this case, that's job done.

     

    I know you said not to focus on Split, but it's worth a quick look.  In your original post, you mentioned


    So I tried to use a split command like this:     currRec = split( "$row."+recordNum,",")  (where recordNum was the row indicator number to get the above data) BUT it errors telling me -->

    groovy.lang.MissingMethodException: No signature of method: Script51.split() is applicable for argument types: (String, String) values: [[SKU:TRANS SKU SNIND E, DESCRIPTION:Trans SKU w/ SNI E].1, , ] Possible solutions: split(groovy.lang.Closure), wait(), sprintf(java.lang.String, [Ljava.lang.Object;), sprintf(java.lang.String, java.lang.Object), inspect(), wait(long) error at line: 26

     

    SO WHAT AM I EXPECTED TO DO HERE????  Is 'split' really not a valid method???

    Do I need to import a library?  If so, how do you figure out which library needs to be imported?  

     


    This isn't a missing import.  split("something",",") won't work.  Here, whatever example you've borrowed from, is saying there is a function called split that takes two parameters.  There isn't and that's what this part of the error "split() is applicable for argument types: (String, String)" says.

     

    How to approach this?  Back to Google and search for "java groovy split".  Again, first hit is tutorialspoint and an example...

     

    Split isn't a function.  It's a method on the string class, we need to call it like "hello-world".split("-") instead of split("hello-world", ",")

     

    Thinking about imports in general, I can only actually think of a handful I've had to use.  These are for file handling, SQL and database connectivity, JSON parser and XML Parser.  Everything else I've done is using core language without imports.  If something went wrong with my scripts, I'd definitely be more inclined to think I have a code error before an import issue.

     

    There are some great and some not-so-great resources out there.  For things Groovy and SoapUI?ReadyAPI related, have a look at ou-ryperd.net .  This is an excellent resource and one I have recommended three times in the last fortnight.  There is also StackOverflow, which can be a mixed bag.

     

    But, this forum is the best for Groovy with ReadyAPI or SoapUI.  Don't struggle, fire off lots of questions, even if you think too simple or too obvious.  Typically, quick/easy problems are answered very, very fast.  I know you had to wait a few days for a response to this thread, but there were a few things to think about!

     

     

     

    • bqualters's avatar
      bqualters
      Occasional Contributor

      And THAT folks...is how you answer a question!  Thanks Chris - tons of info here.  My problem is I am a self taught WinRunner /UFT tester who has zero classroom training on scripting of any sort, so I carried alot of expectations over to Groovy that I shouldn't - like a good built in reference manual.  But hey..that's why it's free...the error messages are NOT very intuitive - as you pointed out with the split example..I thought since it showed the (string,string) that it recognized the syntax but that I needed to load a library to be able to use it...again - BOOKMARKING this answer as a reference for future stuff.  I am making pretty good progress on creating an engine to automatically run my functional testing stuff - knowing the basics of the language will make it alot easier so THANK YOU!

  • bqualters's avatar
    bqualters
    Occasional Contributor

    Believe it or not I figured out most of this myself BUT I think what you presented has some "cleaner and easier" ways of doing it - However, I tried the replace command just like what you have for a parenthesis and it kept telling me I couldn't split it by that - I changed my command to see if it would work with a letter instead of the parenthesis and it did work - so I was confused.  I appreciate everything you did here and will save this answer off as a reference for other things later but I still have the BIG question of - if you are told that the method you are trying to use (let's forget about this specific example - I am talking generally) is not available and you know it's a valid function (in my case I am assuming they are valid as I've seen them in responses to other people's questions) - HOW do you find the library that must be loaded to allow you to use it?