Posted: August 21st, 2011 |
Author: simeshev |
Filed under: Distributed Caching Good news: We’ve just added support for per-select caching for MyBatis to our open source 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:
- Per-select MyBatis caches
- Ability to turn off invalidation
- Ability to turn off namespace cache
- Cache templates for select caches
For more information and examples check Cacheonix documentation: Configuring MyBatis Cache Adapter.
Enjoy!
Regards,
Slava Imeshev
Cacheonix | Reliable Distributed Java Cache
(No) Comments: Post a response
Posted: August 19th, 2011 |
Author: simeshev |
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
Cacheonix: Reliable Distributed Java Cache
References
1. JUnit Add-On PrivateAccessor
(8) Comments: Post a response