Interceptors
The Space Filter implementation may use the following interceptors. The relevant method should be annotated with the annotation listed below. The signature of these methods may include the following parameters:
Parameter | Description | Type |
---|---|---|
First Parameter | Space Template for before read or before take / Space object for after read/after take/write/update | Object |
Second Parameter | Operation Type | int |
Third Parameter | Security Context. Passed with a secured space. | SpaceContext |
Annotation List:
Filter Annotation | Description | Operation Type |
---|---|---|
AfterAllNotifyTrigger | Filter callback after all notify trigger. | 18 |
AfterNotifyTrigger | Filter callback after notify trigger. | 16 |
AfterReadMultiple | Filter callback after read multiple operation. Called for each matching object. | 12 |
AfterRemoveByLease | Filter callback after an entry was removed due to lease expression or lease cancel. | 53 |
AfterTakeMultiple | Filter callback after take multiple operation. Called for each matching object. | 14 |
AfterUpdate | Filter callback after update operation. | 10 |
AfterWrite | Filter callback after write operation. | 1 |
BeforeAllNotifyTrigger | Filter callback before all notify trigger. | 17 |
BeforeAuthentication | Filter callback before authentication. | 6 |
BeforeCleanSpace | Filter callback after clean space operation. | 8 |
BeforeExecute | Filter callback before execute operation. | 20 |
AfterExecute | Filter callback after execute operation. | 23 |
BeforeNotify | Filter callback before notify operation. | 4 |
BeforeNotifyTrigger | Filter callback before notify trigger. | 15 |
BeforeRead | Filter callback before read operation. | 2 |
AfterRead | Filter callback after read operation. | 21 |
BeforeReadMultiple | Filter callback before read multiple operation. | 11 |
BeforeRemoveByLease | Filter callback before an entry was removed due to lease expression or lease cancel. | 52 |
BeforeTake | Filter callback before take operation. | 3 |
AfterTake | Filter callback after take operation. | 22 |
BeforeTakeMultiple | Filter callback before take multiple operation. | 13 |
BeforeUpdate | Filter callback before update operation. | 9 |
BeforeWrite | Filter callback before write operation. | 0 |
BeforeChange | Filter callback before change operation. | 24 |
AfterChange | Filter callback after change operation. Called for each matching object. | 25 |
OnFilterClose | A callback method when the filter is closed. | |
OnFilterInit | A callback method when the filter is initialized. | 51 |
The space filter business logic impacts the space responsiveness to client requests - please make sure your filter implementation will not involve heavy business 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. Every non-thread safe attributes you use as part of the filter implementation will be thread-safe protected.
Example
The following example illustrates a space Filter POJO and a Bean that performs some space operations:
package com.test;
import org.openspaces.core.GigaSpace;
import org.openspaces.core.context.GigaSpaceLateContext;
import org.openspaces.core.space.filter.AfterAllNotifyTrigger;
import org.openspaces.core.space.filter.AfterNotifyTrigger;
import org.openspaces.core.space.filter.AfterReadMultiple;
import org.openspaces.core.space.filter.AfterRemoveByLease;
import org.openspaces.core.space.filter.AfterTakeMultiple;
import org.openspaces.core.space.filter.AfterWrite;
import org.openspaces.core.space.filter.BeforeAllNotifyTrigger;
import org.openspaces.core.space.filter.BeforeExecute;
import org.openspaces.core.space.filter.BeforeNotify;
import org.openspaces.core.space.filter.BeforeNotifyTrigger;
import org.openspaces.core.space.filter.BeforeRead;
import org.openspaces.core.space.filter.BeforeReadMultiple;
import org.openspaces.core.space.filter.BeforeTake;
import org.openspaces.core.space.filter.BeforeTakeMultiple;
import org.openspaces.core.space.filter.BeforeWrite;
import org.openspaces.core.space.filter.OnFilterClose;
import org.openspaces.core.space.filter.OnFilterInit;
import org.springframework.beans.factory.InitializingBean;
public class MySpaceFilter implements InitializingBean{
//late context is needed since there's a circular dependency between the filter bean and the space itself
@GigaSpaceLateContext
GigaSpace space;
@OnFilterInit
void init() {
System.out.println("MySpaceFilter Space Filter initialized");
}
@OnFilterClose
void close() {
System.out.println("Closing Space Filter");
}
@BeforeWrite
public void beforeWrite(Object spaceObject) {
System.out.println("beforeWrite called" + spaceObject);
}
@AfterWrite
public void afterWrite(Object echo) {
System.out.println("afterWrite called" + echo);
}
@BeforeRead
public void beforeRead(Object spaceTemplate) {
System.out.println("beforeRead called" + spaceTemplate);
}
@AfterRemoveByLease
public void afterRemoveByLease(Object spaceObject) {
System.out.println("afterRemoveByLease called" + spaceObject);
}
@BeforeTake
public void beforeTake(Object spaceTemplate) {
System.out.println("beforeTake called " + spaceTemplate);
}
@BeforeReadMultiple
public void beforeReadMultiple(Object spaceTemplate) {
System.out.println("beforeReadMultiple called - Template:" + spaceTemplate);
}
@AfterReadMultiple
public void afterReadMultiple(Object spaceObject) {
System.out.println("afterReadMultiple called - Space Object:" + spaceObject);
}
@BeforeTakeMultiple
public void beforeTakeMultiple(Object spaceTemplate) {
System.out.println("beforeTakeMultiple called - Template:" + spaceTemplate);
}
@AfterTakeMultiple
public void afterTakeMultiple(Object spaceObject) {
System.out.println("afterTakeMultiple called - Space Object:" + spaceObject);
}
@BeforeExecute
public void beforeExecute(Object task) {
System.out.println("beforeExecute called " + task);
}
@BeforeNotify
public void beforeNotify(Object spaceObject) {
System.out.println("beforeNotify called " + spaceObject);
}
@AfterAllNotifyTrigger
public void afterAllNotifyTrigger(Object spaceObject) {
System.out.println("afterAllNotifyTrigger called " + spaceObject);
}
@BeforeAllNotifyTrigger
public void beforeAllNotifyTrigger(Object spaceObject) {
System.out.println("beforeAllNotifyTrigger called " + spaceObject);
}
@AfterNotifyTrigger
public void AfterNotifyTrigger(Object spaceTemplate) {
System.out.println("afterNotifyTrigger called " + spaceTemplate);
}
@BeforeNotifyTrigger
public void beforeNotifyTrigger(Object spaceTemplate) {
System.out.println("beforeNotifyTrigger called " + spaceTemplate);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("space "+space);
}
}
package com.test;
import org.openspaces.core.GigaSpace;
import org.openspaces.core.context.GigaSpaceContext;
import org.openspaces.events.adapter.SpaceDataEvent;
import org.openspaces.events.notify.SimpleNotifyContainerConfigurer;
import org.openspaces.events.notify.SimpleNotifyEventListenerContainer;
import org.springframework.beans.factory.InitializingBean;
import com.j_spaces.core.LeaseContext;
public class MyBean implements InitializingBean{
@GigaSpaceContext
GigaSpace space;
@Override
public void afterPropertiesSet() throws Exception {
Message m = new Message();
m.setId("1");
m.setData("AAAA");
System.out.println("Calling write");
LeaseContext<Message> lc = space.write(m);
line();
System.out.println("Calling read");
Message m1 = space.read(new Message());
line();
System.out.println("Calling lease cancel");
lc.cancel();
line();
System.out.println("Calling write");
space.write(m);
line();
System.out.println("Calling readMultiple");
Message m1Array[] =space.readMultiple(new Message(), Integer.MAX_VALUE);
line();
System.out.println("Calling take");
Message m2 = space.take(new Message());
line();
System.out.println("Calling write");
space.write(m);
line();
System.out.println("Calling takeMultiple");
Message m2Array[] =space.takeMultiple(new Message(), Integer.MAX_VALUE);
line();
System.out.println("Calling execute");
space.execute(new MyTask());
Thread.sleep(1000);
line();
System.out.println("Calling Notify Registration");
SimpleNotifyEventListenerContainer notifyEventListenerContainer =
new SimpleNotifyContainerConfigurer(space)
.template(new Message())
.notifyWrite(true)
.eventListenerAnnotation(new Object() {
@SpaceDataEvent
public void eventHappened() {
System.out.println("SpaceDataEvent event called");
}
}).notifyContainer();
notifyEventListenerContainer.start();
Thread.sleep(1000);
line();
System.out.println("Calling write");
space.write(m);
Thread.sleep(2000);
}
static void line()
{
System.out.println("-------------------------");
}
}
<bean id="mySpaceFilter" class="com.test.MySpaceFilter" />
<bean id="myBean" class="com.test.MyBean" />
<os-core:embedded-space id="space" space-name="space" >
<os-core:annotation-adapter-filter priority="2">
<os-core:filter ref="mySpaceFilter" />
</os-core:annotation-adapter-filter>
</os-core:embedded-space>
<os-core:giga-space id="gigaSpace" space="space"/>
<os-core:giga-space-context/>
<os-core:giga-space-late-context />
package com.test;
import com.gigaspaces.annotation.pojo.SpaceClass;
import com.gigaspaces.annotation.pojo.SpaceId;
@SpaceClass
public class Message {
String id;
String data;
public Message (){}
@SpaceId
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String toString() {
return " Class Message - Object ID:" + id + " data:" + data;
}
}
package com.test;
import java.io.Serializable;
import org.openspaces.core.executor.Task;
public class MyTask implements Task<Serializable>{
@Override
public Serializable execute() throws Exception {
return null;
}
}
MySpaceFilter Space Filter initialized
INFO [com.gigaspaces.core.common] - Space [space_container:space] with url
[/./space?schema=default&groups=gigaspaces-7.1.0-XAPPremium-rc&state=started] started successfully
space space_container:space
Calling write
beforeWrite called Class Message - Object ID:1 data:AAAA
afterWrite called Class Message - Object ID:1 data:AAAA
-------------------------
Calling read
beforeRead called Class Message - Object ID:null data:null
-------------------------
Calling lease cancel
afterRemoveByLease called Class Message - Object ID:1 data:AAAA
-------------------------
Calling write
beforeWrite called Class Message - Object ID:1 data:AAAA
afterWrite called Class Message - Object ID:1 data:AAAA
-------------------------
Calling readMultiple
beforeReadMultiple called - Template: Class Message - Object ID:null data:null
afterReadMultiple called - Space Object: Class Message - Object ID:1 data:AAAA
-------------------------
Calling take
beforeTake called Class Message - Object ID:null data:null
afterRemoveByLease called Class Message - Object ID:1 data:AAAA
-------------------------
Calling write
beforeWrite called Class Message - Object ID:1 data:AAAA
afterWrite called Class Message - Object ID:1 data:AAAA
-------------------------
Calling takeMultiple
beforeTakeMultiple called Template: Class Message - Object ID:null data:null
afterRemoveByLease called Class Message - Object ID:1 data:AAAA
afterTakeMultiple called Space Object:Class Message - Object ID:1 data:AAAA
-------------------------
Calling execute
beforeExecute called com.test.MyTask@9e4585
-------------------------
Calling Notify Registration
beforeNotify called Class Message - Object ID:null data:null
-------------------------
Calling write
beforeWrite called Class Message - Object ID:1 data:AAAA
afterWrite called Class Message - Object ID:1 data:AAAA
beforeAllNotifyTrigger called Class Message - Object ID:1 data:AAAA
beforeNotifyTrigger called Class Message - Object ID:1 data:AAAA
SpaceDataEvent event called
afterNotifyTrigger called Class Message - Object ID:1 data:AAAA
afterAllNotifyTrigger called Class Message - Object ID:1 data:AAAA
Advanced Options
A filter is an instance of a class that implements the ISpaceFilter
interface (com.j_spaces.core.filters.ISpaceFilter
; see Javadoc.
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.
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 is 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.- filterId ist he name of this filter. - url is 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 is a number between 0 and 4. Filters with higher priorities will be executed first, meaning the filters will be executed in ascending order of priority. For example, a BEFORE_WRITE filter with priority 4 will be executed before an AFTER_WRITE filter with priority 3. If a RuntimeException is thrown from the into method during filter initialization, it is discarded for the lifetime of the current engine run. |
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. It may be null for a non-secured Space. SpaceContext has a SecurityContext object as one of its public fields. The proxy passes the SpaceContext object to a Space method in each call (except for replication and recovery). For operation codes ON_INIT , BEFORE_REMOVE and AFTER_REMOVE , the SpaceContext is always null .- entry is a representation of the Entry that caused the Space event, and 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 theISpaceFilterEntry. This argument may be null (for example, in ON_INIT filters). The ISpaceFilterEntry contains the Entry class name, field types and values. 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 is not inserted to the Space, and the client receives this exception. Therefore, the filter developer is responsible for catching any exceptions that will not abort the operation.- operationCode is 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. 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 work for space operations that use timeouts - if the space operation was successfully performed.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. |
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. |
FilterOperationCodes
The FilterOperationCodes class includes the all the filter code you may use.
Use the init()
method to initialize the filter. This method is called before the space fully starts. The init()
method guarantees that no one else can access the space before init()
is finished.
FilterOperationCodes
with the prefix AFTER
(which indicate operations to be performed after a certain space operation) are not called for space operations that use timeouts. For example, if you use the code AFTER_READ
, and a specific read operation is performed with a timeout, the operation that was supposed to happen after the read will not be 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.
Space Filter invocation with backup/replica Space
The space filter context is null
for a filter called as a result of a replication event. For secured space, you can use this as indication to know if this operation originated by a client call or replication event.
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 Space Object 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.