JavaScript environment

When writing code for a filter, you can define variables and functions as in any other JavaScript environment:

function f() {
log.debug("f has been called");
}

var a = "AA";
let b = 123.45;
const c = true;

These variables are short-lived: they will disappear as soon as the execution of the filter ends.


Long-term variables

For longer-term storage, which should live longer than just one execution of a filter, you can use:

  • context.filterContext : variables defined in this object are visible to any execution of that filter, and will live as long as Gallium Data is running, or until a new version of the project is published. Useful when the filter needs to initialize something at first execution, which can be cached in this object.

  • context.connectionContext : variables defined in this object are visible to all filters for that particular database connection. They will disappear when that database connection is closed.

  • context.projectContext : variables defined in this object are visible to all filters in the project. This is as close to "global" variables as you can get. These variables will disappear whenever you publish a new version of the project.

  • context.threadContext : variables defined in this object are only visible to the invocation of this filter on the current thread. This is useful when dealing with Java objects that are not thread-safe. This object is shared by all filters running on this thread. These variables will disappear whenever a thread is terminated, which is (conceptually) at the end of a connection.

When storing objects in these contexts (except context.threadContext), keep in mind that these objects might get accessed from multiple threads, and therefore need to be thread-safe. Also it's easy to create race conditions in which multiple threads compete to write or change a value.

Also, don't forget that anything you store in these objects takes up memory space. Be careful about storing large objects for a long time, especially if you want your filters to be able to scale and run many times in parallel.

Finally, if you are running multiple copies of Gallium Data (like in a Kubernetes environment), the different instances of Gallium Data do not communicate with each other, so even a variable set in context.projectContext will not be visible in other instances of Gallium Data.


Do not store JavaScript objects in long-lived contexts

Because of limitations in the underlying JavaScript engine, you should not store JavaScript objects or functions in these long-lived contexts. For instance, it might be tempting to do:

// Don't do this
context.connectionContext.status = {
this: 123,
that: "something",
the_other: {...}
};

If you do this, when you access that variable from a different invocation of the filter, you will most likely get an exception complaining about accessing a Value across threads. You can store strings, numbers and booleans, but nothing more complex. Java objects are fine.

If you want to store an object-like structure in a long-lived context, use context.utils.createObject(), e.g.:

let ctxt = context.connectionContext;
ctxt.status = context.utils.createObject();
ctxt.status.this = 123;
ctxt.status.that = "something";
ctxt.status.the_other = context.utils.createObject();
etc...

There is one exception to this rule: you can, in fact, store JavaScript objects in context.threadContext, since (by definition) it is only ever available from one thread.


log

The main way to log messages, fully documented on this page.


context

An object that contains a number of variables, depending on the exact filter type.


context.packet

The current packet being processed before it gets sent to its final destination. The exact type of the packet depends on the database type, and the parameters specified for the filter.


context.packets

A container of packets, which normally contains only the current packet. This is made available so that you add new packets to the request or response.


context.row

This is only defined for result set filters. This variable contains a row (for relational databases) or object (for non-relational databases), which can be modified or hidden before it is returned to the database client.


Using Java classes

Your JavaScript code has full access to the underlying Java platform. Consult the GraalVM documentation for much more information.