Summary: Filters are interceptors inside the GigaSpaces space engine that enable integration with external systems and implementation of user-defined logic based on space events.

Overview

Filters are interceptors inside the GigaSpaces space engine that enable integration with external systems and/or implementation of user-defined logic based on space events.

The filter business logic impacts the space responsiveness to client requests - please make sure your filter implementation will not involve heavy logic. With concurrent access into the space all clients share the same filter instance object where the space engine access the same filter object on behalf of each client. Please make sure that every non thread safe attributes you use as part of the filter implementation will be thread-safe protected.

A filter is an instance of a class that implements the ISpaceFilter interface (com.j_spaces.core.filters.ISpaceFilter; seeJavadoc ).

When performing operations using transactions (write, update, or take with a transaction object), the space filter callbacks are called when the operation is called, and not when the transaction commit/rollback is called.

Review and consider using the recommended OpenSpaces space filter support.

com.j_spaces.core.filters.ISpaceFilter Interface

Return value method
void close()
when the space is closed gracefully, all active filters close method is called to allow cleaning any open resources.
void init (IJSpace space, String filterId, String url, int priority)
When a space initializes, it instantiates all the filters defined as part of its schema file and calls the init method on each one. The init method provides an opportunity for the filter to initialize itself. The arguments of the init method are:
  • space – a reference to a collocated space proxy. This reference can be used later to operate on the space, although this should be done with extreme care.
  • url – The free string defined as part of the filter definition at the space schema file. This allows passing any data into the filter from external source.
    priority – a number between 0 and 4. Filters with higher priorities will be executed first, i.e., the filters will be executed in ascending order of priority. Security filters (i.e., filters that are defined with <security>true<security> in the space schema) will be executed first in each priority. For example, a BEFORE_WRITE filter with priority 4 will be executed before an AFTER_WRITE filter with priority 3. If a security filter of BEFORE_WRITE is defined with the same priority 4 as a non-security filter, it will be executed first. If a RuntimeException is thrown from the into method during a non-security filter initialization, it is discarded for the lifetime of the current engine run. For a security filter, an exception during initialization will disable the space and prevent its further operation.
void process (SpaceContext context, ISpaceFilterEntry Entry, int operationCode)
This method is called by the engine when an event matching this filter's operation code occurs in the engine. When an operation inside the space triggers a filter, the filter's process method is called with the following arguments:
  • context is passed as the first parameter to process. SpaceContext has a SecurityContext object as one of its public fields. The proxy passes the SpaceContext object to a space method in each call, provided that a SecurityContext has been set (using either the setSecurityContext method on the proxy or the default properties). For operation codes ON_INIT, BEFORE_REMOVE and AFTER_REMOVE, the SpaceContext is always null.
  • entry – a representation of the Entry that caused the space event is passed to the process method as an argument. The Entry is the object or the template object used at the relevant space operation, represented by the
    ISpaceFilterEntry . This argument may be null (e.g., in ON_INIT filters). The ISpaceFilterEntry contains Entry class name, field types and values. It is important to note that if a RuntimeException occurs in BEFORE operations, the space engine aborts the operation. For example, if a BEFORE_WRITE filter throws a RuntimeException, the Entry will not be inserted to the space, and the client will receive this exception. Therefore, the filter developer is responsible for catching any exceptions that will not abort the operation.
  • operationCode – any one of the FilterOperationCodes

    or FilterOperationCodes that triggers the process method. The optional values are the ones defined as part of the filter definition as part of the space schema file.

    BEFORE_WRITE/AFTER_WRITE and BEFORE_UPDATE/AFTER_UPDATE codes are used when calling the writeMultiple()/updateMultiple() respectively. The readMultiple and takeMultiple have their own set of codes.
    FilterOperationCodes with the prefix AFTER (which indicate operations to be performed after a certain space operation) do not work for space operations that use timeouts. For example, if you use the code AFTER_WRITE, and a specific write operation is performed with a timeout, the operation that was supposed to happen after the write is not executed.
    The ON_INIT, BEFORE_REMOVE and AFTER_REMOVE operation codes can be used only in non-security filters, i.e., they receive a null context. For example, a filter with operation code BEFORE_WRITE will be called (its process method will be called) on every Entry that enters the space immediately before it is inserted into the space engine. A filter can be defined to handle several operation codes, for example <operation-code>1,3<operation-code>, if the filter definition activates it in AFTER_WRITE (1) and BEFORE_TAKE (3) trigger-points. When the SET_SECURITY operation occurs (IJSpace.setSecurityContext called) you may modify the passed context to include client local permissions set (see the security*** section) - base on the user and password passed, the filter should set the user permission - i.e call the SecurityContext.setPermissions() with the relevant values:
    context.setPermissions("" + SecurityContext.PERMISSION_WRITE +
     SecurityContext.PERMISSION_READ); // read & write permission
    All other filters should not modify the passed context object.

void process (SpaceContext context, ISpaceFilterEntry [] entries, int operationCode).
This method is called when the IJSpace.replace() is called for the BEFORE_UPDATE and AFTER_UPDATE. The passed Entries array size is 2 and includes the template Entry at the first position at the array and the new entry at the second position at the array. This method is also called for the AFTER_UPDATE event of the IJSpace.update(). The passed Entries array size is 2 and includes the original Entry at the first position at the array and the updated Entry at the second position at the array.

com.j_spaces.core.filters.FilterOperationCodes

The FilterOperationCodes class includes the following operations:

Operation Code Desription
BEFORE_WRITE 0 Called before write, writeMultiple operations
AFTER_WRITE 1 Called after write,writeMultiple operations
BEFORE_READ 2 Called before read, count operations
BEFORE_TAKE 3 Called before take operation
BEFORE_NOTIFY 4 Called before notify registration operation
BEFORE_GETADMIN 5 Called before admin operation operations
SET_SECURITY 6 Called when setting the SecurityContext operation
BEFORE_CLEAN_SPACE 8 Called before clean operation
BEFORE_UPDATE 9 Called before update and updateMultiple operations
AFTER_UPDATE 10 Called after update and updateMultiple operations
BEFORE_READ_MULTIPLE 11 Called before readMultiple operation
AFTER_READ_MULTIPLE 12 Called after readMultiple operation
BEFORE_TAKE_MULTIPLE 13 Called before takeMultiple operation
AFTER_TAKE_MULTIPLE 14 Called after takeMultiple operation
BEFORE_NOTIFY_TRIGGER 15 Called before sending notification operation
AFTER_NOTIFY_TRIGGER 16 Called after sending notification operation
BEFORE_ALL_NOTIFY_TRIGGER 17 Called before sending notification operation
AFTER_ALL_NOTIFY_TRIGGER 18 Called after sending notification operation
ON_INITdeprecated (see warning below) 51 Called when space started
BEFORE_REMOVE 52 Called before entry expires or canceled
AFTER_REMOVE 53 Called after entry expire or canceled

You do not need to use the ON_INIT event. Instead, just implement the logic in the init() method. The result is the same, since the init() method is called at the same time as ON_INIT – before the space starts.

FilterOperationCodes with the prefix AFTER (which indicate operations to be performed after a certain space operation) do not work for space operations that use timeouts. For example, if you use the code AFTER_WRITE, and a specific write operation is performed with a timeout, the operation that was supposed to happen after the Write is not executed.

The BEFORE_NOTIFY_TRIGGER, AFTER_NOTIFY_TRIGGER, BEFORE_ALL_NOTIFY_TRIGGER, and AFTER_ALL_NOTIFY_TRIGGER FilterOperationCodes events provide:

  • Notification statistics infrastructure
  • Durable notifications infrastructure
  • Notification recovery infrastructure
  • BEFORE_NOTIFY_TRIGGER – before a notify trigger operation, indicates that a matched notify template was found for the current Entry event.
  • AFTER_NOTIFY_TRIGGER – after a notify trigger operation, indicates that a notify trigger was successful.
  • BEFORE_ALL_NOTIFY_TRIGGER – before all notify trigger operations, indicates that a notify trigger was successful.
  • AFTER_ALL_NOTIFY_TRIGGER – after all notify trigger operations, indicates that all notify templates that are matched to the current Entry event were triggered, and returned or failed.

init() method guarantees that no one else can access the space before init() is finished.

Space Filter invocation with backup/replica Space

– The space filter context is null for a filter called as a result of a replication event. You can use this as indication to know if this is originated by a client call or replication event. Just make sure your space is secured and you pass the security context credentials for the space proxy via IJSpace.setSecurityContext().
– Update filter operations are not called on a replica space. This will fixed in future versions.

com.j_spaces.core.filters.entry.ISpaceFilterEntry Interface

The ISpaceFilterEntry represents an Entry instance passed to the ISpaceFilter process method implementation. The ISpaceFilterEntry class extends the IFilterEntry that extends the IGSEntry which includes methods that allow you to access the Entry values, class name and other Entry object properties. The ISpaceFilterEntry class does not include the Entry Class methods. To convert the ISpaceFilterEntry class to your Entry object, you should call the ISpaceFilterEntry.getEntry(IJSpace space) method or the ISpaceFilterEntry.getExternalEntry(IJSpace space) method.

Modifying Written Entry or Template

You may modify the written Entry field values before the Entry is stored in the space, using the BEFORE_WRITE event, or you can modify the template field values used when performing a search for a matching Entry, using the BEFORE_READ event.

This allows you to truncate an unnecessary Entry field value, or replace it with some enriched data.

When modifying the template field values, you can construct a different search than the original one constructed by the client. For example, you can aggregate data from multiple Entries as part of a BEFORE_READ event, write the aggregated data into the space, and modify the template to return the aggregated data. This will return the aggregated Entry data to the client, and not the Entry that matches the original template constructed by the client. To modify the written Entry or the template, you should use the IFilterEntry.setFieldValue method.

Introducing Filters to Space

Every space may have a set of filters. The filters are defined using the space schema XML configuration file.

The space invokes the filters and space events based on the operation codes defined as part of the filter <operation-code> value:

<space-config>
          <filters>
                <filter-names>myFilter</filter-names>
                <myFilter>
                     <enabled>true</enabled>
                     <security>false</security>
                     <class>com.pak.myFilter</class>
                     <!-- List of available filter operation codes: -->
                     <!--The operation codes defines the operations in which this filter will be called.-->
                     <!-- 0 - Before write;-->
                     <!-- 1 - After write;-->
                     <!-- 2 - Before read;-->
                     <!-- 3 - Before take;-->
                     <!-- 4 - Before notify;-->
                     <!-- 5 - Before getadmin;-->
                     <!-- 6 - Set security context;-->
                     <!-- 7 - Before get collection;-->
                     <!-- 8 - Before Clean space;-->
                     <!-- 9 - Before update;-->
                     <!-- 10 - After update;-->
                     <!-- 11 - Before read multiple;-->
                     <!-- 12 - After read multiple;-->
                     <!-- 13 - Before take multiple;-->
                     <!-- 14 - After take multiple;-->
                     <!-- 15 - Before notify trigger operation;-->
                     <!-- 16 - After notify trigger operation;-->
                     <!-- 17 - Before all notify trigger operation;-->
                     <!-- 18 - Before all notify trigger operation;-->
                     <!-- the following operation codes can be used ONLY in non-security filters -->
                     <!-- 51 - On init;-->
                     <!-- 52 - Before remove;-->
                     <!-- 53 - After remove;-->
                     <operation-code>0, 2, 3, 4, 6, 8, 9, 11, 13</operation-code>
                     <url>somefreetext</url>
                     <priority>1</priority>
                     <active-when-backup>false</active-when-backup> 
                     <shutdown-space-on-init-failure>true</shutdown-space-on-init-failure>  
                </myFilter>
           </filters>
</space-config>
Element XPath Property Description
<filter-names> space-config.
filters.filter-names
The <filter-names> element contains a comma-separated list of filter names. Following is the configuration of each filter.
<enabled> space-config.
filters.
myFilter.enabled
If the <enabled> tag is false, the filter is disabled.
<security> space-config.
filters.
myFilter.security
Security filters: filters defined with a <security>true<security> tag. SET_SECURITY filter is always defined as a security filter. A security filter (unlike a non-security one) aborts the space operations if its initialization process fails. A security filter executes first within its priority. A security filter always gets a non-null SpaceContext and a non-null SecurityContext within it.
<class> space-config.
filters.
myFilter.class
The filter implementation class. This class must implement the com.j_spaces.core.filters.ISpaceFilter interface.
<operation-code> space-config.
filters.
myFilter.operation-code
The FilterOperationCodes

that are invoked. This is a comma separated value string.

<url> space-config.
filters.
myFilter.url
A free text string passed to the filter init() method.
<priority> space-config.
filters.
myFilter.priority
The filter priority. Values allowed 0-4.
<active-when-backup> space-config.
filters.
myFilter.active-when-backup
Controls the filter's activity mode. When set to false, the filter init method is called, only when the space is in active mode (i.e., the backup space is moved to active mode). When set to true, the filter init() method is also called for spaces running in backup mode.
<shutdown-space-on-init-failure> space-config.
filters.
myFilter.shutdown-space-on-init-failure
shutdown-space-on-init-failure=true shuts down the space in case of a filter initialization failure. Meaning, if the user-defined init() implementation throws any exception (it doesn't matter which exception), this means a failure has occured.

External Space Filter

You can define an ISpaceFilter implementation including its different characteristics (priority, enabled, etc.) externally when constructing an embedded space.

The FilterProvider is set as part of the Properties class (used when calling the SpaceFinder), and wraps the ISpaceFilter implementation and all of its characteristics.

For example:

ISpaceFilter myFilter = new MyFilter(param1, param2);
FilterProvider filterProvider = new FilterProvider("myFilter", myFilter);

Properties props = new Properties();
props.put(Constants.Filter.FILTER_PROVIDERS, new FilterProvider[] {filterProvider}); 

SpaceFinder.find("/./space", props);

Space Filter Example

The DebugFilter class is an AFTER_WRITE filter that counts the number of Entries written per class:

</space-config>
          <filters>
                <filter-names>DebugFilter</filter-names>
                <myFilter>
                     <enabled>true</enabled>
                     <security>false</security>
                     <class>com.j_spaces.examples.filters.DebugFilter</class>
                     <operation-code>1</operation-code>
                     <url>somefreetext</url>
                     <priority>1</priority>
                     <active-when-backup>false</active-when-backup> 
                     <shutdown-space-on-init-failure>true</shutdown-space-on-init-failure>  
                </myFilter>
           </filters>
</space-config>
package com.j_spaces.examples.filters;

import com.j_spaces.core.filters.*;
import com.j_spaces.core.*;
import com.j_spaces.core.filters.entry.*;
import java.util.Hashtable;

/**
* This example demonstrates the use of filters
* in the GigaSpaces(TM) Platform.
*/

public class DebugFilter implements ISpaceFilter
{
  private String m_FilterName;
  private Hashtable m_Hashtable;

  public void close() {}
  public void init(IJSpace space, String filterId, String url, int priority)
  {
     m_FilterName = filterId;
  }

  public void process(SpaceContext context, ISpaceFilterEntry[] entries, int operationCode)
  {}

  public void process(SpaceContext context, ISpaceFilterEntry entry, int operationCode)
  {
    System.out.println(m_FilterName + ": process() called.");

      synchronized(m_Hashtable)
      {
        Integer count = (Integer) m_Hashtable.get(entry.getClassName());
        if (count == null)
          {
            count = new Integer(1);
          }
          else
          {
            count = new Integer(count.intValue() + 1);
          }
        m_Hashtable.put(entry.getClassName(), count);

        System.out.println("Number of instances of class: " + entry.getClassName() + " is: "
        + count.intValue());
      }
  }

}

As with any filter, in order to run the example, you must ensure that the filter class is accessible to the GigaSpaces instance. Besides being public and with a public default (no-arg) constructor, the class must be available via the server classpath. This can be accomplished by adding it to the GigaSpaces classpath in gsInstance - GigaSpaces CLI.

To test the filter, run the ping utility. The number of written entries will be written to the console:

debug-filter: process() called
Number of instances of class: com.j_spaces.cli.PingCommand$Message is: 1
debug-filter: process() called
Number of instances of class: com.j_spaces.cli.PingCommand$Message is: 2
debug-filter: process() called
Number of instances of class: com.j_spaces.cli.PingCommand$Message is: 3
debug-filter: process() called
Number of instances of class: com.j_spaces.cli.PingCommand$Message is: 4
debug-filter: process() called
Number of instances of class: com.j_spaces.cli.PingCommand$Message is: 5

***Link required

GigaSpaces.com - Legal Notice - 3rd Party Licenses - Site Map - API Docs - Forum - Downloads - Blog - White Papers - Contact Tech Writing - Gen. by Atlassian Confluence