I recently got an request from customer that they want to invalidate the data in OSB ResultCache. As there is no way that we can create Key to invalidate the data, best way we can take is using filter. Here is the snippet of the code.
extern "C" void invalidate(char* key) {
try {
String::View vsCacheName = "/osb/service/ResultCache";
NamedCache::Handle hCache = CacheFactory::getCache(vsCacheName);
ValueExtractor::Handle hExtractor = KeyExtractor::create(ReflectionExtractor::create("getToken"));
Filter::View vEqualsFilter = EqualsFilter::create(hExtractor, String::create(key));
hCache->invokeAll(vEqualsFilter, ConditionalRemove::create(AlwaysFilter::getInstance(),true));
} catch (const std::exception& e) {
std::cerr << "error: " << e.what() << std::endl;
}
}
One issue here is that we cannot specify which result of BusinessService should be invalidated. If two BusinessServices happen to have same token, This will remove both of them which sometimes is not desirable. Also, Index is not in place, so if size of cache is huge, we would expect the performance issue.Currently, I'm not aware of any way to make Key class. I tried making it by myself, but somehow, the one I make and generated by OSB is different.so I ended up making my own ResultCache logic to achieve this purpose.
--
public class ResultCacheHelper {
private static String CACHE_NAME = "dist-test";
public static void put(String key, org.apache.xmlbeans.XmlObject value) throws IOException {
NamedCache cache = CacheFactory.getCache(CACHE_NAME);
cache.put(key, serialize(value));
CacheFactory.log("Cache Key : " + key + " is put in Cache!:" + serialize(value).toString());
}
public static org.apache.xmlbeans.XmlObject get(String key) throws IOException, ClassNotFoundException, XmlException {
XmlObject result;
NamedCache cache = CacheFactory.getCache(CACHE_NAME);
byte[] bytes = (byte[]) cache.get(key);
if(bytes == null) {
String xmlNull = "<cache xmlns=\"http://com.oracle.demoapp.ws/\">null</cache>";
result = org.apache.xmlbeans.XmlObject.Factory.parse(xmlNull);
CacheFactory.log("Cache Key : " + key + " is not found in Cache!");
} else {
result = (org.apache.xmlbeans.XmlObject)deserialize(bytes, Thread.currentThread().getContextClassLoader());
CacheFactory.log("Cache Key : " + key + " is found in Cache!:"+result.toString());
}
return result;
}
protected static Object deserialize(byte[] bytes, final ClassLoader cl)
throws IOException, ClassNotFoundException {
ObjectInputStream ois = null;
try {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais) {
protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException {
return Class.forName(desc.getName(), false, cl);
}
};
return ois.readObject();
} finally {
if (ois != null)
ois.close();
}
}
protected static byte[] serialize(Object object) throws IOException {
ObjectOutputStream oos = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
return baos.toByteArray();
} finally {
if (oos != null)
oos.close();
}
}
}
--
Now I can just simply invalidate the cache
String::View deleteKey = key;
String::View vsCacheName = "dist-test";
NamedCache::Handle hCache = CacheFactory::getCache(vsCacheName);
hCache->remove(deleteKey);
I believe that OSB invalidation feature will be added in near future.