Exforsys

Home arrow Reviews arrow Oracle Coherence

Oracle Coherence: Value and Reflection Extractor

Author: Packt Publishing     Published on: 27th Jun 2010

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.

Ads

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:

Sample Code
  1.     public interface ValueExtractor {
  2.       Object extract(Object target)
  3.     }
Copyright exforsys.com


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:

Sample Code
  1.     Filter filter = new BetweenFilter("getTime", from, to)
Copyright exforsys.com


Is really just a shorter form of:

Sample Code
  1.     Filter filter = new BetweenFilter(
  2.                          new ReflectionExtractor("getTime"),
  3.                          from, to)
Copyright exforsys.com


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:

Sample Code
  1.     public class PropertyExtractor
  2.                  implements ValueExtractor, Serializable {
  3.  
  4.       private final String m_propertyName
  5.       private transient volatile Method m_readMethod
  6.  
  7.       public PropertyExtractor(String propertyName) {
  8.         m_propertyName = propertyName
  9.         }
  10.  
  11.         public Object extract(Object o) {
  12.           if (o == null) {
  13.             return null
  14.           }
  15.  
  16.             Class targetClass = o.getClass()
  17.             try {
  18.               if (readMethod ==
  19.                       null readMethod.getDeclaringClass() != targetClass) {
  20.                 PropertyDescriptor pd =
  21.                           new PropertyDescriptor(propertyName, o.getClass())
  22.                 readMethod = pd.getReadMethod()
  23.               }
  24.               return readMethod.invoke(o)
  25.             }
  26.             catch (Exception e) {
  27.               throw new RuntimeException(e)
  28.             }
  29.         }
  30.     }
Copyright exforsys.com


Now we can use PropertyExtractor instead of ReflectionExtractor in our filter definitions:

Sample Code
  1.     Filter filter = new BetweenFilter(
  2.                          new PropertyExtractor("time"),
  3.                          from, to)
Copyright exforsys.com


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.

Ads

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.



 
This tutorial is part of a Oracle Coherence tutorial series. Read it from the beginning and learn yourself.

Oracle Coherence

 

Comments