How to use Deephaven in a local development environment
Set up your IDE
Note
Download Example project files
This example will use IntelliJ IDEA together with the Gradle build tool and show you how to:
- Create a new Gradle project.
- Add Groovy if you plan to use it to create queries.
Your new project will include a build.gradle
file that looks something like this:
plugins {
id 'groovy'
id 'java-library'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.codehaus.groovy:groovy-all:3.0.5'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}
test {
useJUnitPlatform()
}
To add Deephaven libraries to your project, add the following to your dependencies:
version = '1.20221001.+'
implementation 'iris:DB:' + version
implementation 'iris:configs:' + version
This will add the DB module (which includes helpful classes like Table or Database) and configs module
(which includes configuration files with default property values) to your project.
To download all Deephaven modules, use 'iris:Iris:' + version
.
Next, add the following Maven repository with your credentials. artifactoryUser
and artifactoryAPIKey
must be set in gradle.properties
:
maven {
credentials {
username = artifactoryUser ?: System.getProperty('user.name')
password = artifactoryAPIKey ?: ""
}
url 'https://illumon.jfrog.io/illumon/libs-customer'
}
Your build.gradle
file will now look something like:
plugins {
id 'groovy'
id 'java-library'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
maven {
credentials {
username = artifactoryUser ?: System.getProperty('user.name')
password = artifactoryAPIKey ?: ""
}
url 'https://illumon.jfrog.io/illumon/libs-customer'
}
}
dependencies {
version = '1.20221001.+'
implementation 'iris:DB:' + version
implementation 'iris:configs:' + version
implementation 'org.codehaus.groovy:groovy-all:3.0.5'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}
test {
useJUnitPlatform()
}
Refresh the project, and Gradle will download the specified modules.
Local unit testing
It may be helpful to have some local test data you can use to test your query's correctness.
The following example requires the DB
and fishlib
modules.
The following simple query calculates the average prices of stocks for a given day:
import com.illumon.iris.db.tables.databases.Database
db = (Database) db
date = currentDateNy()
AvgStockPrices = QueryUtils.getAvgStockPriceTable(db, date)
It uses a helper method which is written in Java so that it can be unit tested:
import com.illumon.iris.db.tables.Table;
import com.illumon.iris.db.tables.databases.Database;
public class QueryUtils {
public static Table getAvgStockPriceTable(final Database db, final String date) {
return db.t("Example", "StockTrades")
.where("Date = `" + date + "`")
.view("USym", "Last")
.avgBy("USym");
}
}
We need a local copy of the Example.StockTrades
schema:
<Table name="StockTrades" namespace="Example" storageType="NestedPartitionedOnDisk" namespaceSet="User">
<Partitions keyFormula="__PARTITION_AUTOBALANCE_SINGLE__" multiday="0,1,2,3,4,5" />
<Column name="Date" dataType="String" columnType="Partitioning"/>
<Column name="Timestamp" dataType="DateTime" columnType="Normal"/>
<Column name="SecurityType" dataType="String" columnType="Normal"/>
<Column name="Exchange" dataType="String" columnType="Normal"/>
<Column name="USym" dataType="String" columnType="Grouping"/>
<Column name="Sym" dataType="String" columnType="Grouping"/>
<Column name="Last" dataType="double" columnType="Normal"/>
<Column name="Size" dataType="int" columnType="Normal"/>
<Column name="Source" dataType="String" columnType="Normal"/>
<Column name="ExchangeId" dataType="int" columnType="Normal"/>
<Column name="ExchangeTimestamp" dataType="DateTime" columnType="Normal"/>
<Column name="SaleCondition" dataType="String" columnType="Normal"/>
</Table>
And some test data (saved as src/test/resources/StockTrades.csv
in the example project):
Date,Timestamp,SecurityType,Exchange,USym,Sym,Last,Size,Source,ExchangeId,ExchangeTimestamp,SaleCondition
2017-08-25,2017-08-25T04:00:15.733154147 NY,Stock,Arca,AAPL,AAPL,159.37,15,Normal,1045,2017-08-25T04:00:15.732196352 NY,@FTI
2017-08-25,2017-08-25T04:00:15.733319609 NY,Stock,Arca,AAPL,AAPL,159.48,85,Normal,1046,2017-08-25T04:00:15.732196352 NY,@FTI
2017-08-25,2017-08-25T04:00:15.740707833 NY,Stock,Arca,AAPL,AAPL,159.48,75,Normal,1047,2017-08-25T04:00:15.740309248 NY,@TI
2017-08-25,2017-08-25T04:00:15.740837742 NY,Stock,Arca,AAPL,AAPL,159.48,25,Normal,1048,2017-08-25T04:00:15.740445952 NY,@FTI
2017-08-25,2017-08-25T04:01:23.959890355 NY,Stock,Nasdaq,AAPL,AAPL,159.55,70,Normal,1055,2017-08-25T04:01:23.959818555 NY,@TI
2017-08-25,2017-08-25T04:30:01.201529919 NY,Stock,Arca,GOOG,GOOG,922.6,1,Normal,1406,2017-08-25T04:30:01.201131776 NY,@TI
2017-08-25,2017-08-25T04:37:49.866345636 NY,Stock,Arca,GOOG,GOOG,924.7,1,Normal,1410,2017-08-25T04:37:49.865935872 NY,@TI
2017-08-25,2017-08-25T05:08:13.941985645 NY,Stock,Nasdaq,GOOG,GOOG,924.7,1,Normal,1418,2017-08-25T05:08:13.941942454 NY,@TI
2017-08-25,2017-08-25T05:18:23.583713313 NY,Stock,Nasdaq,GOOG,GOOG,922.9,11,Normal,1420,2017-08-25T05:18:23.583659125 NY,@FTI
2017-08-25,2017-08-25T05:18:23.584098382 NY,Stock,Nasdaq,GOOG,GOOG,922.9,8,Normal,1421,2017-08-25T05:18:23.584068891 NY,@FTI
- The first step to load the schema and test data into the database is to create a
Configuration
object. TheConfiguration
contains the JVM options, several of which are required to create aDatabase
. This example uses thebuild.gradle
file from before to set unit test configurations.
test {
useJUnitPlatform()
systemProperties = [
'Configuration.rootFile' : 'iris-defaults.prop',
'devroot' : "$rootDir/tmp/iris",
'workspace' : "$rootDir/tmp/workspace",
'com.fishlib.configuration.PropertyInputStreamLoader.override': 'com.fishlib.configuration.PropertyInputStreamLoaderTraditional'
]
}
Property | Description |
---|---|
Configuration.rootFile | The base property file. |
devroot | Contains all jar and configuration files. |
workspace | Will be the root of the local Deephaven file structure. The example unit test will store the table data here. |
com.fishlib.configuration.PropertyInputStreamLoader.override | Set to PropertyInputStreamLoaderTraditional . This loads property files from the classpath, as opposed to, for example, etcd. |
See Client Configuration for more information on the Configuration
.
- Next, you will need to create a local
SchemaService
instance.
final Configuration configuration = Configuration.getInstance();
final String schemaDir = "src/test/resources";
final SchemaService schemaService = SchemaServiceFactory.getLocalInstance(configuration, schemaDir);
The SchemaService
will load all schema files inside the schemaDir
directory.
Caution
The Groovy query is purposefully stored in src/main/resources
instead of src/main/groovy
to ensure it is not compiled.
The example query script is intended to run in a Groovy session inside a Deephaven query worker, which contains
additional predefined variables (such as db) and imported classes that are not available during compilation in the
local development environment.
- Create the
OnDiskQueryDatabase
:
//creates a logger that will print to stdout
final Logger logger = new StreamLoggerImpl();
//where the binary data for the unit test's Table will be stored
final Path rootPath = Files.createTempDirectory(Paths.get(Configuration.getInstance().getWorkspacePath()), "UnitTest");
final File rootFile = rootPath.toFile();
final LocalTablePathManager pathManager = new LocalTablePathManager(rootFile);
final TableDataService tableDataService = new LocalTableDataService(pathManager);
final OnDiskQueryDatabase db = new OnDiskQueryDatabase(logger, rootFile, tableDataService, schemaService);
- Start the
OnDiskQueryDatabase
and set a user context:
db.startup();
Configuration.getInstance().setProperty("IrisDB.permissionFilterProvider", "null");
PermissionFilterProvider.FACTORY.reload();
db.setUserContext(null, new SimpleUserContext("nobody", "nobody"));
- Add the test data:
final Table stockTrades = TableTools.readCsv(new File("src/test/resources/StockTrades.csv"));
db.addTablePartition("Example", "StockTrades", "2017-08-25", stockTrades);
- Use the table getter methods described in the Ultimate Cheat Sheet to test your query:
@Test
public void testQuery() throws IOException {
final Database db = getTestDatabase();
final Table testResult = QueryUtils.getAvgStockPriceTable(db, TEST_DATE);
final double sumAAPL = testResult.where("USym = `AAPL`").getColumn("Last").getDouble(0);
Assertions.assertEquals(159.472, sumAAPL, 0.0002);
final double sumGOOG = testResult.where("USym = `GOOG`").getColumn("Last").getDouble(0);
Assertions.assertEquals(923.56, sumGOOG, 0.0002);
}
The full test class:
import com.fishlib.auth.SimpleUserContext;
import com.fishlib.configuration.Configuration;
import com.fishlib.io.logger.Logger;
import com.fishlib.io.logger.StreamLoggerImpl;
import com.illumon.iris.db.schema.SchemaService;
import com.illumon.iris.db.schema.SchemaServiceFactory;
import com.illumon.iris.db.tables.Table;
import com.illumon.iris.db.tables.databases.Database;
import com.illumon.iris.db.tables.databases.OnDiskQueryDatabase;
import com.illumon.iris.db.tables.utils.TableTools;
import com.illumon.iris.db.v2.locations.TableDataService;
import com.illumon.iris.db.v2.locations.local.LocalTableDataService;
import com.illumon.iris.db.v2.locations.local.LocalTablePathManager;
import com.illumon.iris.db.v2.permissions.PermissionFilterProvider;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class UnitTest {
private static final Logger logger = new StreamLoggerImpl();
private static final String TEST_DATE = "2017-08-25";
private static Database getTestDatabase() throws IOException {
//create a local SchemaService
final Configuration configuration = Configuration.getInstance();
final String schemaDir = "src/test/resources";
final SchemaService schemaService = SchemaServiceFactory.getLocalInstance(configuration, schemaDir);
//create the OnDiskQueryDatabase
final Path rootPath = Files.createTempDirectory(Paths.get(Configuration.getInstance().getWorkspacePath()), "UnitTest");
final File rootFile = rootPath.toFile();
final LocalTablePathManager pathManager = new LocalTablePathManager(rootFile);
final TableDataService tableDataService = new LocalTableDataService(pathManager);
final OnDiskQueryDatabase db = new OnDiskQueryDatabase(logger, rootFile, tableDataService, schemaService);
//start the OnDiskQueryDatabase and set a user context
db.startup();
Configuration.getInstance().setProperty("IrisDB.permissionFilterProvider", "null");
PermissionFilterProvider.FACTORY.reload();
db.setUserContext(null, new SimpleUserContext("nobody", "nobody"));
//add the test data
addData(db);
return db;
}
private static void addData(final Database db) throws IOException {
final Table t = TableTools.readCsv(new File("src/test/resources/StockTrades.csv"));
db.addTablePartition("Example", "StockTrades", TEST_DATE, t);
}
@Test
public void testQuery() throws IOException {
final Database db = getTestDatabase();
final Table testResult = QueryUtils.getAvgStockPriceTable(db, TEST_DATE);
final double sumAAPL = testResult.where("USym = `AAPL`").getColumn("Last").getDouble(0);
Assertions.assertEquals(159.472, sumAAPL, 0.0002);
final double sumGOOG = testResult.where("USym = `GOOG`").getColumn("Last").getDouble(0);
Assertions.assertEquals(923.56, sumGOOG, 0.0002);
}
}
Connect to a remote DB
Client applications can connect to Deephaven server installations to run queries on a remote database.
The application must be configured to use the program files downloaded by the Deephaven Launcher. Below is an example VM configuration on a Mac:
-DConfiguration.rootFile=iris-defaults.prop
-Ddevroot=<user home>/iris/.programfiles/<instance>/
-Dworkspace=<user home>/iris/workspaces/<instance>/RemoteDatabaseExample/
-Ddh.config.client.bootstrap=<user home>/iris/.programfiles/<instance>/dh-config/clients
-DWAuthenticationClientManager.defaultPrivateKeyFile=<user home>/Documents/priv-<user>.base64.txt
-Dtls.truststore=<user home>/iris/.programfiles/<instance>/resources/truststore-iris.p12
-Dtls.passphrase.file=<user home>/iris/.programfiles/<instance>/resources/truststore_passphrase
-DlogDir=<user home>/code/GradleTest/tmp/logs
Note
- See How to connect to Deephaven from another Java program for more information on these configuration options and for how to set up the private key for authentication.
- See Client Configuration for more information about
dh.config.client.bootstrap
.
Inside the application, the first step will be to create a RemoteQueryClient
and push the required
classes. This makes it so that the remote server can use your local classes. We use the same QueryUtils
as before
in this example.
The RemoteQueryClient
is then used to create the RemoteDatabase
.
// Create a Deephaven query client
final RemoteQueryClient rqc;
try {
rqc = new RemoteQueryClient();
} catch (IOException e) {
throw new UncheckedIOException("Failed to create RemoteQueryClient", e);
}
/*
* Push the QueryUtils class to the worker. This class will be needed by
* by the worker when executeQuery() is called.
*/
try {
rqc.pushClasses(QueryUtils.class);
} catch (IOException e) {
throw new UncheckedIOException("Failed to push QueryUtils class", e);
}
// Create a connection to the remote query server specified by RemoteQueryDispatcherParameters.host
final RemoteDatabase db;
try {
db = rqc.getRemoteDB(RemoteProcessingRequest.DEFAULT_MAX_HEAP_SIZE_MB, PROCESS_NAME, RemoteProcessingRequest.DEFAULT_WORKER_DEBUG_ENABLED);
} catch (IOException e) {
throw new UncheckedIOException("Failed to create RemoteDatabase", e);
}
The RemoteDatabase
may be queried with ad-hoc method calls (db.i
, db.t
, etc.), comparable to the db
variable in a Deephaven
Console. Because the methods are being called against the RemoteDatabase locally in the client application, each
operation requires a round-trip between the client and the worker. For infrequent or very ad-hoc use, this may be fine;
for applications where a query will be executed repeatedly, better performance can be achieved by using a
ContextAwareRemoteQuery
object to allow the method calls to be made as part of a single execution call from the client
to the worker.
Example of a ContextAwareRemoteQuery:
import com.fishlib.configuration.Configuration;
import com.fishlib.io.log.LogLevel;
import com.fishlib.io.logger.DelegatingLoggerImpl;
import com.fishlib.io.logger.Logger;
import com.fishlib.logger.ProcessUnsafeLogCreator;
import com.fishlib.net.impl.nio.NIODriver;
import com.fishlib.util.process.ProcessEnvironment;
import com.illumon.iris.db.tables.Table;
import com.illumon.iris.db.tables.databases.Database;
import com.illumon.iris.db.tables.remote.RemoteDatabase;
import com.illumon.iris.db.tables.remotequery.ContextAwareRemoteQuery;
import com.illumon.iris.db.tables.remotequery.RemoteProcessingRequest;
import com.illumon.iris.db.tables.remotequery.RemoteQueryClient;
import com.illumon.iris.db.tables.remotequery.RemoteQueryUtils;
import com.illumon.iris.db.tables.utils.DBTimeUtils;
import com.illumon.iris.db.tables.utils.TableTools;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.UncheckedIOException;
/**
* Simple example for executing a {@link ContextAwareRemoteQuery} against a Deephaven intraday table and partition.
*
* This example creates a Deephaven database connection (RemoteDatabase), and also creates an inner
* query class to allow the query steps to be executed as a single request to the query server.
* The query class extends ContextAwareRemoteQuery, and an instance of this class is then passed
* to the RemoteDatabase executeQuery method to execute the contained query and return the result.
*
* For a simpler example that uses ad-hoc method calls against the RemoteDatabase object to execute
* the same query, see RemoteDatabaseExample.java.
*/
public class CARQExample {
private static final String PROCESS_NAME = "CARQExample";
private static void prepareEnvironment() {
// the Configuration object reads the property file, which has named key-value pairs that control the
// operation of the system.
final Configuration configuration = Configuration.getInstance();
// the log object is used by Deephaven components, and produces output in a PROCESS_NAME.log.<date> with
// a hard link to PROCESS_NAME.log.current (e.g., DemoIntegration.log.current). The log files are stored
// in <workspace>/../logs
final Logger log = new ProcessUnsafeLogCreator(PROCESS_NAME, configuration).createLogger(PROCESS_NAME, LogLevel.INFO);
// All log output should be sent to the Logger we created on the line above
DelegatingLoggerImpl.setDelegate(log);
// The Deephaven system uses a wrapper around Java NIO for most network communication and job scheduling, this
// initializes the communications subsystem with our log
NIODriver.init(log);
// The ProcessEnvironment provides hooks for consistent startup and shutdown initialization across processes.
ProcessEnvironment.basicInteractiveProcessInitialization(configuration, PROCESS_NAME, log);
}
/**
* This static inner class extends ContextAwareRemoteQuery to provide a query class that is specifically
* designed to execute {@link QueryUtils#getAvgStockPriceTable(Database, String)}
*
* This class must also be available to the query worker, so the worker will be able to resolve it when
* executeQuery is called. This can be done by deploying this class in a jar to the query server
* or by pushing it to the worker. This example pushes it to the worker. See the rqc.pushClasses
* call, below.
*/
public static class GetAveragePrices extends ContextAwareRemoteQuery<Table> {
private final String date;
/**
* Classes that extend ContextAwareRemoteQuery must override execute. This
* is where the specific query goes that we want to execute. Note that only
* the Database object is passed in here (it is passed in by the executeQuery
* method called against the RemoteDatabase). Other parameters must be defined
* as class variables that are set by the class constructor.
*/
@Override
public Table execute(Database db) {
return QueryUtils.getAvgStockPriceTable(db, date).select();
}
/**
* The class constructor, which takes the parameters needed for this query;
* these parameter values will be used when execute() is called.
*
* @param date Namespace in which to find the table
*/
public GetAveragePrices(final String date) {
this.date = date;
}
}
/**
* Run a sample query to get the average prices of stocks for a given day.
*
* @param args 1: The date to use. If not specified, will use currentDateNy.
*/
public static void main(@NotNull final String... args) {
// Parse parameter values from the command line
final String date;
if (args.length > 0) {
date = args[0];
} else {
date = DBTimeUtils.currentDateNy();
}
final long overallStartNanos = System.nanoTime();
// Set up logging and process management
prepareEnvironment();
// Create a Deephaven query client
final RemoteQueryClient rqc;
try {
rqc = new RemoteQueryClient();
} catch (IOException e) {
throw new UncheckedIOException("Failed to create RemoteQueryClient", e);
}
/*
* Push the QueryUtils class to the worker. This class will be needed by
* by the worker when executeQuery() is called.
*/
try {
rqc.pushClasses(QueryUtils.class);
} catch (IOException e) {
throw new UncheckedIOException("Failed to push QueryUtils class", e);
}
// Create a connection to the remote query server specified by RemoteQueryDispatcherParameters.host
final RemoteDatabase db;
try {
db = rqc.getRemoteDB(RemoteProcessingRequest.DEFAULT_MAX_HEAP_SIZE_MB, PROCESS_NAME, RemoteProcessingRequest.DEFAULT_WORKER_DEBUG_ENABLED);
} catch (IOException e) {
throw new UncheckedIOException("Failed to create RemoteDatabase", e);
}
final long startNanos = System.nanoTime();
/*
* Call executeQuery. Within the call, instantiate a new GetAveragePrices query object and pass in
* the parameters that will be needed to execute the query. The executeQuery method will use the
* GetAveragePrices class that was pushed through the RemoteQueryClient session to interpret the query object
* and invoke its execute() method. The execute() method will execute the query and return the resulting Table.
*/
final Table AvgStockPrices;
try {
AvgStockPrices = db.executeQuery(new GetAveragePrices(date));
} catch (IOException e) {
throw new UncheckedIOException("Failed to execute remote query.", e);
}
final long endNanos = System.nanoTime();
// Output the results
System.out.println();
TableTools.show(AvgStockPrices);
System.out.println("Query duration " + (endNanos - startNanos) + " ns");
System.out.println("Overall duration " + (endNanos - overallStartNanos) + " ns");
}
}
Example of an ad-hoc style query:
import com.fishlib.configuration.Configuration;
import com.fishlib.io.log.LogLevel;
import com.fishlib.io.logger.DelegatingLoggerImpl;
import com.fishlib.io.logger.Logger;
import com.fishlib.logger.ProcessUnsafeLogCreator;
import com.fishlib.net.impl.nio.NIODriver;
import com.fishlib.util.process.ProcessEnvironment;
import com.illumon.iris.db.tables.Table;
import com.illumon.iris.db.tables.TableDefinition;
import com.illumon.iris.db.tables.databases.Database;
import com.illumon.iris.db.tables.remote.RemoteDatabase;
import com.illumon.iris.db.tables.remotequery.ContextAwareRemoteQuery;
import com.illumon.iris.db.tables.remotequery.RemoteProcessingRequest;
import com.illumon.iris.db.tables.remotequery.RemoteQueryClient;
import com.illumon.iris.db.tables.utils.DBTimeUtils;
import com.illumon.iris.db.tables.utils.TableTools;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.UncheckedIOException;
/**
* <p>Simple example for executing {@link QueryUtils#getAvgStockPriceTable(Database, String)}
* against a remote Deephaven database.</p>
*
* <p>This example creates a database connection (RemoteDatabase), and uses its methods ad-hoc,
* comparably to how these methods are used in a Deephaven console session (db.i, db.t, etc).</p>
*
* <p>Because the methods are being called against the RemoteDatabase locally in this client application,
* each operation requires a round-trip between the client and the worker that is associated with the
* session. For infrequent or very ad-hoc use, this may be fine; for applications where a query
* will be executed repeatedly, better performance can be achieved by using a ContextAwareRemoteQuery
* object to allow the method calls to be made as part of a single execution call from the client
* to the worker. The CARQExample class example performs the same query as this example does,
* but does it using a ContextAwareRemoteQuery.</p>
*/
public class RemoteDatabaseExample {
private static final String PROCESS_NAME = "RemoteDatabaseExample";
private static void prepareEnvironment() {
// the Configuration object reads the property file, which has named key-value pairs that control the
// operation of the system.
final Configuration configuration = Configuration.getInstance();
// the log object is used by Deephaven components, and produces output in a PROCESS_NAME.log.<date> with
// a hard link to PROCESS_NAME.log.current (e.g., DemoIntegration.log.current). The log files are stored
// in <workspace>/../logs
final Logger log = new ProcessUnsafeLogCreator(PROCESS_NAME, configuration).createLogger(PROCESS_NAME, LogLevel.INFO);
// All log output should be sent to the Logger we created on the line above
DelegatingLoggerImpl.setDelegate(log);
// The Deephaven system uses a wrapper around Java NIO for most network communication and job scheduling, this
// initializes the communications subsystem with our log
NIODriver.init(log);
// The ProcessEnvironment provides hooks for consistent startup and shutdown initialization across processes.
ProcessEnvironment.basicInteractiveProcessInitialization(configuration, PROCESS_NAME, log);
}
/**
* Run a sample query to get the average prices of stocks for a given day.
*
* @param args 1: The date to use. If not specified, the query will use currentDateNy.
*/
public static void main(@NotNull final String... args) {
// Parse parameter values from the command line
final String date;
if (args.length > 0) {
date = args[0];
} else {
date = DBTimeUtils.currentDateNy();
}
final long overallStartNanos = System.nanoTime();
// Set up logging and process management
prepareEnvironment();
// Create a Deephaven query client
final RemoteQueryClient rqc;
try {
rqc = new RemoteQueryClient();
} catch (IOException e) {
throw new UncheckedIOException("Failed to create RemoteQueryClient", e);
}
/*
* Push the QueryUtils class to the worker. This class will be needed by
* by the worker when executeQuery() is called.
*/
try {
rqc.pushClasses(QueryUtils.class);
} catch (IOException e) {
throw new UncheckedIOException("Failed to push QueryUtils class", e);
}
// Create a connection to the remote query server specified by RemoteQueryDispatcherParameters.host
final RemoteDatabase db;
try {
db = rqc.getRemoteDB(RemoteProcessingRequest.DEFAULT_MAX_HEAP_SIZE_MB, PROCESS_NAME, RemoteProcessingRequest.DEFAULT_WORKER_DEBUG_ENABLED);
} catch (IOException e) {
throw new UncheckedIOException("Failed to create RemoteDatabase", e);
}
final Table AvgStockPrices = QueryUtils.getAvgStockPriceTable(db, date);
// Output the results
TableTools.show(AvgStockPrices);
}
}