diff --git a/docs/src/reference/docbook/reference/cq-container.xml b/docs/src/reference/docbook/reference/cq-container.xml new file mode 100644 index 00000000..63e752b8 --- /dev/null +++ b/docs/src/reference/docbook/reference/cq-container.xml @@ -0,0 +1,134 @@ + +
+ GemFire Continuous Query Container + + A powerful functionality offered by GemFire is + continuous querying (or CQ). + In short, CQ allows one to create a query and automatically be notified when new data that gets added to GemFire matches the query. + + Spring GemFire provides dedicated support for CQs through the org.springframework.data.gemfire.listener package and + its listener container; very similar in functionality + and naming to the JMS integration in Spring Framework; in fact, users familiar with the JMS support in Spring, should + feel right at home. Basically SGF allows methods on POJOs to become end-points for CQ - simply define the query and indicate the method + that should be notified when there is a match - SGF takes care of the rest. This of Java EE's message-driven bean style, but without any + requirement for base class or interface implementations, based on GemFire. + + + Currently, continuous queries are supported by GemFire only in client/server topologies. Additionally the pool used is required to have the + subscription property enabled. Please refer to the documentation for more information. + + +
+ Continuous Query Listener Container + + SGF simplifies the creation, registration, life-cycle and dispatch of CQs by taking care of the infrastructure around them through + ContinuousQueryListenerContainer which does all the heavy lifting on behalf of the user - + users familiar with EJB and JMS should find the concepts familiar as it is designed as close as possible to the + support in Spring Framework and its message-driven POJOs (MDPs) + + ContinuousQueryListenerContainer acts as an event (or message) listener container; it is used to receive the events + from the registered CQs and drive the POJOs that are injected into it. The listener container is responsible for all threading of message + reception and dispatches into the listener for processing. It acts as the intermediary between an EDP (Event Driven POJO) and the event provider + and takes care of creation and registration of CQs (to receive events), resource acquisition and release, exception conversion and suchlike. + This allows you as an application developer to write the (possibly complex) business logic associated with receiving an event (and reacting to it), + and delegates boilerplate GemFire infrastructure concerns to the framework. + + + The container is fully customizable - one can chose either to use the CQ thread to perform the dispatch (synchronous delivery) or a new thread + (from an existing pool for examples) for an asynch approach by defining the suitable java.util.concurrent.Executor + (or Spring's TaskExecutor). Depending on the load, the number of listeners or the runtime + environment, one should change or tweak the executor to better serve her needs - in particular in managed environments (such as app servers), it is + highly recommended to pick a a proper TaskExecutor to take advantage of its runtime. +
+ +
+ The <classname>ContinuousQueryListenerAdapter</classname> and <interfacename>ContinuousQueryListener</interfacename> + + The ContinuousQueryListenerAdapter class is the + final component in SGF CQ support: in a nutshell, it allows you to expose almost any class + as a EDP (there are of course some constraints) - it implements ContinuousQueryListener, a simpler listener interface + similar to GemFire CqListener. + + Consider the following interface definition. Notice the + various event handling methods and their parameters: + + public interface EventDelegate { + void handleEvent(CqEvent event); + void handleEvent(Operation baseOp); + void handleEvent(Object key); + void handleEvent(Object key, Object newValue); + void handleEvent(Throwable th); + void handleQuery(CqQuery cq); + void handleEvent(CqEvent event, Operation baseOp, byte[] deltaValue); + void handleEvent(CqEvent event, Operation baseOp, Operation queryOp, Object key, Object newValue); +} + + public class DefaultEventDelegate implements EventDelegate { + // implementation elided for clarity... +} + + In particular, note how the above implementation of the + EventDelegate interface (the above + DefaultEventDelegate class) has + no GemFire dependencies at all. It truly is a POJO that + we will make into an EDP via the following configuration (note that the class doesn't have to implement an interface, + one is present only to better show case the decoupling between contract and implementation). + + <?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:gfe="http://www.springframework.org/schema/gemfire" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd"> + + + <gfe:client-cache pool-name="client"/> + + <gfe:pool id="client" subscription-enabled="true"> + <gfe:server host="localhost" port="40404"/> + </gfe:pool> + + <gfe:cq-listener-container> + <!-- default handle method --> + <gfe:listener ref="listener" query="SELECT * from /region"/ > + <gfe:listener ref="another-listener" query="SELECT * from /another-region" name="my-query" method="handleQuery"/> + </gfe:cq-listener-container> + + <bean id="listener" class="gemfireexample.DefaultMessageDelegate"/> + <bean id="another-listener" class="gemfireexample.DefaultMessageDelegate"/> + ... +<beans> + The example above shows some of the various forms that a listener can have; at its minimum the listener reference and the actual query definition are required. It's possible however to specify + a name for the resulting continuous query (useful for monitoring) but also the name of the method (the default is handleEvent). The specified method can have various + argument types, the EventDelegate interface lists the allowed types. + + The example above uses the SGF namespace to declare the event listener container and automatically register the POJOs as listeners. The full blown, beans definition + is displayed below: + + <!-- this is the Event Driven POJO (MDP) --> +<bean id="eventListener" class="org.springframework.data.gemfire.listener.adapter.ContinuousQueryListenerAdapter"> + <constructor-arg> + <bean class="gemfireexample.DefaultEventDelegate"/> + </constructor-arg> +</bean> + +<!-- and this is the event listener container... --> +<bean id="gemfireListenerContainer" class="org.springframework.data.gemfire.listener.ContinuousQueryListenerContainer"> + <property name="cache" ref="gemfire-cache"/> + <property name="queryListeners"> + <!-- set of listeners --> + <set> + <bean class="org.springframework.data.gemfire.listener.ContinuousQueryDefinition" > + <constructor-arg value="SELECT * from /region" /> + <constructor-arg ref="eventListener" /> + </bean> + </set> + </property> +</bean> + + Each time an event is received, the adapter automatically performs + type translation between the GemFire event and the required method argument(s) transparently. Any exception caused by the method invocation + is caught and handled by the container (by default, being logged). + +
+
\ No newline at end of file diff --git a/docs/src/reference/docbook/reference/data.xml b/docs/src/reference/docbook/reference/data.xml index e7a815aa..4fbc4017 100644 --- a/docs/src/reference/docbook/reference/data.xml +++ b/docs/src/reference/docbook/reference/data.xml @@ -1,5 +1,5 @@ - + Working with the GemFire APIs Once the GemFire cache and regions have been configured they can @@ -136,6 +136,8 @@ url="http://www.gemstone.com/docs/6.0.1/product/docs/japi/com/gemstone/gemfire/cache/CacheTransactionManager.html">documentation. + +
Wiring <interfacename>Declarable</interfacename> components