Beginning soapUI Scripting: Javadocs 2

In my last post I started a discussion of javadocs, providing a high level overview. In this post I'll try to cover some of the keywords and concepts you may encounter when dealing with documentation for a class.

I have to admit I may have bitten off more than I can chew with this post, which accounts in part for the length of time it took me to publish it.  As I started looking at javadocs and javadoc keywords in more detail, I realized the post had to include explanations of a lot of basic Java concepts.  I hope I did an adequate job of explaining them, but I strongly encourage you to check out the official Java Tutorials to fill in the gaps (of which I'm sure there are a few).  I recommend the entire Learning the Java Language trail, but the particularly relevant sections include the sections on Classes and Objects and Interfaces and Inheritance.

Access Modifiers and Special Considerations for Groovy

Access modifiers-- private, package-private (which is the default when no modifier is specified), protected, and public-- specify the context in which a class and its members can be read and/or modified in code.  In the context of the basic usage of an API (when using it in a soapUI script, for example, as opposed to more advanced usage like making your own modifications to the source code), you're generally only going to deal with classes and members marked public.  The two most restrictive levels of access, private and package-private are reserved for those classes and members that represent "internal wiring"-- strictly intended for use within a class (private) or package (package-private), not intended for direct use by API consumers.  In fact, the Javadoc tool excludes classes and members with these access modifiers by default, in which case they don't even appear in documentation.  Members at the protected level are only slightly less restricted in that they're inherited by sub-classes of their enclosing class (even sub-classes that aren't in the same package)-- for somebody using the API, this comes into play when creating your own sub-class, something beyond the basic scripting covered here.

However, there's a very important caveat when working with Groovy.  When trying some scripting in soapUI with the HSSFWorkbook class, I was surprised to see that I could in fact access the _sheets field.  If you look at the documentation, this field is marked protected, meaning it should only be accessible from within the class, within other resources in the same package, or from within a sub-class-- a Groovy Script step doesn't fall into any of those categories.  After investigating, I found this interesting post indicating that Groovy doesn't always respect access modifiers (see item 6)-- that's potentially a bad thing; there are good reasons why an API developer might restrict access to a certain member of a class, particularly when it comes to modifying its value.  As the article says, just because Groovy allows you to do something doesn't mean you should do it; you may have to police yourself a bit-- be wary of accessing classes or members marked anything other than public.

Static and Final

The final modifier generally restricts a user's ability to modify a class or member, although it means slightly different things in different contexts.  Applied to a class, it means the class can not be extended-- you can not create a sub-class based on that class.  A final method can not be overridden in a sub-class; in other words, you can't change the way the method is implemented, writing new code for it in your sub-class.  The value of a field marked final can not be changed.  As with the more restrictive access modifiers discussed above, the final modifier at the class and method level isn't something you'll need to worry about too much with basic usage of the API; it's more relevant when you start dealing with sub-classes.  With fields, however, more often than not you'll see them marked final in javadocs, and the distinction is important even in the context of basic scripting.

The static modifier designates a class (as opposed to instance) member.  A non-static member is associated with an individual object-- an instance of a class.  I discussed the _sheets field of the HSSFWorkbook class above-- if you were to create two different HSSFWorkbook objects and add sheets to each, the _sheets field would be different for each object; each instance of HSSFWorkbook would have its own value for the field.  A static member, on the other hand, is associated with the class itself; when you access a class member, you access it through the name of the class, not the name of a variable representing an instance of the class:

log.info(myWorkbook._sheets) //_sheets is accessed for an HSSFWorkbook instance named myWorkbook-- can be done in Groovy
log.info(HSSFWorkbook.INITIAL_CAPACITY) //INITIAL_CAPACITY is accessed via the HSSFWorkbook class itself

It's common to use the static and final modifiers together with fields to create constants-- so common, in fact, that there's a convention in Java to use all caps in these fields' names (as with the INITIAL_CAPACITY field above).  Class constants often represent values that are frequently used; creating class constants for these values eliminates the need to repeatedly declare variables to hold them.  Java's Math class has the static final field PI, for example; similarly, the Color class has static fields to represent frequently used colors: RED, BLUE, etc.  Again, there's no need to create objects of class Math or Color to access these constants; they're called against the class names themselves (Math.PI or Color.RED, for example).

Methods, too, can be marked static.  Returning to Java's Math class as an example, aside from the standard methods it inherits from the object class, all of its methods are static-- the class is essentially a toolbox of mathematical operations.  As with static fields, static methods are accessed via the class instead of an instance.

Method Return and Parameter Types

Method definitions in javadocs specify return types (the data types of results from functions) and parameter type(s) (the types of the values passed into the functions).  For the most part, these should be pretty straightforward; for example, look at the WsdlTestCase class in the API documentation for soapUI.  In the Method Summary table, find the getTestStepByName() method; in the left-hand (Modifier and Type) column you can see that the return type is WsdlTestStep.  In the Method and Description column, you can see in the parentheses next to the method name that the method takes a single String argument called stepName-- note that stepName is a somewhat arbitrary parameter name; any variable name could have been used when the method was created (of course, stepName is a good choice because it describes the significance of the String argument).  From the perspective of somebody using the method, the parameter name itself is relatively unimportant; what is important is recognizing the method takes a single String argument and returns a WsdlTestStep object.

The void keyword is used for the return type when a method doesn't return a value.  The setName() function of the WsdlTestCase class, for example, changes a property of the test case without actually returning anything.  For functions that don't take any arguments, the parentheses next to the method name are simply left empty.

Some functions return multiple data items; for these, the "enclosing" data type is also indicated.  For example, the getTestStepList() method of the WsdlTestCase class specifies a return type of List<TestStep>, meaning it returns an object of class List containing zero (the list could be empty) or more TestStep objects (more about what that means below).  The getTestSteps() method returns an object of class Map; Maps consist of key-value pairs, so the return type specifies Map<String,TestStep>-- each key-value pair in the returned Map consists of a String (the key) and a TestStep object (the value).

In some cases, a method's parameter and/or return types are determined at runtime, in which case you'll see a slightly complicated-looking syntax. Look at the getTestStepsOfType() method, for example.  The return type is given as <T extends TestStep> List<T>.  There's no T class, of course.  The T is used as a placeholder for a data type to be determined later.  The <T extends TestStep> part of the return type tells us that there's a restriction on T-- it has to be a type that's derived from the TestStep interface (a class that implements the TestStep interface, for example, or a class that extends another class that implements the interface, etc.), and the rest (List<T>) tells us that the method returns a List of objects of that type.  So how is the type actually determined? If you look at the method description column, getTestStepsOfType(Class<T> stepType) tells us that type T is the type of the class passed in for the stepType argument-- so the argument determines the meaning of T in the return type definition as well.

Return Types and Polymorphism

Above, when discussing the getTestStepList() method, I wrote that it returns a list of TestStep objects.  If you were to look at the TestStep definition in the javadocs, however, you'll see that TestStep is actually not a class-- it's an interface.  In my last post I mentioned that you can't actually create an instance of an interface.  What's going on here?  This is actually an illustration of the object-oriented concept of polymorphism-- it's a source of great flexibility and power in Java, but for me, at least, it was a source of some confusion when I first started working with javadocs.  In a very simplified nutshell, polymorphism means an object can be many things at the same time. Because an object can extend another class and/or implement multiple interfaces, it shares their characteristics and can be used wherever a parent class or any implemented interfaces are called for.  So for example, if an interface is specified as a method parameter or return type (as with the getTestStepList() method), it means that the method will take or return an object of a class that implements the given interface.  The same principle applies to classes that are sub-classed: if a class is given as a parameter or return type, the method can actually take or return an instance of the class or any sub-class of that class.  For example, WsdlTestStep is the return type for the getTestStepAt() method.  If you look at the javadoc entry for WsdlTestStep, you'll see that it has three sub-classes: WsdlPropertiesTestStep, WsdlRunTestCaseTestStep, and WsdlTestStepWithProperties (which itself has its own sub-classes).  The specific class returned by the method, then, can be any of the sub-classes of WsdlTestStep (including the sub-classes of the WsdlTestStepWithProperties class).

The problem with polymorphism in the context of javadocs is that they may not indicate the specific class that's ultimately returned by a call to the method in your script.  Knowing the class of the returned object is important, of course, in order to know what methods and properties are available to that object.  If push comes to shove, you can identify an object's class by using the getClass() method-- this is a basic method inherited by all classes from Java's Object class:
def myTestStep = testCase.getTestStepAt(1)
log.info(myTestStep.getClass())
//Example output: class com.eviware.soapui.impl.wsdl.teststeps.WsdlGroovyScriptTestStep
//The return type specified in the javadoc for getTestStepAt() is WsdlTestStep
//The object returned is actually an instance of an indirect sub-class of the WsdlTestStep class

Beginning soapUI Scripting: Javadocs 1

I've written quite a few posts now on scripting in soapUI; hopefully they've provided enough useful information to get you started on your own projects.  However, you may come to a point where you're trying to do something for which you can't find a good example, or you've found an example but need some help understanding it.  Or perhaps you're just curious to see what else might be possible with a script you've already written.  In this post, I want to begin a series looking at javadoc documentation to help you explore the capabilities of Java and Groovy libraries on your own.

The javadoc format is standardized, generated directly from a resource's code and specially formatted comments and annotation within the code (Javadoc is the name of the tool used to do this).  Although it may be a little non-intuitive at first, its ubiquity across the Java world makes even a basic understanding extremely useful: if you can read javadoc documentation, you can learn more not just about soapUI but many of the other APIs we've discussed in previous posts: POI, Groovy, and, of course, the base Java library itself.

Let's take a look at the HSSFWorkbook class of the Apache POI API, which I think provides a fairly straightforward example-- for those of you unfamiliar with it, this API allows you to work with Microsoft document formats within Java; the HSSFWorkbook class corresponds to an Excel xls workbook.  Launch the documentation page via this link (I recommend opening the link in a new window or tab so you can read this post and see the example side by side): http://poi.apache.org/apidocs/index.html.  Near the top of the page or the top of the main frame on the right (depending on your current view), you'll see links/buttons for "Frames" or "No Frames" that you can use to switch between two available views; this post is written from the perspective of the "Frames" view.

The top left frame lists the packages of the POI API, the organizational units into which its resources are divided.  You can select an individual package to view its classes or "All Classes" to view all of the API's classes together.  Scroll through the packages in the upper left frame and select the org.apache.poi.hssf.usermodel package, then take a look at the lower left frame, which should now be populated with the package's contents.  In this case, they're divided into three different categories: interfaces (I'll explain more about these a little later), classes, and enums.  These aren't the only categories you may encounter-- another common category is exceptions, for example. For the sake of this post and to keep things simple, I'm going to think in terms of two primary groups: classes and interfaces (enums and exceptions are both special types of classes).  Note that interfaces and classes are distinguished from each other by the way they're displayed; interfaces are always displayed in italics.

Find the HSSFWorkbook class in the lower left frame and click on it-- the main frame on the right will update and display information specific to the class.

Just above the name of the class at the top of the frame is its enclosing package.  In the context of scripting, one reason this is important is for import statements.  Recall from my post about using the XmlHolder class in soapUI that an import statement was necessary in order to create an instance of the class:

import com.eviware.soapui.support.XmlHolder

def myHolder = new XmlHolder(messageExchange.getResponseContentAsXml())

The fully qualified name of the class (including its package) is needed for the import statement.

The fully qualified name is also displayed in the class's hierarchical structure, displayed just below the name-- a description of the classes from which it inherits properties and methods and the interfaces implemented by the class.  I'll try to explain these concepts briefly here, but I strongly recommend checking out the more detailed explanation here in Oracle's Java Tutorials.

One benefit of Java's object-oriented approach is the idea of inheritance-- when creating a new class you don't have to start from scratch; you can designate another class as its base class and the new class starts with some (or all) of its base class's methods and properties.  You can then override some of those inherited members (create a new implementation of a method, for example) or add new ones to make the new class more specialized and add additional functionality.  In fact, there are some classes called abstract classes that are designed specifically to be used as base classes.  You can't actually create an instance of an abstract class; you'll never work with an abstract class directly in code.  However, "concrete" classes (which can be instantiated) can inherit from it.

Interfaces are similar to abstract classes in some ways.  In simplified terms, interfaces primarily define a set of methods-- but they don't provide any actual implementation of those methods.  The methods in an interface have names and signatures-- describing what types of data the methods take as arguments and what types are returned-- but they don't have any code for the methods.  Where does the actual code come from?  A class can implement an interface; if it does, it is required to "fill in" the implementation of each of the methods defined for the interface.  Importantly, a class can inherit from only one class (although that class may itself inherit from another, which may inherit from another, etc.), but it can implement multiple interfaces.

Returning to our example of the HSSFWorkbook class, its javadoc page shows us that it's a sub-class of (i.e., it inherits from) the POIDocument class and it implements the Workbook interface.

Just below the hierarchy information is the class's declaration-- this is actually how the class is declared in its underlying Java code:

public final class HSSFWorkbook
extends POIDocument
implements Workbook

I'll discuss the meaning of some of the keywords like public and final in the next post.  This declaration also tells us some of the same information we saw in the hierarchy information: the extends keyword indicates the class's base class (POIDocument), and the implements keyword indicates interfaces implemented by the class (Workbook).

Just below this information is a description of the class (the description is a single line here, but this may be much longer and more detailed in some cases) followed by the meat of the javadoc entry: descriptions of its members, its properties and methods.  These are described in brief summary form at the top of the page, then in more detail farther down on the page.

Fields are the member variables of a class-- variables associated with the class itself (as opposed to variables that are declared within methods or code blocks-- a variable used as a counter in a for loop would not be a member variable, for example).  For fields that are not inherited, the summary section shows them in a table with modifying keywords and type (the data type/class of the field) on the left and a name and description on the right.  Inherited fields are simply listed with the class or interface from which they're inherited, linked to their detailed descriptions in those classes and interfaces.

Below the field descriptions are the class's constructors.  Constructors are special methods used to create new instances of a class when used in conjunction with the new keyword:

//An import statement is required to use the constructor
import org.apache.poi.hssf.usermodel.HSSFWorkbook

def myXLSWorkbook = new HSSFWorkbook()

Note constructors have the same name as the class.  Also note that with the HSSFWorkbook there are multiple constructors, demonstrating the concept of overloading-- its possible for a class to have multiple methods (this is not limited to constructors) with the same name as long as each method takes different sets of argument types.  For example, you can see that one constructor takes no arguments, while another takes an InputStream as an argument, and yet another takes an InputStream and a boolean (true or false) as its arguments.  This is permissible because the data types of the arguments are unique for each constructor; the interpreter or compiler can tell which particular constructor you're trying to call based on the types of the arguments passed into the constructor.

Below the constructors are the remaining methods of the class.  These are displayed in a table with modifying keywords and type (the data type returned by the method) on the left and the method name and parameter types (the data types the method takes) on the right.  As with fields, methods that are inherited from other classes or interfaces are listed separately, linked to their detailed descriptions in the corresponding class or interface.

That completes a quick overview of a typical javadoc page.  In the next post, I'll look at some of those keyword modifiers and what they mean in the context of scripting.

XPath in soapUI Part 4: XPath and Property Transfers

This post is the last in the series on using XPath in soapUI.  Up until this point we've been looking at XPath as it's used in XPath Match assertions, but it also features prominently in property transfers.  While there's not much by way of new syntax in this post (in fact, you'll probably find that expressions used in XPath assertions are generally more complex than the expression you'll use with property transfers), I think it's useful to see how XPath expressions can be used to designate source and target locations for property transfers.

This post uses the same sample project we've been using with previous XPath posts, built around a web service that returns information about holidays in several countries; you can download it here.  The test suite contains a test case called PropXferExample (the last test case in the suite) specifically created to illustrate using XPath in property transfers.  Let's take a quick look at the test case before we try to run it.

The test case begins with a straightforward test request:


This request asks the service for available US holidays, submitting "US" as the countryCode.  For this test case, we're going to take one of the holiday codes (corresponding to Valentine's Day) returned in the response to this test request and use it as a parameter in a subsequent test request.  Here's a look at an excerpt from the response, which we'll reference in the property transfer step:


The second step in the test case is a Property Transfer step, consisting of a single property transfer:


In the upper panel, we select our source location-- the location from which we'd like to copy our property value.  The AvailableHolidays test step (the first test request in the test case) is selected in the Source drop-down; in the Property drop-down, we indicate that we'd like to get our transfer value from the request's response.  Of course, we're not interested in the entire response, so we can use an XPath expression to specify precisely which part we would like to use; the XPath expression //Holidays[Name = "Valentine's Day"]/Key designates the value of the Key element for the Holidays element with the Name "Valentine's Day".  Just as with an XPath assertion, we can automatically declare namespaces to use with our XPath expression.  Note the button to auto-generate namespace declarations in the Property Transfer dialog looks different than the button in XPath assertion dialogs (simply labelled "ns:" here).  The XPath expression //Holidays[Name = "Valentine's Day"]/Key designates the value of the Key element for the Holidays element with the Name "Valentine's Day".

In the lower panel, we designate the destination for our transfer-- the location to which we'd like to copy the property value.  We could copy the property value to a test case or test suite property (useful if we intend to re-use it in multiple places throughout our script), but in this case we're only using it in the single request, so we can copy it directly via the transfer.  The request property of the GetHolidayDate test request step is selected as the target via the drop-downs, and the XPath expression (//ns1:holidayName) designates that we'd like to plug the copied property value into the holidayName element in the request.

To give some context to the expression, let's take a look at that request step now (again, don't run anything just yet):


This request sends a country, holiday (its key, not name, despite the name of the element), and year to retrieve the selected holiday's date.  Note the holidayName parameter is missing from the request (for now).

Run the test case and it should complete without errors.  The first test step retrieves the list of US holidays.  The second step finds the key corresponding to Valentine's Day in the response to step one and plugs it into the holidayName element in the final test request step.  Look at the second test request again after running the test case and you'll see that our missing parameter is now populated and we get a valid response: