Per-select Caching for MyBatis

Posted: August 21st, 2011 | Author: | Filed under: Distributed Caching

Good news: We’ve just added support for per-select caching for MyBatis to our open source Java cache Cacheonix that addresses major problems with default MyBatis caching.

Problems With Default MyBatis Caching

There are a few problems with the way caching works in MyBatis:

  • MyBatis keeps results of all selects in a single, namespace-wide, cache. This means any invalidation caused by inserts or updates will flush cached results of all selects, including those that are really not affected by the changes.
  • It is impossible to ignore invalidation completely and to have pure time-only expiration for some selects.
  • It is impossible to have different cache configurations for particular selects.

Benefits of Cacheonix Adapter for MyBatis

Cacheonix have addressed these concerns by adding the following features:

  1. Per-select MyBatis caches
  2. Ability to turn off invalidation
  3. Ability to turn off namespace cache
  4. Cache templates for select caches

For more information and examples check Cacheonix documentation: Configuring MyBatis Cache Adapter.

Enjoy!

Regards,

Slava Imeshev

(No) Comments: Post a response

Testing Private Methods in Java

Posted: August 19th, 2011 | Author: | Filed under: General

Java 5 provides vargargs API that allows to test private methods in a very concise way. Here is how.

Yesterday, during a meetup at Loopt, a question of an API for testing private methods was brought up. I used to use JUnit add-on PrivateAccessor [1] when I was testing private methods. The problem was that applying PrivateAccessor produced prohibitively verbose code, so you had to think really hard to understand what the test was doing.

invoke() with varargs

Luckily, Java 5 provides vargargs API that allows to write really concise code for invoking private methods and return results. Here is the invoke() method that makes use of vargargs. Feel free to use it in your code:

   /**
    * Invokes a private method on an object.
    *
    * @param obj        the object on what to invoke the method.
    * @param methodName the name of the method to invoke.
    * @param parameters a list of parameter
    * @return the result of dispatching the method represented by the object.
    */
   public static <T> T invoke(Object obj, String methodName, Object... parameters) {

      try {

         // Create a list of parameter classes
         final Class[] parameterTypes = new Class[parameters.length];
         for (int i = 0; i < parameters.length; i++) {
            parameterTypes[i] = parameters[i].getClass();
         }

         // Get method
         Class clazz = obj.getClass();
         Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
         method.setAccessible(true);

         // Call method
         return (T)method.invoke(obj, parameters);
      } catch (RuntimeException e) {

         throw e;
      } catch (Exception e) {

         throw new IllegalArgumentException(e);
      }
   }

Complete Example

Below is a complete JUnit tests that tests StringBuilder’s private method append(). Notice how neatly the invocation of append() fits into a short single line:

import java.lang.reflect.Method;
import junit.framework.TestCase;

public final class StringBuilderTest extends TestCase {


   /**
    * Object under test
    */
   private StringBuilder object;


   /**
    * Tests String's private method 'append(StringBuilder sb)'.
    */
   public void testAppend() {
      
      StringBuilder toAppend = new StringBuilder("Test");
      StringBuilder result = invoke(object, "append", toAppend);
      assertEquals("Test", result.toString());
   }


   /**
    * Invokes a private method on an object.
    *
    * @param obj        the object on what to invoke the method.
    * @param methodName the name of the method to invoke.
    * @param parameters a list of parameter
    * @return the result of dispatching the method represented by the object.
    */
   public static <T> T invoke(Object obj, String methodName, Object... parameters) {

      try {

         // Create a list of parameter classes
         final Class[] parameterTypes = new Class[parameters.length];
         for (int i = 0; i < parameters.length; i++) {
            parameterTypes[i] = parameters[i].getClass();
         }

         // Get method
         Class clazz = obj.getClass();
         Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
         method.setAccessible(true);

         // Call method
         return (T)method.invoke(obj, parameters);
      } catch (RuntimeException e) {

         throw e;
      } catch (Exception e) {

         throw new IllegalArgumentException(e);
      }
   }


   public void setUp() throws Exception {

      super.setUp();

      object = new StringBuilder(10);
   }
}

Making invoke() reusable

To make invoke() reusable, I suggest to move it to a separate utility class or at least to create a super class for all your tests that extends junit.TestCase and move invoke() there.

Regards,

Slava Imeshev

References

1. JUnit Add-On PrivateAccessor

(7) Comments: Post a response