During a load test, it is possible to execute Java code that is external to the Virtual users. This feature allows NeoLoad's functional range to be extended in order to create Virtual Users with a very complex behavior.
This tutorial takes as its example RMI (Remote Method Invocation) calls to a remote Java server. The server provides two services: one gives the dollar value of a stock on the US Stock Exchange, the other provides for the conversion of one currency to another. We are going to string together the call to these two services to obtain a stock price in Euro.
In NeoLoad, Java code may be invoked from JavaScript code, as part of the "JavaScript" logical action.
For Java classes to be used in JavaScript, the class names must be
fully qualified (even for Java classes such as java.util.List) and
preceded by "Packages.".
For example:
var myObj = new Packages.com.company.MyClass(); var result = myObj.compute(myArg); var result2 = Packages.com.company.MyClass.someStaticMethod(result);
Depending on the case, it may be useful to hide part of the complexity of a call to an API behind a "business" layer.
In our present example, we'll choose to handle the intermediate result, namely the dollar stock price, transparently. The aim of this is to simplify as far as possible the succeeding JavaScript calls.
public class SampleClient {
private StockProvider remoteStockProvider;
private CurrencyConverter remoteCurrencyConverter;
private float usdStockQuote=-1;
public void connect() throws NotBoundException, IOException {
this.remoteStockProvider = (StockProvider) Naming.lookup(
"//fooserver/StockProvider"
);
this.remoteCurrencyConverter = (CurrencyConverter) Naming.lookup(
"//fooserver/CurrencyConverter"
);
}
public boolean isConnected() {
return this.remoteStockProvider != null && remoteCurrencyConverter != null;
}
public void getStockQuoteUSD(String stockSymbol) throws RemoteException {
if (!isConnected()) {
throw new IllegalStateException("Not connected to server");
}
this.usdStockQuote = this.remoteStockProvider.getStockQuote(stockSymbol);
}
public float getStockQuoteEur() throws RemoteException {
if (this.usdStockQuote < 0) {
throw new IllegalStateException(
"The method getStockQuoteUSD() has not been called."
);
}
return this.remoteCurrencyConverter.currencyConvert(
"USD", "EUR", this.usdStockQuote
);
}
}The connect() method is used to connect
to the remote object, getStockQuoteUSD() retrieves the
specified stock price and stores it internally, and
getStockQuoteEur() returns the stock price converted
into Euro.Generally speaking, NeoLoad must have access to the Java classes used.
Copy the code to be called, and the libraries used, into the
<neoload-project>/lib/jslib/. You may place
either JAR files or .class files in the directory.
For our example, copy the SampleClient class
compiled in <neoload-project>/lib/jslib/, as
well as the JARs containing the interfaces for the remote objects to be
used, namely StockProvider and
CurrencyConverter.
Our RMI calls require entry data, in this case the symbols for the
stocks whose price we want to retrieve. Create the
"stockSymbols" File - type variable
with the required values:
Create the stockQuotes.csv file
symbol;description IBM;IBM MSFT;Microsoft AAPL;Apple ORCL;Oracle JAVA;Sun GOOG;Google
Procedure 16.2. Create the "stockSymbols" variable
Use the "Edit / Variables" menu item.
Click the "Create a variable" button.
Select "File" type.
Name the variable, "stockSymbols".
Use the file previously created.
Select the "Use first line as header" option.
Leave the value change policies to their default setting: each line of the file corresponds to a Virtual User instance.
Click "Ok".
Create a new Virtual User in the current project. We are going to create one action for each RMI call, as this will allow us to retrieve access time statistics for each call:
Place three "JavaScript" logical actions in the Virtual User.
Let's name them "connect"
,"getStockQuoteUSD" and
"getStockQuoteEur".
Place a "Delay" action in between each JavaScript action.
Modify the wait time for each delay. This must correspond to the time between the two calls in the simulated application.
Replace the default code for each action with the following.

The JavaScript code for the three actions is as follows:
connect
var sampleClient = Packages.com.neotys.test.rmi.client.SampleClient();
sampleClient.connect();
context.currentVU.put("sampleClient",sampleClient);
logger.debug("sampleClient connected");The script creates an instance of the SampleClient class described
above and makes the connection to the server. The
sampleClient instance is stored within the Virtual User
instance, for use by the subsequent requests. Thus, we have one instance
of SampleClient per Virtual User instance throughout the test.
getStockQuoteUSD
var sampleClient = context.currentVU.get("sampleClient");
var stockSymbol = context.variableManager.getValue("stockSymbols.symbol");
logger.debug("stockSymbol=" + stockSymbol);
sampleClient.getStockQuoteUSD(stockSymbol);
The script retrieves the sampleClient
instance stored by the previous script, then interprets the
"stockSymbols" variable created previously. The
getStockQuoteUSD method makes the RMI call that
retrieves the price for the stock whose symbol is taken from the CSV file.
The dollar value is stored within the SampleClient, to
be used as an argument in the following call.getStockQuoteEuro
var sampleClient=context.currentVU.get("sampleClient");
var stockValueEuro = sampleClient.getStockQuoteEUR();
logger.debug("Stock price €" + stockValueEuro);
context.variableManager.setValue("stockPriceEUR",stockValueEuro);The script retrieves the sampleClient instance
stored by the first script, then makes the call to the RMI method that
allows the previously-stored dollar value to be converted into Euro. The
call to the VariableManager allows the value retrieved
by RMI to be injected into a NeoLoad variable. This value may then be used
in NeoLoad, for example as a classic HTTP request parameter. This is
outside the scope of this example however.
As with a standard Virtual User, the Virtual User must be validated in order to verify its proper execution.
Open the validation pane via the "Run / Start
checking" menu item.
Select the appropriate user in the drop-down list
("RMIUser").
Click the "Start Checking" button.

Error Handling
The "JS-OK" return code denotes that the JavaScript code was
correctly executed. In the case of a JavaScript error, or if the Java code
produces an exception, the "JavaScript" action is flagged as containing an
error, accompanied by the JS-ERROR-EVAL or
JS-FAIL error code.
The logger.debug() method provides for the
logging of useful information for checking that the scenario runs
correctly during the validation. In our example, we're displaying the
result of the last RMI call. By default, DEBUG-level logs are only
displayed during the validation process. See the Reference Guide for more information on
logs.
Once the Virtual User has been created and checked, create a population and configure your scenario as for a normal test.
In NeoLoad, the "JavaScript" logical action is not considered a request. Therefore, most of the NeoLoad statistics, such as average pages/sec, average hits/sec, average request response times... all return zero. This is true during test monitoring, in the test summary and in the generated reports.
Thus, the only place the JavaScript statistics can be found is in
NeoLoad's "Values" and "Graphs"
tabs. The information available in these tabs is the same as for an HTTP
request.
For more information about using JavaScript in NeoLoad, see the section called “JavaScript”.
See NeoLoad's JavaScript API .