Updated reference and JSON support for GemfireTemplate queries
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
SPRING DATA GEMFIRE CHANGELOG
|
||||
=============================
|
||||
http://www.springsource.org/spring-gemfire
|
||||
Changes in version 1.3.0.RELEASE (2013-02-15)
|
||||
Changes in version 1.3.0.RELEASE (2013-03-14)
|
||||
---------------------------------------------
|
||||
General
|
||||
* Added annotation support for GemFire functions
|
||||
* Added 'datasource' element to gfe-data namespace to simplify client connection
|
||||
|
||||
* Added support for JSON
|
||||
See [release notes](https://jira.springsource.org/secure/ReleaseNote.jspa?projectId=10462&version=13300)
|
||||
|
||||
Changes in version 1.2.1.RELEASE (2012-10-26)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</note>
|
||||
|
||||
<section id="new-in-1-3-0">
|
||||
<title>New in the 1.3.0.Release</title>
|
||||
<title>New in the 1.3.0 Release</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
@@ -29,9 +29,25 @@
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>A <tag><datasource></tag> tag has been added to the
|
||||
<para>We have added a <tag><datasource></tag> tag to the
|
||||
<emphasis>gfe-data</emphasis> XML namespace. This simplifies
|
||||
establishing a basic client <link linkend="data-access:datasource">connection</link> to a GemFire data grid.</para>
|
||||
establishing a basic client <link
|
||||
linkend="data-access:datasource">connection</link> to a GemFire data
|
||||
grid.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>To <link linkend="bootstrap:region:json">support JSON</link> features introduced in GemFire 7.0, we have
|
||||
added a ,<tag><json-region-autoproxy></tag> tag to the <emphasis>gfe-data</emphasis> XML
|
||||
namespace, enabling Spring AOP to perform the necessary conversions
|
||||
automatically on region operations.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Upgraded to GemFire 7.0.1 and added namespace support for new AsyncEventQueue attributes</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Added support for setting subscription interest policy on regions</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
pdx-read-serialized="false"
|
||||
message-sync-interval="1"
|
||||
search-timeout="300"
|
||||
close="false"
|
||||
>
|
||||
<co id="gfe#transaction#listener"/><gfe:transaction-listener ref="myTransactionListener"/>
|
||||
|
||||
|
||||
@@ -3,35 +3,37 @@
|
||||
xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
>
|
||||
<title>Document structure</title>
|
||||
xmlns:ns5="http://www.w3.org/2000/svg"
|
||||
xmlns:ns4="http://www.w3.org/1998/Math/MathML"
|
||||
xmlns:ns3="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ns="http://docbook.org/ns/docbook">
|
||||
<title>Document structure</title>
|
||||
|
||||
<para>The following chapters explain the core functionality offered by
|
||||
Spring Data GemFire.</para>
|
||||
<para>The following chapters explain the core functionality offered by
|
||||
Spring Data GemFire.</para>
|
||||
|
||||
<para><xref linkend="bootstrap"/> describes the configuration support
|
||||
provided for bootstrapping, initializing, configuring, and accessing
|
||||
GemFire caches, cache servers, regions, and related distributed system
|
||||
components</para>
|
||||
<para><xref linkend="bootstrap"/> describes the configuration support
|
||||
provided for bootstrapping, initializing, configuring, and accessing GemFire
|
||||
caches, cache servers, regions, and related distributed system
|
||||
components</para>
|
||||
|
||||
<para><xref linkend="apis"/> explains the integration between the GemFire
|
||||
APIs and the various data access features available in Spring, such as
|
||||
transaction management and exception translation.</para>
|
||||
<para><xref linkend="apis"/> explains the integration between the GemFire
|
||||
APIs and the various data access features available in Spring, such as
|
||||
transaction management and exception translation.</para>
|
||||
|
||||
<para><xref linkend="serialization"/> describes the enhancements for
|
||||
GemFire (de)serialization and management of associated objects.</para>
|
||||
<para><xref linkend="serialization"/> describes the enhancements for GemFire
|
||||
(de)serialization and management of associated objects.</para>
|
||||
|
||||
<para><xref linkend="mapping"/> describes persistence mapping for POJOs
|
||||
stored in GemFire using Spring Data</para>
|
||||
<para><xref linkend="mapping"/> describes persistence mapping for POJOs
|
||||
stored in GemFire using Spring Data</para>
|
||||
|
||||
<para><xref linkend="gemfire-repositories"/> describes how to create and
|
||||
use GemFire Repositories using Spring Data</para>
|
||||
<para><xref linkend="gemfire-repositories"/> describes how to create and use
|
||||
GemFire Repositories using Spring Data</para>
|
||||
|
||||
<para><xref linkend="function-annotations"/> describes how to create and
|
||||
use GemFire Functions using Spring Data</para>
|
||||
<para><xref linkend="function-annotations"/> describes how to create and use
|
||||
GemFire Functions using Spring Data</para>
|
||||
|
||||
<para><xref linkend="samples"/> describes the samples provided with the
|
||||
distribution to illustrate the various features available in Spring
|
||||
GemFire.</para>
|
||||
</chapter>
|
||||
|
||||
<para><xref linkend="samples"/> describes the samples provided with the
|
||||
distribution to illustrate the various features available in Spring Data
|
||||
GemFire.</para>
|
||||
</chapter>
|
||||
|
||||
@@ -125,9 +125,7 @@
|
||||
<title>Common Region Attributes</title>
|
||||
|
||||
<para>The following table(s) list attributes available for various
|
||||
region types:
|
||||
<table
|
||||
id="bootstrap:region:common:attributes:table">
|
||||
region types: <table id="bootstrap:region:common:attributes:table">
|
||||
<title>Common Region Attributes</title>
|
||||
|
||||
<tgroup cols="3">
|
||||
@@ -163,7 +161,7 @@
|
||||
<entry>close</entry>
|
||||
|
||||
<entry spanname="values">
|
||||
<emphasis>boolean, default:true</emphasis>
|
||||
<emphasis>boolean, default:false (Note: The default was true prior to 1.3.0)</emphasis>
|
||||
</entry>
|
||||
|
||||
<entry spanname="description">Indicates whether the region
|
||||
@@ -499,7 +497,17 @@
|
||||
<para>This is discussed further in <xref
|
||||
linkend="bootstrap-diskstore"/></para>
|
||||
</section>
|
||||
<section id="bootstrap:region:subscription">
|
||||
<title>Subscription Interest Policy</title>
|
||||
|
||||
<para>GemFire allows configuration of subscriptions to control <ulink url="http://pubs.vmware.com//vfabricNoSuite/topic/com.vmware.vfabric.gemfire.7.0/developing/events/configure_p2p_event_messaging.html">peer to peer event handling</ulink>.
|
||||
Spring Data GemFire provides a <tag><gfe:subscription/></tag> to set the interest policy on replicated and partitioned regions to either <literal>ALL</literal> or <literal>CACHE_CONTENT</literal>.
|
||||
</para>
|
||||
|
||||
<programlisting language="xml"><gfe:partitioned-region id="subscription-partition">
|
||||
<gfe:subscription type="CACHE_CONTENT"/>
|
||||
</gfe:partitioned-region></programlisting>
|
||||
</section>
|
||||
<section id="bootstrap:region:eviction">
|
||||
<title>Data Eviction and Overflowing</title>
|
||||
|
||||
@@ -782,7 +790,7 @@ and a nested resolver declaration -->
|
||||
client region while the latter defines connection pools to be used/shared
|
||||
by the various client regions.</para>
|
||||
|
||||
<para>Below is a typical client region configuration:</para>
|
||||
<para>Below is a typical client region configuration:G</para>
|
||||
|
||||
<programlisting language="xml"><!-- client region using the default client-cache pool -->
|
||||
<gfe:client-region id="simple">
|
||||
@@ -847,4 +855,30 @@ and a nested resolver declaration -->
|
||||
details.</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="bootstrap:region:json">
|
||||
<title>JSON Support</title>
|
||||
|
||||
<para>Gemfire 7.0 introduced support for caching JSON documents with OQL
|
||||
query support. These are stored internally as <ulink url="http://www.vmware.com/support/developer/vfabric-gemfire/700-api/com/gemstone/gemfire/pdx/PdxInstance.html">PdxInstance</ulink> types using the
|
||||
<ulink url="http://www.vmware.com/support/developer/vfabric-gemfire/700-api/com/gemstone/gemfire/pdx/JSONFormatter.html">JSONFormatter</ulink> to perform conversion to and from JSON strings. Spring Data
|
||||
GemFire provides a <tag><gfe-data:json-region-autoproxy/></tag> tag to enable a
|
||||
<ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/htmlsingle/#aop-introduction">Spring AOP</ulink> component to advise appropropriate region operations, effectively
|
||||
encapsulating the JSONFormatter, allowing your application to work directly
|
||||
with JSON strings. In addition, Java objects written to JSON configured regions will
|
||||
be automatically converted to JSON using the Jackson ObjectMapper. Reading these values will return a JSON string.
|
||||
</para>
|
||||
<para>
|
||||
By default, <tag><gfe-data:json-region-autoproxy/></tag> will perform the conversion on all regions. To apply this feature to selected regions, provide a comma delimited list of
|
||||
their ids via the <literal>region-refs</literal> attribute. Other attributes include a
|
||||
<literal>pretty-print</literal> flag (false by default) and <literal>convert-returned-collections</literal>. By default the results of region
|
||||
operations getAll() and values() will be converted for configured
|
||||
regions. This is done by creating a parallel structure in local memory. This can incur significant overhead for large collections. Set this
|
||||
flag to false to disable automatic conversion for these operation.
|
||||
<note>Certain region operations, specifically those that use GemFire's proprietary Region.Entry such as entries(boolean), entrySet(boolean) and getEntry()
|
||||
type are not targeted for AOP advice. In addition, the entrySet() method which returns a Set<java.util.Map.Entry<?,?>> is not affected.</note>
|
||||
</para>
|
||||
<para>This feature also works with seamlessly with GemfireTemplate operations, currently native QueryService operations are not supported.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.gemfire;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
import com.gemstone.gemfire.cache.query.Query;
|
||||
import com.gemstone.gemfire.cache.query.QueryService;
|
||||
import com.gemstone.gemfire.cache.query.SelectResults;
|
||||
|
||||
/**
|
||||
* @author David Turanski
|
||||
*
|
||||
*/
|
||||
public interface GemfireOperations {
|
||||
|
||||
public abstract boolean containsKey(Object key);
|
||||
|
||||
public abstract boolean containsKeyOnServer(Object key);
|
||||
|
||||
public abstract boolean containsValue(Object value);
|
||||
|
||||
public abstract boolean containsValueForKey(Object key);
|
||||
|
||||
public abstract <K, V> void create(K key, V value);
|
||||
|
||||
public abstract <K, V> V get(K key);
|
||||
|
||||
public abstract <K, V> V put(K key, V value);
|
||||
|
||||
public abstract <K, V> V putIfAbsent(K key, V value);
|
||||
|
||||
public abstract <K, V> V remove(K key);
|
||||
|
||||
public abstract <K, V> V replace(K key, V value);
|
||||
|
||||
public abstract <K, V> boolean replace(K key, V oldValue, V newValue);
|
||||
|
||||
public abstract <K, V> Map<K, V> getAll(Collection<?> keys);
|
||||
|
||||
public abstract <K, V> void putAll(Map<? extends K, ? extends V> map);
|
||||
|
||||
/**
|
||||
* Shortcut for {@link Region#query(String)} method. Filters the values of this region using the predicate given as a string with the syntax of the WHERE clause of the query language.
|
||||
* The predefined variable this may be used inside the predicate to denote the current element being filtered.
|
||||
* This method evaluates the passed in where clause and returns results. It is supported on servers as well as clients.
|
||||
* When executed on a client, this method always runs on the server and returns results.
|
||||
* When invoking this method from the client, applications can pass in a where clause or a complete query.
|
||||
|
||||
* @see Region#query(String)
|
||||
* @param query A query language boolean query predicate.
|
||||
* @return A SelectResults containing the values of this Region that match the predicate.
|
||||
*/
|
||||
public abstract <E> SelectResults<E> query(String query);
|
||||
|
||||
/**
|
||||
* Executes a GemFire query with the given (optional) parameters and returns the result. Note this method expects the query to return multiple results; for queries that return only one
|
||||
* element use {@link #findUnique(String, Object...)}.
|
||||
* <p/>
|
||||
* As oppose, to the {@link #query(String)} method, this method allows for more generic queries (against multiple regions even) to be executed.
|
||||
*
|
||||
* <p/>Note that the local query service is used if the region is configured as a client without any pool configuration or server connectivity - otherwise the query service on the default pool
|
||||
* is being used.
|
||||
*
|
||||
* @see QueryService#newQuery(String)
|
||||
* @see Query#execute(Object[])
|
||||
* @see SelectResults
|
||||
* @param query GemFire query
|
||||
* @param params Values that are bound to parameters (such as $1) in this query.
|
||||
* @return A {@link SelectResults} instance holding the objects matching the query
|
||||
* @throws InvalidDataAccessApiUsageException in case the query returns a single result (not a {@link SelectResults}).
|
||||
*/
|
||||
public abstract <E> SelectResults<E> find(String query, Object... params) throws InvalidDataAccessApiUsageException;
|
||||
|
||||
/**
|
||||
* Executes a GemFire query with the given (optional) parameters and returns the result. Note this method expects the query to return a single result; for queries that return multiple
|
||||
* elements use {@link #find(String, Object...)}.
|
||||
* <p/>
|
||||
* As oppose, to the {@link #query(String)} method, this method allows for more generic queries (against multiple regions even) to be executed.
|
||||
*
|
||||
* <p/>Note that the local query service is used if the region is configured as a client without any pool configuration or server connectivity - otherwise the query service on the default pool
|
||||
* is being used.
|
||||
*
|
||||
* @see QueryService#newQuery(String)
|
||||
* @see Query#execute(Object[])
|
||||
* @param query GemFire query
|
||||
* @param params Values that are bound to parameters (such as $1) in this query.
|
||||
* @return The (single) object that represents the result of the query.
|
||||
* @throws InvalidDataAccessApiUsageException in case the query returns multiple objects (through {@link SelectResults}).
|
||||
*/
|
||||
public abstract <T> T findUnique(String query, Object... params) throws InvalidDataAccessApiUsageException;
|
||||
|
||||
public abstract <T> T execute(GemfireCallback<T> action) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute the action specified by the given action object within a
|
||||
* Region.
|
||||
* @param action callback object that specifies the Gemfire action
|
||||
* @param exposeNativeRegion whether to expose the native
|
||||
* GemFire region to callback code
|
||||
* @return a result object returned by the action, or <code>null</code>
|
||||
* @throws org.springframework.dao.DataAccessException in case of GemFire errors
|
||||
*/
|
||||
public abstract <T> T execute(GemfireCallback<T> action, boolean exposeNativeRegion) throws DataAccessException;
|
||||
|
||||
}
|
||||
@@ -55,7 +55,7 @@ import com.gemstone.gemfire.internal.cache.LocalRegion;
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class GemfireTemplate extends GemfireAccessor {
|
||||
public class GemfireTemplate extends GemfireAccessor implements GemfireOperations {
|
||||
|
||||
private boolean exposeNativeRegion = false;
|
||||
|
||||
@@ -96,6 +96,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
return this.exposeNativeRegion;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#containsKey(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean containsKey(final Object key) {
|
||||
return execute(new GemfireCallback<Boolean>() {
|
||||
public Boolean doInGemfire(Region<?,?> region) throws GemFireCheckedException, GemFireException {
|
||||
@@ -104,6 +108,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#containsKeyOnServer(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean containsKeyOnServer(final Object key) {
|
||||
return execute(new GemfireCallback<Boolean>() {
|
||||
public Boolean doInGemfire(Region<?,?> region) throws GemFireCheckedException, GemFireException {
|
||||
@@ -112,6 +120,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#containsValue(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean containsValue(final Object value) {
|
||||
return execute(new GemfireCallback<Boolean>() {
|
||||
public Boolean doInGemfire(Region<?,?> region) throws GemFireCheckedException, GemFireException {
|
||||
@@ -120,6 +132,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#containsValueForKey(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean containsValueForKey(final Object key) {
|
||||
return execute(new GemfireCallback<Boolean>() {
|
||||
public Boolean doInGemfire(Region<?,?> region) throws GemFireCheckedException, GemFireException {
|
||||
@@ -128,6 +144,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#create(K, V)
|
||||
*/
|
||||
@Override
|
||||
public <K, V> void create(final K key, final V value) {
|
||||
execute(new GemfireCallback<Object>() {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@@ -138,6 +158,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#get(K)
|
||||
*/
|
||||
@Override
|
||||
public <K, V> V get(final K key) {
|
||||
return execute(new GemfireCallback<V>() {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@@ -147,6 +171,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#put(K, V)
|
||||
*/
|
||||
@Override
|
||||
public <K, V> V put(final K key, final V value) {
|
||||
return execute(new GemfireCallback<V>() {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@@ -156,6 +184,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#putIfAbsent(K, V)
|
||||
*/
|
||||
@Override
|
||||
public <K, V> V putIfAbsent(final K key, final V value) {
|
||||
return execute(new GemfireCallback<V>() {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@@ -165,6 +197,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#remove(K)
|
||||
*/
|
||||
@Override
|
||||
public <K, V> V remove(final K key) {
|
||||
return execute(new GemfireCallback<V>() {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@@ -174,6 +210,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#replace(K, V)
|
||||
*/
|
||||
@Override
|
||||
public <K, V> V replace(final K key, final V value) {
|
||||
return execute(new GemfireCallback<V>() {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@@ -183,6 +223,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#replace(K, V, V)
|
||||
*/
|
||||
@Override
|
||||
public <K, V> boolean replace(final K key, final V oldValue, final V newValue) {
|
||||
return execute(new GemfireCallback<Boolean>() {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@@ -192,6 +236,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#getAll(java.util.Collection)
|
||||
*/
|
||||
@Override
|
||||
public <K, V> Map<K, V> getAll(final Collection<?> keys) {
|
||||
return execute(new GemfireCallback<Map<K, V>>() {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@@ -201,6 +249,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#putAll(java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public <K, V> void putAll(final Map<? extends K, ? extends V> map) {
|
||||
execute(new GemfireCallback<Object>() {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@@ -211,17 +263,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for {@link Region#query(String)} method. Filters the values of this region using the predicate given as a string with the syntax of the WHERE clause of the query language.
|
||||
* The predefined variable this may be used inside the predicate to denote the current element being filtered.
|
||||
* This method evaluates the passed in where clause and returns results. It is supported on servers as well as clients.
|
||||
* When executed on a client, this method always runs on the server and returns results.
|
||||
* When invoking this method from the client, applications can pass in a where clause or a complete query.
|
||||
|
||||
* @see Region#query(String)
|
||||
* @param query A query language boolean query predicate.
|
||||
* @return A SelectResults containing the values of this Region that match the predicate.
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#query(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public <E> SelectResults<E> query(final String query) {
|
||||
return execute(new GemfireCallback<SelectResults<E>>() {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@@ -231,23 +276,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a GemFire query with the given (optional) parameters and returns the result. Note this method expects the query to return multiple results; for queries that return only one
|
||||
* element use {@link #findUnique(String, Object...)}.
|
||||
* <p/>
|
||||
* As oppose, to the {@link #query(String)} method, this method allows for more generic queries (against multiple regions even) to be executed.
|
||||
*
|
||||
* <p/>Note that the local query service is used if the region is configured as a client without any pool configuration or server connectivity - otherwise the query service on the default pool
|
||||
* is being used.
|
||||
*
|
||||
* @see QueryService#newQuery(String)
|
||||
* @see Query#execute(Object[])
|
||||
* @see SelectResults
|
||||
* @param query GemFire query
|
||||
* @param params Values that are bound to parameters (such as $1) in this query.
|
||||
* @return A {@link SelectResults} instance holding the objects matching the query
|
||||
* @throws InvalidDataAccessApiUsageException in case the query returns a single result (not a {@link SelectResults}).
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#find(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public <E> SelectResults<E> find(final String query, final Object... params)
|
||||
throws InvalidDataAccessApiUsageException {
|
||||
return execute(new GemfireCallback<SelectResults<E>>() {
|
||||
@@ -265,22 +297,10 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a GemFire query with the given (optional) parameters and returns the result. Note this method expects the query to return a single result; for queries that return multiple
|
||||
* elements use {@link #find(String, Object...)}.
|
||||
* <p/>
|
||||
* As oppose, to the {@link #query(String)} method, this method allows for more generic queries (against multiple regions even) to be executed.
|
||||
*
|
||||
* <p/>Note that the local query service is used if the region is configured as a client without any pool configuration or server connectivity - otherwise the query service on the default pool
|
||||
* is being used.
|
||||
*
|
||||
* @see QueryService#newQuery(String)
|
||||
* @see Query#execute(Object[])
|
||||
* @param query GemFire query
|
||||
* @param params Values that are bound to parameters (such as $1) in this query.
|
||||
* @return The (single) object that represents the result of the query.
|
||||
* @throws InvalidDataAccessApiUsageException in case the query returns multiple objects (through {@link SelectResults}).
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#findUnique(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public <T> T findUnique(final String query, final Object... params) throws InvalidDataAccessApiUsageException {
|
||||
return execute(new GemfireCallback<T>() {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@@ -289,8 +309,13 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
Query q = queryService.newQuery(query);
|
||||
Object result = q.execute(params);
|
||||
if (result instanceof SelectResults) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
SelectResults<T> selectResults = (SelectResults<T>)result;
|
||||
if (selectResults.asList().size() == 1) {
|
||||
result = selectResults.iterator().next();
|
||||
} else {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"Result object returned from GemfireCallback isn't unique: [" + result + "]");
|
||||
}
|
||||
}
|
||||
return (T) result;
|
||||
}
|
||||
@@ -314,19 +339,18 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#execute(org.springframework.data.gemfire.GemfireCallback)
|
||||
*/
|
||||
@Override
|
||||
public <T> T execute(GemfireCallback<T> action) throws DataAccessException {
|
||||
return execute(action, isExposeNativeRegion());
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the action specified by the given action object within a
|
||||
* Region.
|
||||
* @param action callback object that specifies the Gemfire action
|
||||
* @param exposeNativeRegion whether to expose the native
|
||||
* GemFire region to callback code
|
||||
* @return a result object returned by the action, or <code>null</code>
|
||||
* @throws org.springframework.dao.DataAccessException in case of GemFire errors
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.GemfireOperations#execute(org.springframework.data.gemfire.GemfireCallback, boolean)
|
||||
*/
|
||||
@Override
|
||||
public <T> T execute(GemfireCallback<T> action, boolean exposeNativeRegion) throws DataAccessException {
|
||||
Assert.notNull(action, "Callback object must not be null");
|
||||
try {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.data.gemfire.support;
|
||||
|
||||
import org.springframework.dao.support.DaoSupport;
|
||||
import org.springframework.data.gemfire.GemfireOperations;
|
||||
import org.springframework.data.gemfire.GemfireTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -37,7 +38,7 @@ import com.gemstone.gemfire.cache.Region;
|
||||
*/
|
||||
public class GemfireDaoSupport extends DaoSupport {
|
||||
|
||||
private GemfireTemplate gemfireTemplate;
|
||||
private GemfireOperations gemfireTemplate;
|
||||
|
||||
/**
|
||||
* Sets the GemFire Region to be used by this DAO.
|
||||
@@ -57,7 +58,7 @@ public class GemfireDaoSupport extends DaoSupport {
|
||||
* @return the new GemfireTemplate instance
|
||||
* @see #setRegion
|
||||
*/
|
||||
protected GemfireTemplate createGemfireTemplate(Region<?, ?> region) {
|
||||
protected GemfireOperations createGemfireTemplate(Region<?, ?> region) {
|
||||
return new GemfireTemplate(region);
|
||||
}
|
||||
|
||||
@@ -66,7 +67,7 @@ public class GemfireDaoSupport extends DaoSupport {
|
||||
* as an alternative to specifying a GemFire {@link Region}.
|
||||
* @see #setRegion
|
||||
*/
|
||||
public final void setGemfireTemplate(GemfireTemplate gemfireTemplate) {
|
||||
public final void setGemfireTemplate(GemfireOperations gemfireTemplate) {
|
||||
this.gemfireTemplate = gemfireTemplate;
|
||||
}
|
||||
|
||||
@@ -74,7 +75,7 @@ public class GemfireDaoSupport extends DaoSupport {
|
||||
* Return the GemfireTemplate for this DAO, pre-initialized
|
||||
* with the Region or set explicitly.
|
||||
*/
|
||||
public final GemfireTemplate getGemfireTemplate() {
|
||||
public final GemfireOperations getGemfireTemplate() {
|
||||
return gemfireTemplate;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,12 @@ import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.springframework.data.gemfire.GemfireTemplate;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
import com.gemstone.gemfire.cache.query.SelectResults;
|
||||
import com.gemstone.gemfire.cache.query.internal.ResultsBag;
|
||||
import com.gemstone.gemfire.pdx.JSONFormatter;
|
||||
import com.gemstone.gemfire.pdx.PdxInstance;
|
||||
|
||||
@@ -84,7 +87,6 @@ public class JSONRegionAdvice {
|
||||
+ "execution(* com.gemstone.gemfire.cache.Region.putIfAbsent(..)) ||"
|
||||
+ "execution(* com.gemstone.gemfire.cache.Region.replace(..))")
|
||||
public Object put(ProceedingJoinPoint pjp) {
|
||||
System.out.println("intercepted " + pjp.getSignature().getName());
|
||||
|
||||
boolean JSONRegion = isIncludedSONRegion(pjp.getTarget());
|
||||
Object retVal = null;
|
||||
@@ -94,6 +96,8 @@ public class JSONRegionAdvice {
|
||||
Object val = newArgs[1];
|
||||
newArgs[1] = convertArgumentToPdxInstance(val);
|
||||
retVal = pjp.proceed(newArgs);
|
||||
log.debug("converting " + retVal + " to JSON string");
|
||||
retVal = convertPdxInstanceToJSONString(retVal);
|
||||
} else {
|
||||
retVal = pjp.proceed();
|
||||
}
|
||||
@@ -128,22 +132,22 @@ public class JSONRegionAdvice {
|
||||
}
|
||||
|
||||
@Around("execution(* com.gemstone.gemfire.cache.Region.get(..)) "
|
||||
+ "|| execution(* com.gemstone.gemfire.cache.Region.selectValue(..))")
|
||||
+ "|| execution(* com.gemstone.gemfire.cache.Region.selectValue(..))"
|
||||
+ "|| execution(* com.gemstone.gemfire.cache.Region.remove(..))")
|
||||
public Object get(ProceedingJoinPoint pjp) {
|
||||
Object retVal = null;
|
||||
try {
|
||||
if (isIncludedSONRegion(pjp.getTarget())) {
|
||||
retVal = pjp.proceed();
|
||||
log.debug("converting " + retVal + " to JSON string");
|
||||
return convertPdxInstanceToJSONString(retVal);
|
||||
retVal = convertPdxInstanceToJSONString(retVal);
|
||||
} else {
|
||||
return pjp.proceed();
|
||||
retVal = pjp.proceed();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
handleThrowable(t);
|
||||
}
|
||||
return retVal;
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -185,6 +189,35 @@ public class JSONRegionAdvice {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Around("execution(* org.springframework.data.gemfire.GemfireOperations.find(..)) " +
|
||||
"|| execution(* org.springframework.data.gemfire.GemfireOperations.findUnique(..)) " +
|
||||
"|| execution(* org.springframework.data.gemfire.GemfireOperations.query(..))")
|
||||
public Object templateQuery(ProceedingJoinPoint pjp) {
|
||||
GemfireTemplate template = (GemfireTemplate) pjp.getTarget();
|
||||
boolean jsonRegion = isIncludedSONRegion(template.getRegion());
|
||||
Object retVal = null;
|
||||
try {
|
||||
if (jsonRegion) {
|
||||
retVal = pjp.proceed();
|
||||
if (retVal instanceof SelectResults && convertReturnedCollections ) {
|
||||
ResultsBag resultsBag = new ResultsBag();
|
||||
for (Object obj: (SelectResults<?>)retVal) {
|
||||
resultsBag.add(convertPdxInstanceToJSONString(obj));
|
||||
}
|
||||
retVal = resultsBag;
|
||||
} else {
|
||||
retVal = convertPdxInstanceToJSONString(retVal);
|
||||
}
|
||||
} else {
|
||||
retVal = pjp.proceed();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
handleThrowable(t);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
private PdxInstance convertArgumentToPdxInstance(Object value) {
|
||||
PdxInstance val = null;
|
||||
@@ -220,9 +253,9 @@ public class JSONRegionAdvice {
|
||||
Object result = retVal;
|
||||
if (retVal != null && retVal instanceof PdxInstance) {
|
||||
result = JSONFormatter.toJSON((PdxInstance) retVal);
|
||||
}
|
||||
if (!prettyPrint) {
|
||||
result = flattenString(result);
|
||||
if (!prettyPrint) {
|
||||
result = flattenString(result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public class GemfireTemplateTest {
|
||||
|
||||
private static final String SINGLE_QUERY = "(select * from /simple).size";
|
||||
|
||||
@Autowired GemfireTemplate template;
|
||||
@Autowired GemfireOperations template;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Before
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.data.gemfire.GemfireOperations;
|
||||
import org.springframework.data.gemfire.GemfireTemplate;
|
||||
|
||||
/**
|
||||
@@ -30,7 +31,7 @@ public class GemfireDaoSupportTests extends TestCase {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void testGemfireDaoSupportWithTemplate() throws Exception {
|
||||
GemfireTemplate template = new GemfireTemplate();
|
||||
GemfireOperations template = new GemfireTemplate();
|
||||
final List test = new ArrayList();
|
||||
GemfireDaoSupport dao = new GemfireDaoSupport() {
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -24,14 +24,16 @@ import javax.annotation.Resource;
|
||||
|
||||
import org.codehaus.jackson.JsonGenerationException;
|
||||
import org.codehaus.jackson.map.JsonMappingException;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.gemfire.GemfireOperations;
|
||||
import org.springframework.data.gemfire.repository.sample.Person;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
import com.gemstone.gemfire.cache.query.SelectResults;
|
||||
|
||||
/**
|
||||
* @author David Turanski
|
||||
@@ -40,17 +42,28 @@ import com.gemstone.gemfire.cache.Region;
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class JSONRegionAdviceTest {
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Resource(name="someRegion")
|
||||
private Region region;
|
||||
|
||||
@Autowired
|
||||
GemfireOperations template;
|
||||
|
||||
@Test
|
||||
public void testPutString() {
|
||||
String json = "{\"hello\":\"world\"}";
|
||||
|
||||
region.put("key",json);
|
||||
Object result = region.put("key",json);
|
||||
assertEquals(json,result);
|
||||
|
||||
region.create("key2",json);
|
||||
|
||||
System.out.println(region.get("key"));
|
||||
assertEquals(json,region.get("key"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testPutAll() {
|
||||
Map<String,String> map = new HashMap<String,String>();
|
||||
@@ -69,6 +82,32 @@ public class JSONRegionAdviceTest {
|
||||
region.put("dave",dave);
|
||||
String json = (String)region.get("dave");
|
||||
assertEquals(json,"{\"id\":1,\"firstname\":\"Dave\",\"lastname\":\"Turanski\",\"address\":null}",json);
|
||||
Object result = region.put("dave",dave);
|
||||
assertEquals("{\"id\":1,\"firstname\":\"Dave\",\"lastname\":\"Turanski\",\"address\":null}",result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateFindUnique() {
|
||||
Person dave = new Person(1L,"Dave","Turanski");
|
||||
region.put("dave",dave);
|
||||
String json = (String) template.findUnique("Select * from /someRegion where firstname=$1","Dave");
|
||||
assertEquals("{\"id\":1,\"firstname\":\"Dave\",\"lastname\":\"Turanski\",\"address\":null}",json);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateFind() {
|
||||
Person dave = new Person(1L,"Dave","Turanski");
|
||||
region.put("dave",dave);
|
||||
SelectResults<String> results = template.find("Select * from /someRegion where firstname=$1","Dave");
|
||||
assertEquals("{\"id\":1,\"firstname\":\"Dave\",\"lastname\":\"Turanski\",\"address\":null}",results.iterator().next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateQuery() {
|
||||
Person dave = new Person(1L,"Dave","Turanski");
|
||||
region.put("dave",dave);
|
||||
SelectResults<String> results = template.query("firstname='Dave'");
|
||||
assertEquals("{\"id\":1,\"firstname\":\"Dave\",\"lastname\":\"Turanski\",\"address\":null}",results.iterator().next());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,18 +7,18 @@
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
|
||||
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd">
|
||||
|
||||
|
||||
<gfe:cache/>
|
||||
<gfe:replicated-region id="replicALL">
|
||||
<gfe:subscription type="ALL"/>
|
||||
</gfe:replicated-region>
|
||||
|
||||
|
||||
<gfe:partitioned-region id="partCACHE_CONTENT">
|
||||
<gfe:subscription type="CACHE_CONTENT"/>
|
||||
<gfe:eviction threshold="70"/>
|
||||
</gfe:partitioned-region>
|
||||
|
||||
|
||||
|
||||
|
||||
<gfe:partitioned-region id="partDEFAULT">
|
||||
<gfe:subscription/>
|
||||
</gfe:partitioned-region>
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
<!-- <bean class="org.springframework.data.gemfire.support.JSONRegionAdvice" /> -->
|
||||
|
||||
<gfe:cache properties-ref="props"/>
|
||||
<gfe:replicated-region id="someRegion" />
|
||||
|
||||
<gfe:replicated-region id="someRegion"/>
|
||||
|
||||
<bean id="template" class="org.springframework.data.gemfire.GemfireTemplate">
|
||||
<constructor-arg ref="someRegion"/>
|
||||
</bean>
|
||||
</beans>
|
||||
|
||||
Reference in New Issue
Block a user