Creating a Java filter

A Java filter consists of two parts: a JSON file to describe the filter and any parameters it might take, and one or more Java classes that implement the filter.

Please download the sample project -- it contains everything you need to get started.

JSON file

The filter is described in a JSON file, which looks like:

{

  "active": true,

  "codeType": "java",

  "implementation": "com.acme.filter.MyFilter",

  "phase": null,

  "canHaveCode": false,

  "helpURL": "https://www.acme.com/docs/MyFilter",

  "tags": [],

  "parameters": {

    "My parameter": {

      "defaultValue":null,

      "description":"This parameter does this and that",

      "type":"STRING",

      "required":false,

      "allowedValues": ["yes", "no", "maybe"]

    }

  }

}

The value of implementation should be the fully qualified name of the main Java class for the filter (the one that implements one of the Filter interfaces).

Parameters are not required, but they can be specified here.  For each parameter:

This JSON file must be named filter.json and must be installed in the Gallium Data metarepo directory under filter_types/<database>/<filter-type>/<filter-name>

For instance:

 filter_types/MySQL/request_filters/MyJavaFilter/filter.json


Java class

A Java filter is a Java class that implements one of these interfaces:

You need to implement both RequestFilter and ResponseFilter to create a duplex filter.

 This class will be invoked by Gallium Data in two ways:


The Java class will need to use the following libraries (here in Maven form):

        <dependency>

            <groupId>galliumdata</groupId>

            <artifactId>galliumdata-filter-library</artifactId>

            <version>1.7.1-1468</version>

        </dependency>

        <dependency>

            <groupId>org.graalvm.sdk</groupId>

            <artifactId>graal-sdk</artifactId>

            <version>22.0.0.2</version>

        </dependency>

        <dependency>

            <groupId>org.apache.logging.log4j</groupId>

            <artifactId>log4j-api</artifactId>

            <version>2.17.2</version>

        </dependency>

Note that the exact versions will depend on which version of Gallium Data you are using.

In addition, you'll need to add the following:

    <repositories>

        <repository>

            <id>gallium-repo</id>

            <url>https://maven.galliumdata.com/</url>

        </repository>

    </repositories>

This will allow Maven to find the galliumdata:galliumdata-filter-library jar.

The configure method

Before Gallium Data invokes a filter, it calls its configure method so that the filter has an opportunity to configure itself. 

This method has the following signature:

public void configure(FilterUse filterUse) 

The FilterUse object contains all the required information about the filter, in particular the value of its parameters (if any). A typical filter will retrieve the values of its parameters and set things up accordingly, for instance:

public class ExampleFilter implements RequestFilter {

    private Pattern userPattern;


    @Override

    public void configure(FilterUse filterUse) {

        String userPatternStr = (String)filterUse.getParameters().get("User pattern");

        if (userPatternStr != null) {

            this.userPattern = Pattern.compile(userPatternStr);

        }

etc...


If the configuration is expensive, you can cache objects in the filterContext:

Variables filterContext = filterUse.getFilterContext();

if (filterContext.containsKey("expensiveThing") {

    // Initialization already done -- reuse the object

    this.expensiveThing = (ExpensiveThing)filterContext.get("expensiveThing");

}

else {

    // Do the expensive initialization

    this.expensiveThing = ...

}


The filter method

The name of the filter method is:

The filter method is invoked with a parameter of type Variables, which contains everything the filter needs. This is the same object that JavaScript code receives as the context object.

The filter method returns a FilterResult object, which must not be null. Returning an empty FilterResult object (i.e. new FilterResult() ) means that execution should continue. Setting the properties of that FilterResult object can change what Gallium Data does with the request. See the Javadoc for FilterResult for details.

Connection filters

Connection filters must implement the method: 

public FilterResult acceptConnection(Socket socket, Variables context)

The Socket object is passed in  so that your filter can read or write from it if needed.

The context object contains:

Request filters

Request filters must implement the filterRequest method:

FilterResult filterRequest(Variables context) 

The context object contains:

Response filters

Response filters must implement the filterResponse method:

FilterResult filterResponse(Variables context)

The context object contains:

Once you have a Java filter that compiles properly, see: