Reviews
Oracle CoherenceOracle Coherence: Value and Reflection Extractor
Value extractors
As you can see from the previous examples, a query is typically expressed in terms of object attributes, such as accountId or time, while the evaluate method defined by the Filter interface accepts a whole object that the attributes belong to, such as a Transaction instance.
That implies that we need a generic way to extract attribute values from an object instance--otherwise, there would be no way to define reusable filters, such as the ones in the table earlier that ship with Coherence, and we would be forced to implement a custom filter for each query we need to execute. In order to solve this problem and enable extraction of attribute values from an object, Coherence introduces value extractors.
A value extractor is an object that implements a com.tangosol.util.
ValueExtractor interface:
- public interface ValueExtractor {
- Object extract(Object target)
- }
The sole purpose of a value extractor is to extract a derived value from the target object that is passed as an argument to the extract method. The result could be a single attribute value, a combination of multiple attributes (concatenation of first and last name, for example), or in general, a result of some transformation of a target object.
Reflection extractor
In the vast majority of cases, you will want to extract a value of the single attribute of a target object, in which case you can use the built-in ReflectionExtractor class. The ReflectionExtractor accepts a method name as a constructor argument, invokes the specified method on a target object via reflection, and returns the result of that method invocation.
As a matter of fact, the ReflectionExtractor is used so often that you can simply specify a method name as a string in most places where a value extractor is expected and an instance of a ReflectionExtractor will be created automatically for you, which is what we took advantage of in the previous filter definitions. For example, the filter definition:
- Filter filter = new BetweenFilter("getTime", from, to)
Is really just a shorter form of:
- Filter filter = new BetweenFilter(
- new ReflectionExtractor("getTime"),
- from, to)
I will have to admit that as useful as ReflectionExtractor is, I have never liked it much. The main reason for this is that it forces you to spell out a full method name for an attribute, when a property name, as defined by the Java Bean specification should've been enough and would've made the code more readable. This is especially bothersome when accessing a Coherence cluster from a .NET client, in which case the 'get' prefix in front of the property name truly feels unnatural.
Fortunately, it is easy to fix the problem by implementing a similar value extractor that uses introspection to obtain an attribute value:
- public class PropertyExtractor
- implements ValueExtractor, Serializable {
- private final String m_propertyName
- private transient volatile Method m_readMethod
- public PropertyExtractor(String propertyName) {
- m_propertyName = propertyName
- }
- public Object extract(Object o) {
- if (o == null) {
- return null
- }
- Class targetClass = o.getClass()
- try {
- if (readMethod ==
- null
readMethod.getDeclaringClass() != targetClass) { - PropertyDescriptor pd =
- new PropertyDescriptor(propertyName, o.getClass())
- readMethod = pd.getReadMethod()
- }
- return readMethod.invoke(o)
- }
- catch (Exception e) {
- throw new RuntimeException(e)
- }
- }
- }
Now we can use PropertyExtractor instead of ReflectionExtractor in our filter definitions:
- Filter filter = new BetweenFilter(
- new PropertyExtractor("time"),
- from, to)
In this example the difference is not significant and it could even be argued that the PropertyExtractor makes the code harder to read as we have to specify it explicitly, instead of using a filter constructor that takes string as an argument and creates ReflectionExtractor for us. However, in the next section we will implement a helper class that makes filter creation much simpler, and the PropertyExtractor will allow us to make things as simple as they can be.
Expression languages and value extractors
If you are familiar with any of the popular expression languages, such as MVEL, OGNL, or SpEL, you will notice that I could've easily implemented the previous value extractor using one of them. Not only would that allow me to do a simple property extraction, but I would be able to use much more sophisticated expressions for extraction. Considering that I created SpEL (Spring Expression Language) while working on Spring.NET a few years back, you can imagine that I am a big proponent of their usage. To prove that, I have implemented value extractors for MVEL, OGNL, SpEL, Groovy, and even Java 6 Scripting in Coherence Tools, so you can easily use your favorite EL with Coherence.
Oracle Coherence
- Oracle Coherence 3.5
- Oracle Coherence: Distributed Caching
- Oracle Coherence: In-place and Parallel Processing
- Oracle Coherence: Coherence within the Oracle Ecosystem
- Oracle Coherence: Querying The Data Grid
- Oracle Coherence: Built-in Filters
- Oracle Coherence: Value and Reflection Extractor
- Oracle Coherence: Other built-in value extractors
- Oracle Coherence: Implementing Custom Value Extractor
- Oracle Coherence: Simplifying Coherence Queries
- Oracle Coherence: Obtaining Query Results
- Oracle Coherence: Controlling Query Scope Using Data Affinity
- Oracle Coherence: Querying Near Cache
- Oracle Coherence: Paging Over Query Results
- Oracle Coherence: Anatomy of an Index
- Oracle Coherence: Creating Indexes
- Oracle Coherence: Query Limitations
- Oracle Coherence: Aggregators
- Oracle Coherence: Built-in Aggregators
- Oracle Coherence: Implementing LookupValuesAggregator







